2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
29 extern enum protocol_types Protocol;
30 extern uint32 global_client_caps;
32 #define get_file_size(sbuf) ((sbuf).st_size)
33 #define DIR_ENTRY_SAFETY_MARGIN 4096
35 static char *store_file_unix_basic(connection_struct *conn,
38 const SMB_STRUCT_STAT *psbuf);
40 static char *store_file_unix_basic_info2(connection_struct *conn,
43 const SMB_STRUCT_STAT *psbuf);
45 /********************************************************************
46 Roundup a value to the nearest allocation roundup size boundary.
47 Only do this for Windows clients.
48 ********************************************************************/
50 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
52 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
54 /* Only roundup for Windows clients. */
55 enum remote_arch_types ra_type = get_remote_arch();
56 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
57 val = SMB_ROUNDUP(val,rval);
62 /********************************************************************
63 Given a stat buffer return the allocated size on disk, taking into
65 ********************************************************************/
67 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
71 if(S_ISDIR(sbuf->st_mode)) {
75 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
76 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
78 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
81 if (fsp && fsp->initial_allocation_size)
82 ret = MAX(ret,fsp->initial_allocation_size);
84 return smb_roundup(conn, ret);
87 /****************************************************************************
88 Utility functions for dealing with extended attributes.
89 ****************************************************************************/
91 /****************************************************************************
92 Refuse to allow clients to overwrite our private xattrs.
93 ****************************************************************************/
95 static bool samba_private_attr_name(const char *unix_ea_name)
97 static const char *prohibited_ea_names[] = {
98 SAMBA_POSIX_INHERITANCE_EA_NAME,
99 SAMBA_XATTR_DOS_ATTRIB,
105 for (i = 0; prohibited_ea_names[i]; i++) {
106 if (strequal( prohibited_ea_names[i], unix_ea_name))
109 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
110 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
116 /****************************************************************************
117 Get one EA value. Fill in a struct ea_struct.
118 ****************************************************************************/
120 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
121 files_struct *fsp, const char *fname,
122 const char *ea_name, struct ea_struct *pea)
124 /* Get the value of this xattr. Max size is 64k. */
125 size_t attr_size = 256;
131 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
133 return NT_STATUS_NO_MEMORY;
136 if (fsp && fsp->fh->fd != -1) {
137 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
139 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
142 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
148 return map_nt_error_from_unix(errno);
151 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
152 dump_data(10, (uint8 *)val, sizeret);
155 if (strnequal(ea_name, "user.", 5)) {
156 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
158 pea->name = talloc_strdup(mem_ctx, ea_name);
160 if (pea->name == NULL) {
162 return NT_STATUS_NO_MEMORY;
164 pea->value.data = (unsigned char *)val;
165 pea->value.length = (size_t)sizeret;
169 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
170 files_struct *fsp, const char *fname,
171 char ***pnames, size_t *pnum_names)
173 /* Get a list of all xattrs. Max namesize is 64k. */
174 size_t ea_namelist_size = 1024;
175 char *ea_namelist = NULL;
180 ssize_t sizeret = -1;
182 if (!lp_ea_support(SNUM(conn))) {
189 * TALLOC the result early to get the talloc hierarchy right.
192 names = TALLOC_ARRAY(mem_ctx, char *, 1);
194 DEBUG(0, ("talloc failed\n"));
195 return NT_STATUS_NO_MEMORY;
198 while (ea_namelist_size <= 65536) {
200 ea_namelist = TALLOC_REALLOC_ARRAY(
201 names, ea_namelist, char, ea_namelist_size);
202 if (ea_namelist == NULL) {
203 DEBUG(0, ("talloc failed\n"));
205 return NT_STATUS_NO_MEMORY;
208 if (fsp && fsp->fh->fd != -1) {
209 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
212 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
216 if ((sizeret == -1) && (errno == ERANGE)) {
217 ea_namelist_size *= 2;
226 return map_nt_error_from_unix(errno);
229 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
230 (unsigned int)sizeret));
240 * Ensure the result is 0-terminated
243 if (ea_namelist[sizeret-1] != '\0') {
245 return NT_STATUS_INTERNAL_ERROR;
253 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
257 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
259 DEBUG(0, ("talloc failed\n"));
261 return NT_STATUS_NO_MEMORY;
267 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
268 names[num_names++] = p;
272 *pnum_names = num_names;
276 /****************************************************************************
277 Return a linked list of the total EA's. Plus the total size
278 ****************************************************************************/
280 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
281 const char *fname, size_t *pea_total_len)
283 /* Get a list of all xattrs. Max namesize is 64k. */
286 struct ea_list *ea_list_head = NULL;
291 if (!lp_ea_support(SNUM(conn))) {
295 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
298 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
302 for (i=0; i<num_names; i++) {
303 struct ea_list *listp;
306 if (strnequal(names[i], "system.", 7)
307 || samba_private_attr_name(names[i]))
310 listp = TALLOC_P(mem_ctx, struct ea_list);
315 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
321 push_ascii_fstring(dos_ea_name, listp->ea.name);
324 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
326 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
327 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
328 (unsigned int)listp->ea.value.length));
330 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
334 /* Add on 4 for total length. */
335 if (*pea_total_len) {
339 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
340 (unsigned int)*pea_total_len));
345 /****************************************************************************
346 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
348 ****************************************************************************/
350 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
351 connection_struct *conn, struct ea_list *ea_list)
353 unsigned int ret_data_size = 4;
356 SMB_ASSERT(total_data_size >= 4);
358 if (!lp_ea_support(SNUM(conn))) {
363 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
366 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
367 dos_namelen = strlen(dos_ea_name);
368 if (dos_namelen > 255 || dos_namelen == 0) {
371 if (ea_list->ea.value.length > 65535) {
374 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
378 /* We know we have room. */
379 SCVAL(p,0,ea_list->ea.flags);
380 SCVAL(p,1,dos_namelen);
381 SSVAL(p,2,ea_list->ea.value.length);
382 fstrcpy(p+4, dos_ea_name);
383 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
385 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
386 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
389 ret_data_size = PTR_DIFF(p, pdata);
390 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
391 SIVAL(pdata,0,ret_data_size);
392 return ret_data_size;
395 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
397 size_t total_ea_len = 0;
398 TALLOC_CTX *mem_ctx = NULL;
400 if (!lp_ea_support(SNUM(conn))) {
403 mem_ctx = talloc_tos();
404 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
408 /****************************************************************************
409 Ensure the EA name is case insensitive by matching any existing EA name.
410 ****************************************************************************/
412 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
415 TALLOC_CTX *mem_ctx = talloc_tos();
416 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
418 for (; ea_list; ea_list = ea_list->next) {
419 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
420 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
421 &unix_ea_name[5], ea_list->ea.name));
422 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
428 /****************************************************************************
429 Set or delete an extended attribute.
430 ****************************************************************************/
432 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
434 if (!lp_ea_support(SNUM(conn))) {
435 return NT_STATUS_EAS_NOT_SUPPORTED;
438 for (;ea_list; ea_list = ea_list->next) {
440 fstring unix_ea_name;
442 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
443 fstrcat(unix_ea_name, ea_list->ea.name);
445 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
447 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
449 if (samba_private_attr_name(unix_ea_name)) {
450 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
451 return NT_STATUS_ACCESS_DENIED;
454 if (ea_list->ea.value.length == 0) {
455 /* Remove the attribute. */
456 if (fsp && (fsp->fh->fd != -1)) {
457 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
458 unix_ea_name, fsp->fsp_name));
459 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
461 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
462 unix_ea_name, fname));
463 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
466 /* Removing a non existent attribute always succeeds. */
467 if (ret == -1 && errno == ENOATTR) {
468 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
474 if (fsp && (fsp->fh->fd != -1)) {
475 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
476 unix_ea_name, fsp->fsp_name));
477 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
478 ea_list->ea.value.data, ea_list->ea.value.length, 0);
480 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
481 unix_ea_name, fname));
482 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
483 ea_list->ea.value.data, ea_list->ea.value.length, 0);
489 if (errno == ENOTSUP) {
490 return NT_STATUS_EAS_NOT_SUPPORTED;
493 return map_nt_error_from_unix(errno);
499 /****************************************************************************
500 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
501 ****************************************************************************/
503 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
505 struct ea_list *ea_list_head = NULL;
506 size_t converted_size, offset = 0;
508 while (offset + 2 < data_size) {
509 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
510 unsigned int namelen = CVAL(pdata,offset);
512 offset++; /* Go past the namelen byte. */
514 /* integer wrap paranioa. */
515 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
516 (offset > data_size) || (namelen > data_size) ||
517 (offset + namelen >= data_size)) {
520 /* Ensure the name is null terminated. */
521 if (pdata[offset + namelen] != '\0') {
524 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
526 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
527 "failed: %s", strerror(errno)));
533 offset += (namelen + 1); /* Go past the name + terminating zero. */
534 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
535 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
541 /****************************************************************************
542 Read one EA list entry from the buffer.
543 ****************************************************************************/
545 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
547 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
549 unsigned int namelen;
550 size_t converted_size;
560 eal->ea.flags = CVAL(pdata,0);
561 namelen = CVAL(pdata,1);
562 val_len = SVAL(pdata,2);
564 if (4 + namelen + 1 + val_len > data_size) {
568 /* Ensure the name is null terminated. */
569 if (pdata[namelen + 4] != '\0') {
572 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
573 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
580 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
581 if (!eal->ea.value.data) {
585 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
587 /* Ensure we're null terminated just in case we print the value. */
588 eal->ea.value.data[val_len] = '\0';
589 /* But don't count the null. */
590 eal->ea.value.length--;
593 *pbytes_used = 4 + namelen + 1 + val_len;
596 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
597 dump_data(10, eal->ea.value.data, eal->ea.value.length);
602 /****************************************************************************
603 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
604 ****************************************************************************/
606 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
608 struct ea_list *ea_list_head = NULL;
610 size_t bytes_used = 0;
612 while (offset < data_size) {
613 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
619 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
620 offset += bytes_used;
626 /****************************************************************************
627 Count the total EA size needed.
628 ****************************************************************************/
630 static size_t ea_list_size(struct ea_list *ealist)
633 struct ea_list *listp;
636 for (listp = ealist; listp; listp = listp->next) {
637 push_ascii_fstring(dos_ea_name, listp->ea.name);
638 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
640 /* Add on 4 for total length. */
648 /****************************************************************************
649 Return a union of EA's from a file list and a list of names.
650 The TALLOC context for the two lists *MUST* be identical as we steal
651 memory from one list to add to another. JRA.
652 ****************************************************************************/
654 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
656 struct ea_list *nlistp, *flistp;
658 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
659 for (flistp = file_list; flistp; flistp = flistp->next) {
660 if (strequal(nlistp->ea.name, flistp->ea.name)) {
666 /* Copy the data from this entry. */
667 nlistp->ea.flags = flistp->ea.flags;
668 nlistp->ea.value = flistp->ea.value;
671 nlistp->ea.flags = 0;
672 ZERO_STRUCT(nlistp->ea.value);
676 *total_ea_len = ea_list_size(name_list);
680 /****************************************************************************
681 Send the required number of replies back.
682 We assume all fields other than the data fields are
683 set correctly for the type of call.
684 HACK ! Always assumes smb_setup field is zero.
685 ****************************************************************************/
687 void send_trans2_replies(connection_struct *conn,
688 struct smb_request *req,
695 /* As we are using a protocol > LANMAN1 then the max_send
696 variable must have been set in the sessetupX call.
697 This takes precedence over the max_xmit field in the
698 global struct. These different max_xmit variables should
699 be merged as this is now too confusing */
701 int data_to_send = datasize;
702 int params_to_send = paramsize;
704 const char *pp = params;
705 const char *pd = pdata;
706 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
707 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
708 int data_alignment_offset = 0;
709 bool overflow = False;
711 /* Modify the data_to_send and datasize and set the error if
712 we're trying to send more than max_data_bytes. We still send
713 the part of the packet(s) that fit. Strange, but needed
716 if (max_data_bytes > 0 && datasize > max_data_bytes) {
717 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
718 max_data_bytes, datasize ));
719 datasize = data_to_send = max_data_bytes;
723 /* If there genuinely are no parameters or data to send just send the empty packet */
725 if(params_to_send == 0 && data_to_send == 0) {
726 reply_outbuf(req, 10, 0);
727 show_msg((char *)req->outbuf);
731 /* When sending params and data ensure that both are nicely aligned */
732 /* Only do this alignment when there is also data to send - else
733 can cause NT redirector problems. */
735 if (((params_to_send % 4) != 0) && (data_to_send != 0))
736 data_alignment_offset = 4 - (params_to_send % 4);
738 /* Space is bufsize minus Netbios over TCP header minus SMB header */
739 /* The alignment_offset is to align the param bytes on an even byte
740 boundary. NT 4.0 Beta needs this to work correctly. */
742 useable_space = max_send - (smb_size
745 + data_alignment_offset);
747 if (useable_space < 0) {
748 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
749 "= %d!!!", useable_space));
750 exit_server_cleanly("send_trans2_replies: Not enough space");
753 while (params_to_send || data_to_send) {
754 /* Calculate whether we will totally or partially fill this packet */
756 total_sent_thistime = params_to_send + data_to_send;
758 /* We can never send more than useable_space */
760 * Note that 'useable_space' does not include the alignment offsets,
761 * but we must include the alignment offsets in the calculation of
762 * the length of the data we send over the wire, as the alignment offsets
763 * are sent here. Fix from Marc_Jacobsen@hp.com.
766 total_sent_thistime = MIN(total_sent_thistime, useable_space);
768 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
769 + data_alignment_offset);
771 /* Set total params and data to be sent */
772 SSVAL(req->outbuf,smb_tprcnt,paramsize);
773 SSVAL(req->outbuf,smb_tdrcnt,datasize);
775 /* Calculate how many parameters and data we can fit into
776 * this packet. Parameters get precedence
779 params_sent_thistime = MIN(params_to_send,useable_space);
780 data_sent_thistime = useable_space - params_sent_thistime;
781 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
783 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
785 /* smb_proff is the offset from the start of the SMB header to the
786 parameter bytes, however the first 4 bytes of outbuf are
787 the Netbios over TCP header. Thus use smb_base() to subtract
788 them from the calculation */
790 SSVAL(req->outbuf,smb_proff,
791 ((smb_buf(req->outbuf)+alignment_offset)
792 - smb_base(req->outbuf)));
794 if(params_sent_thistime == 0)
795 SSVAL(req->outbuf,smb_prdisp,0);
797 /* Absolute displacement of param bytes sent in this packet */
798 SSVAL(req->outbuf,smb_prdisp,pp - params);
800 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
801 if(data_sent_thistime == 0) {
802 SSVAL(req->outbuf,smb_droff,0);
803 SSVAL(req->outbuf,smb_drdisp, 0);
805 /* The offset of the data bytes is the offset of the
806 parameter bytes plus the number of parameters being sent this time */
807 SSVAL(req->outbuf, smb_droff,
808 ((smb_buf(req->outbuf)+alignment_offset)
809 - smb_base(req->outbuf))
810 + params_sent_thistime + data_alignment_offset);
811 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
814 /* Initialize the padding for alignment */
816 if (alignment_offset != 0) {
817 memset(smb_buf(req->outbuf), 0, alignment_offset);
820 /* Copy the param bytes into the packet */
822 if(params_sent_thistime) {
823 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
824 params_sent_thistime);
827 /* Copy in the data bytes */
828 if(data_sent_thistime) {
829 if (data_alignment_offset != 0) {
830 memset((smb_buf(req->outbuf)+alignment_offset+
831 params_sent_thistime), 0,
832 data_alignment_offset);
834 memcpy(smb_buf(req->outbuf)+alignment_offset
835 +params_sent_thistime+data_alignment_offset,
836 pd,data_sent_thistime);
839 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
840 params_sent_thistime, data_sent_thistime, useable_space));
841 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
842 params_to_send, data_to_send, paramsize, datasize));
845 error_packet_set((char *)req->outbuf,
846 ERRDOS,ERRbufferoverflow,
847 STATUS_BUFFER_OVERFLOW,
851 /* Send the packet */
852 show_msg((char *)req->outbuf);
853 if (!srv_send_smb(smbd_server_fd(),
855 IS_CONN_ENCRYPTED(conn)))
856 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
858 TALLOC_FREE(req->outbuf);
860 pp += params_sent_thistime;
861 pd += data_sent_thistime;
863 params_to_send -= params_sent_thistime;
864 data_to_send -= data_sent_thistime;
867 if(params_to_send < 0 || data_to_send < 0) {
868 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
869 params_to_send, data_to_send));
877 /****************************************************************************
878 Reply to a TRANSACT2_OPEN.
879 ****************************************************************************/
881 static void call_trans2open(connection_struct *conn,
882 struct smb_request *req,
883 char **pparams, int total_params,
884 char **ppdata, int total_data,
885 unsigned int max_data_bytes)
887 char *params = *pparams;
888 char *pdata = *ppdata;
893 bool return_additional_info;
904 SMB_STRUCT_STAT sbuf;
907 struct ea_list *ea_list = NULL;
912 uint32 create_disposition;
913 uint32 create_options = 0;
914 TALLOC_CTX *ctx = talloc_tos();
917 * Ensure we have enough parameters to perform the operation.
920 if (total_params < 29) {
921 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
925 flags = SVAL(params, 0);
926 deny_mode = SVAL(params, 2);
927 open_attr = SVAL(params,6);
928 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
929 if (oplock_request) {
930 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
934 return_additional_info = BITSETW(params,0);
935 open_sattr = SVAL(params, 4);
936 open_time = make_unix_date3(params+8);
938 open_ofun = SVAL(params,12);
939 open_size = IVAL(params,14);
943 reply_doserror(req, ERRSRV, ERRaccess);
947 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
948 total_params - 28, STR_TERMINATE,
950 if (!NT_STATUS_IS_OK(status)) {
951 reply_nterror(req, status);
955 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
956 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
957 (unsigned int)open_ofun, open_size));
959 if (open_ofun == 0) {
960 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
964 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
969 reply_doserror(req, ERRDOS, ERRbadaccess);
973 /* Any data in this call is an EA list. */
974 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
975 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
979 if (total_data != 4) {
980 if (total_data < 10) {
981 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
985 if (IVAL(pdata,0) > total_data) {
986 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
987 IVAL(pdata,0), (unsigned int)total_data));
988 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
992 ea_list = read_ea_list(talloc_tos(), pdata + 4,
995 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
998 } else if (IVAL(pdata,0) != 4) {
999 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1003 status = create_file(conn, /* conn */
1005 0, /* root_dir_fid */
1007 access_mask, /* access_mask */
1008 share_mode, /* share_access */
1009 create_disposition, /* create_disposition*/
1010 create_options, /* create_options */
1011 open_attr, /* file_attributes */
1012 oplock_request, /* oplock_request */
1013 open_size, /* allocation_size */
1015 ea_list, /* ea_list */
1017 &smb_action, /* pinfo */
1020 if (!NT_STATUS_IS_OK(status)) {
1021 if (open_was_deferred(req->mid)) {
1022 /* We have re-scheduled this call. */
1025 reply_openerror(req, status);
1029 size = get_file_size(sbuf);
1030 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1031 mtime = sbuf.st_mtime;
1032 inode = sbuf.st_ino;
1034 close_file(fsp,ERROR_CLOSE);
1035 reply_doserror(req, ERRDOS,ERRnoaccess);
1039 /* Realloc the size of parameters and data we will return */
1040 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1041 if(*pparams == NULL ) {
1042 reply_nterror(req, NT_STATUS_NO_MEMORY);
1047 SSVAL(params,0,fsp->fnum);
1048 SSVAL(params,2,fattr);
1049 srv_put_dos_date2(params,4, mtime);
1050 SIVAL(params,8, (uint32)size);
1051 SSVAL(params,12,deny_mode);
1052 SSVAL(params,14,0); /* open_type - file or directory. */
1053 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1055 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1056 smb_action |= EXTENDED_OPLOCK_GRANTED;
1059 SSVAL(params,18,smb_action);
1062 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1064 SIVAL(params,20,inode);
1065 SSVAL(params,24,0); /* Padding. */
1067 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1068 SIVAL(params, 26, ea_size);
1070 SIVAL(params, 26, 0);
1073 /* Send the required number of replies */
1074 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1077 /*********************************************************
1078 Routine to check if a given string matches exactly.
1079 as a special case a mask of "." does NOT match. That
1080 is required for correct wildcard semantics
1081 Case can be significant or not.
1082 **********************************************************/
1084 static bool exact_match(connection_struct *conn,
1088 if (mask[0] == '.' && mask[1] == 0)
1090 if (conn->case_sensitive)
1091 return strcmp(str,mask)==0;
1092 if (StrCaseCmp(str,mask) != 0) {
1095 if (dptr_has_wild(conn->dirptr)) {
1101 /****************************************************************************
1102 Return the filetype for UNIX extensions.
1103 ****************************************************************************/
1105 static uint32 unix_filetype(mode_t mode)
1108 return UNIX_TYPE_FILE;
1109 else if(S_ISDIR(mode))
1110 return UNIX_TYPE_DIR;
1112 else if(S_ISLNK(mode))
1113 return UNIX_TYPE_SYMLINK;
1116 else if(S_ISCHR(mode))
1117 return UNIX_TYPE_CHARDEV;
1120 else if(S_ISBLK(mode))
1121 return UNIX_TYPE_BLKDEV;
1124 else if(S_ISFIFO(mode))
1125 return UNIX_TYPE_FIFO;
1128 else if(S_ISSOCK(mode))
1129 return UNIX_TYPE_SOCKET;
1132 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1133 return UNIX_TYPE_UNKNOWN;
1136 /****************************************************************************
1137 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1138 ****************************************************************************/
1140 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1142 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1143 SMB_STRUCT_STAT *psbuf,
1145 enum perm_type ptype,
1150 if (perms == SMB_MODE_NO_CHANGE) {
1151 if (!VALID_STAT(*psbuf)) {
1152 return NT_STATUS_INVALID_PARAMETER;
1154 *ret_perms = psbuf->st_mode;
1155 return NT_STATUS_OK;
1159 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1160 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1161 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1162 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1163 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1164 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1165 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1166 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1167 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1169 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1172 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1175 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1180 /* Apply mode mask */
1181 ret &= lp_create_mask(SNUM(conn));
1182 /* Add in force bits */
1183 ret |= lp_force_create_mode(SNUM(conn));
1186 ret &= lp_dir_mask(SNUM(conn));
1187 /* Add in force bits */
1188 ret |= lp_force_dir_mode(SNUM(conn));
1190 case PERM_EXISTING_FILE:
1191 /* Apply mode mask */
1192 ret &= lp_security_mask(SNUM(conn));
1193 /* Add in force bits */
1194 ret |= lp_force_security_mode(SNUM(conn));
1196 case PERM_EXISTING_DIR:
1197 /* Apply mode mask */
1198 ret &= lp_dir_security_mask(SNUM(conn));
1199 /* Add in force bits */
1200 ret |= lp_force_dir_security_mode(SNUM(conn));
1205 return NT_STATUS_OK;
1208 /****************************************************************************
1209 Needed to show the msdfs symlinks as directories. Modifies psbuf
1210 to be a directory if it's a msdfs link.
1211 ****************************************************************************/
1213 static bool check_msdfs_link(connection_struct *conn,
1214 const char *pathname,
1215 SMB_STRUCT_STAT *psbuf)
1217 int saved_errno = errno;
1218 if(lp_host_msdfs() &&
1219 lp_msdfs_root(SNUM(conn)) &&
1220 is_msdfs_link(conn, pathname, psbuf)) {
1222 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1225 psbuf->st_mode = (psbuf->st_mode & 0xFFF) | S_IFDIR;
1226 errno = saved_errno;
1229 errno = saved_errno;
1234 /****************************************************************************
1235 Get a level dependent lanman2 dir entry.
1236 ****************************************************************************/
1238 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1239 connection_struct *conn,
1241 const char *path_mask,
1244 int requires_resume_key,
1250 int space_remaining,
1252 bool *got_exact_match,
1253 int *last_entry_off,
1254 struct ea_list *name_list)
1258 SMB_STRUCT_STAT sbuf;
1259 const char *mask = NULL;
1260 char *pathreal = NULL;
1261 const char *fname = NULL;
1262 char *p, *q, *pdata = *ppdata;
1266 SMB_OFF_T file_size = 0;
1267 SMB_BIG_UINT allocation_size = 0;
1269 struct timespec mdate_ts, adate_ts, create_date_ts;
1270 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1272 char *last_entry_ptr;
1274 uint32 nt_extmode; /* Used for NT connections instead of mode */
1275 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1276 bool check_mangled_names = lp_manglednames(conn->params);
1277 char mangled_name[13]; /* mangled 8.3 name. */
1279 *out_of_space = False;
1280 *got_exact_match = False;
1282 ZERO_STRUCT(mdate_ts);
1283 ZERO_STRUCT(adate_ts);
1284 ZERO_STRUCT(create_date_ts);
1286 if (!conn->dirptr) {
1290 p = strrchr_m(path_mask,'/');
1293 mask = talloc_strdup(ctx,"*.*");
1303 bool ms_dfs_link = False;
1305 /* Needed if we run out of space */
1306 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1307 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1310 * Due to bugs in NT client redirectors we are not using
1311 * resume keys any more - set them to zero.
1312 * Check out the related comments in findfirst/findnext.
1318 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1319 (long)conn->dirptr,curr_dirpos));
1326 * fname may get mangled, dname is never mangled.
1327 * Whenever we're accessing the filesystem we use
1328 * pathreal which is composed from dname.
1334 /* Mangle fname if it's an illegal name. */
1335 if (mangle_must_mangle(dname,conn->params)) {
1336 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1337 continue; /* Error - couldn't mangle. */
1339 fname = mangled_name;
1342 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1343 got_match = mask_match(fname, mask, conn->case_sensitive);
1346 if(!got_match && check_mangled_names &&
1347 !mangle_is_8_3(fname, False, conn->params)) {
1349 * It turns out that NT matches wildcards against
1350 * both long *and* short names. This may explain some
1351 * of the wildcard wierdness from old DOS clients
1352 * that some people have been seeing.... JRA.
1354 /* Force the mangling into 8.3. */
1355 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1356 continue; /* Error - couldn't mangle. */
1359 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1360 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1365 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1367 if (dont_descend && !isdots) {
1373 pathreal = talloc_asprintf(ctx,
1378 pathreal = talloc_asprintf(ctx,
1388 if (INFO_LEVEL_IS_UNIX(info_level)) {
1389 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1390 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1391 pathreal,strerror(errno)));
1392 TALLOC_FREE(pathreal);
1395 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1396 /* Needed to show the msdfs symlinks as
1399 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1401 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1402 pathreal,strerror(errno)));
1403 TALLOC_FREE(pathreal);
1409 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1411 mode = dos_mode(conn,pathreal,&sbuf);
1414 if (!dir_check_ftype(conn,mode,dirtype)) {
1415 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1416 TALLOC_FREE(pathreal);
1420 if (!(mode & aDIR)) {
1421 file_size = get_file_size(sbuf);
1423 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1425 mdate_ts = get_mtimespec(&sbuf);
1426 adate_ts = get_atimespec(&sbuf);
1427 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1429 if (ask_sharemode) {
1430 struct timespec write_time_ts;
1431 struct file_id fileid;
1433 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1434 get_file_infos(fileid, NULL, &write_time_ts);
1435 if (!null_timespec(write_time_ts)) {
1436 mdate_ts = write_time_ts;
1440 if (lp_dos_filetime_resolution(SNUM(conn))) {
1441 dos_filetime_timespec(&create_date_ts);
1442 dos_filetime_timespec(&mdate_ts);
1443 dos_filetime_timespec(&adate_ts);
1446 create_date = convert_timespec_to_time_t(create_date_ts);
1447 mdate = convert_timespec_to_time_t(mdate_ts);
1448 adate = convert_timespec_to_time_t(adate_ts);
1450 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1454 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1461 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1463 switch (info_level) {
1464 case SMB_FIND_INFO_STANDARD:
1465 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1466 if(requires_resume_key) {
1470 srv_put_dos_date2(p,0,create_date);
1471 srv_put_dos_date2(p,4,adate);
1472 srv_put_dos_date2(p,8,mdate);
1473 SIVAL(p,12,(uint32)file_size);
1474 SIVAL(p,16,(uint32)allocation_size);
1478 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1479 p += ucs2_align(base_data, p, 0);
1481 len = srvstr_push(base_data, flags2, p,
1482 fname, PTR_DIFF(end_data, p),
1484 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1486 SCVAL(nameptr, -1, len - 2);
1488 SCVAL(nameptr, -1, 0);
1492 SCVAL(nameptr, -1, len - 1);
1494 SCVAL(nameptr, -1, 0);
1500 case SMB_FIND_EA_SIZE:
1501 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1502 if(requires_resume_key) {
1506 srv_put_dos_date2(p,0,create_date);
1507 srv_put_dos_date2(p,4,adate);
1508 srv_put_dos_date2(p,8,mdate);
1509 SIVAL(p,12,(uint32)file_size);
1510 SIVAL(p,16,(uint32)allocation_size);
1513 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1514 SIVAL(p,22,ea_size); /* Extended attributes */
1518 len = srvstr_push(base_data, flags2,
1519 p, fname, PTR_DIFF(end_data, p),
1520 STR_TERMINATE | STR_NOALIGN);
1521 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1534 SCVAL(nameptr,0,len);
1536 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1539 case SMB_FIND_EA_LIST:
1541 struct ea_list *file_list = NULL;
1544 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1548 if(requires_resume_key) {
1552 srv_put_dos_date2(p,0,create_date);
1553 srv_put_dos_date2(p,4,adate);
1554 srv_put_dos_date2(p,8,mdate);
1555 SIVAL(p,12,(uint32)file_size);
1556 SIVAL(p,16,(uint32)allocation_size);
1558 p += 22; /* p now points to the EA area. */
1560 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1561 name_list = ea_list_union(name_list, file_list, &ea_len);
1563 /* We need to determine if this entry will fit in the space available. */
1564 /* Max string size is 255 bytes. */
1565 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1566 /* Move the dirptr back to prev_dirpos */
1567 dptr_SeekDir(conn->dirptr, prev_dirpos);
1568 *out_of_space = True;
1569 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1570 return False; /* Not finished - just out of space */
1573 /* Push the ea_data followed by the name. */
1574 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1576 len = srvstr_push(base_data, flags2,
1577 p + 1, fname, PTR_DIFF(end_data, p+1),
1578 STR_TERMINATE | STR_NOALIGN);
1579 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1592 SCVAL(nameptr,0,len);
1594 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1598 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1599 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1600 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1602 SIVAL(p,0,reskey); p += 4;
1603 put_long_date_timespec(p,create_date_ts); p += 8;
1604 put_long_date_timespec(p,adate_ts); p += 8;
1605 put_long_date_timespec(p,mdate_ts); p += 8;
1606 put_long_date_timespec(p,mdate_ts); p += 8;
1607 SOFF_T(p,0,file_size); p += 8;
1608 SOFF_T(p,0,allocation_size); p += 8;
1609 SIVAL(p,0,nt_extmode); p += 4;
1610 q = p; p += 4; /* q is placeholder for name length. */
1612 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1613 SIVAL(p,0,ea_size); /* Extended attributes */
1616 /* Clear the short name buffer. This is
1617 * IMPORTANT as not doing so will trigger
1618 * a Win2k client bug. JRA.
1620 if (!was_8_3 && check_mangled_names) {
1621 if (!name_to_8_3(fname,mangled_name,True,
1623 /* Error - mangle failed ! */
1624 memset(mangled_name,'\0',12);
1626 mangled_name[12] = 0;
1627 len = srvstr_push(base_data, flags2,
1628 p+2, mangled_name, 24,
1629 STR_UPPER|STR_UNICODE);
1631 memset(p + 2 + len,'\0',24 - len);
1638 len = srvstr_push(base_data, flags2, p,
1639 fname, PTR_DIFF(end_data, p),
1640 STR_TERMINATE_ASCII);
1643 SIVAL(p,0,0); /* Ensure any padding is null. */
1644 len = PTR_DIFF(p, pdata);
1645 len = (len + 3) & ~3;
1650 case SMB_FIND_FILE_DIRECTORY_INFO:
1651 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1653 SIVAL(p,0,reskey); p += 4;
1654 put_long_date_timespec(p,create_date_ts); p += 8;
1655 put_long_date_timespec(p,adate_ts); p += 8;
1656 put_long_date_timespec(p,mdate_ts); p += 8;
1657 put_long_date_timespec(p,mdate_ts); p += 8;
1658 SOFF_T(p,0,file_size); p += 8;
1659 SOFF_T(p,0,allocation_size); p += 8;
1660 SIVAL(p,0,nt_extmode); p += 4;
1661 len = srvstr_push(base_data, flags2,
1662 p + 4, fname, PTR_DIFF(end_data, p+4),
1663 STR_TERMINATE_ASCII);
1666 SIVAL(p,0,0); /* Ensure any padding is null. */
1667 len = PTR_DIFF(p, pdata);
1668 len = (len + 3) & ~3;
1673 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1674 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1676 SIVAL(p,0,reskey); p += 4;
1677 put_long_date_timespec(p,create_date_ts); p += 8;
1678 put_long_date_timespec(p,adate_ts); p += 8;
1679 put_long_date_timespec(p,mdate_ts); p += 8;
1680 put_long_date_timespec(p,mdate_ts); p += 8;
1681 SOFF_T(p,0,file_size); p += 8;
1682 SOFF_T(p,0,allocation_size); p += 8;
1683 SIVAL(p,0,nt_extmode); p += 4;
1684 q = p; p += 4; /* q is placeholder for name length. */
1686 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1687 SIVAL(p,0,ea_size); /* Extended attributes */
1690 len = srvstr_push(base_data, flags2, p,
1691 fname, PTR_DIFF(end_data, p),
1692 STR_TERMINATE_ASCII);
1696 SIVAL(p,0,0); /* Ensure any padding is null. */
1697 len = PTR_DIFF(p, pdata);
1698 len = (len + 3) & ~3;
1703 case SMB_FIND_FILE_NAMES_INFO:
1704 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1706 SIVAL(p,0,reskey); p += 4;
1708 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1709 acl on a dir (tridge) */
1710 len = srvstr_push(base_data, flags2, p,
1711 fname, PTR_DIFF(end_data, p),
1712 STR_TERMINATE_ASCII);
1715 SIVAL(p,0,0); /* Ensure any padding is null. */
1716 len = PTR_DIFF(p, pdata);
1717 len = (len + 3) & ~3;
1722 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1723 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1725 SIVAL(p,0,reskey); p += 4;
1726 put_long_date_timespec(p,create_date_ts); p += 8;
1727 put_long_date_timespec(p,adate_ts); p += 8;
1728 put_long_date_timespec(p,mdate_ts); p += 8;
1729 put_long_date_timespec(p,mdate_ts); p += 8;
1730 SOFF_T(p,0,file_size); p += 8;
1731 SOFF_T(p,0,allocation_size); p += 8;
1732 SIVAL(p,0,nt_extmode); p += 4;
1733 q = p; p += 4; /* q is placeholder for name length. */
1735 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1736 SIVAL(p,0,ea_size); /* Extended attributes */
1739 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1740 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1741 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1742 len = srvstr_push(base_data, flags2, p,
1743 fname, PTR_DIFF(end_data, p),
1744 STR_TERMINATE_ASCII);
1747 SIVAL(p,0,0); /* Ensure any padding is null. */
1748 len = PTR_DIFF(p, pdata);
1749 len = (len + 3) & ~3;
1754 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1755 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1756 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1758 SIVAL(p,0,reskey); p += 4;
1759 put_long_date_timespec(p,create_date_ts); p += 8;
1760 put_long_date_timespec(p,adate_ts); p += 8;
1761 put_long_date_timespec(p,mdate_ts); p += 8;
1762 put_long_date_timespec(p,mdate_ts); p += 8;
1763 SOFF_T(p,0,file_size); p += 8;
1764 SOFF_T(p,0,allocation_size); p += 8;
1765 SIVAL(p,0,nt_extmode); p += 4;
1766 q = p; p += 4; /* q is placeholder for name length */
1768 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1769 SIVAL(p,0,ea_size); /* Extended attributes */
1772 /* Clear the short name buffer. This is
1773 * IMPORTANT as not doing so will trigger
1774 * a Win2k client bug. JRA.
1776 if (!was_8_3 && check_mangled_names) {
1777 if (!name_to_8_3(fname,mangled_name,True,
1779 /* Error - mangle failed ! */
1780 memset(mangled_name,'\0',12);
1782 mangled_name[12] = 0;
1783 len = srvstr_push(base_data, flags2,
1784 p+2, mangled_name, 24,
1785 STR_UPPER|STR_UNICODE);
1788 memset(p + 2 + len,'\0',24 - len);
1795 SSVAL(p,0,0); p += 2; /* Reserved ? */
1796 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1797 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1798 len = srvstr_push(base_data, flags2, p,
1799 fname, PTR_DIFF(end_data, p),
1800 STR_TERMINATE_ASCII);
1803 SIVAL(p,0,0); /* Ensure any padding is null. */
1804 len = PTR_DIFF(p, pdata);
1805 len = (len + 3) & ~3;
1810 /* CIFS UNIX Extension. */
1812 case SMB_FIND_FILE_UNIX:
1813 case SMB_FIND_FILE_UNIX_INFO2:
1815 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1817 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1819 if (info_level == SMB_FIND_FILE_UNIX) {
1820 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1821 p = store_file_unix_basic(conn, p,
1823 len = srvstr_push(base_data, flags2, p,
1824 fname, PTR_DIFF(end_data, p),
1827 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1828 p = store_file_unix_basic_info2(conn, p,
1832 len = srvstr_push(base_data, flags2, p, fname,
1833 PTR_DIFF(end_data, p), 0);
1834 SIVAL(nameptr, 0, len);
1838 SIVAL(p,0,0); /* Ensure any padding is null. */
1840 len = PTR_DIFF(p, pdata);
1841 len = (len + 3) & ~3;
1842 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1844 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1853 if (PTR_DIFF(p,pdata) > space_remaining) {
1854 /* Move the dirptr back to prev_dirpos */
1855 dptr_SeekDir(conn->dirptr, prev_dirpos);
1856 *out_of_space = True;
1857 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1858 return False; /* Not finished - just out of space */
1861 /* Setup the last entry pointer, as an offset from base_data */
1862 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1863 /* Advance the data pointer to the next slot */
1869 /****************************************************************************
1870 Reply to a TRANS2_FINDFIRST.
1871 ****************************************************************************/
1873 static void call_trans2findfirst(connection_struct *conn,
1874 struct smb_request *req,
1875 char **pparams, int total_params,
1876 char **ppdata, int total_data,
1877 unsigned int max_data_bytes)
1879 /* We must be careful here that we don't return more than the
1880 allowed number of data bytes. If this means returning fewer than
1881 maxentries then so be it. We assume that the redirector has
1882 enough room for the fixed number of parameter bytes it has
1884 char *params = *pparams;
1885 char *pdata = *ppdata;
1889 uint16 findfirst_flags;
1890 bool close_after_first;
1892 bool requires_resume_key;
1894 char *directory = NULL;
1895 const char *mask = NULL;
1897 int last_entry_off=0;
1901 bool finished = False;
1902 bool dont_descend = False;
1903 bool out_of_space = False;
1904 int space_remaining;
1905 bool mask_contains_wcard = False;
1906 SMB_STRUCT_STAT sbuf;
1907 struct ea_list *ea_list = NULL;
1908 NTSTATUS ntstatus = NT_STATUS_OK;
1909 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1910 TALLOC_CTX *ctx = talloc_tos();
1912 if (total_params < 13) {
1913 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1917 dirtype = SVAL(params,0);
1918 maxentries = SVAL(params,2);
1919 findfirst_flags = SVAL(params,4);
1920 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1921 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1922 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1923 info_level = SVAL(params,6);
1925 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1926 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1927 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1928 info_level, max_data_bytes));
1931 /* W2K3 seems to treat zero as 1. */
1935 switch (info_level) {
1936 case SMB_FIND_INFO_STANDARD:
1937 case SMB_FIND_EA_SIZE:
1938 case SMB_FIND_EA_LIST:
1939 case SMB_FIND_FILE_DIRECTORY_INFO:
1940 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1941 case SMB_FIND_FILE_NAMES_INFO:
1942 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1943 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1944 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1946 case SMB_FIND_FILE_UNIX:
1947 case SMB_FIND_FILE_UNIX_INFO2:
1948 if (!lp_unix_extensions()) {
1949 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1954 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1958 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1959 params+12, total_params - 12,
1960 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1961 if (!NT_STATUS_IS_OK(ntstatus)) {
1962 reply_nterror(req, ntstatus);
1966 ntstatus = resolve_dfspath_wcard(ctx, conn,
1967 req->flags2 & FLAGS2_DFS_PATHNAMES,
1970 &mask_contains_wcard);
1971 if (!NT_STATUS_IS_OK(ntstatus)) {
1972 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1973 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1974 ERRSRV, ERRbadpath);
1977 reply_nterror(req, ntstatus);
1981 ntstatus = unix_convert(ctx, conn, directory, True, &directory, NULL, &sbuf);
1982 if (!NT_STATUS_IS_OK(ntstatus)) {
1983 reply_nterror(req, ntstatus);
1987 ntstatus = check_name(conn, directory);
1988 if (!NT_STATUS_IS_OK(ntstatus)) {
1989 reply_nterror(req, ntstatus);
1993 p = strrchr_m(directory,'/');
1995 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1996 if((directory[0] == '.') && (directory[1] == '\0')) {
1998 mask_contains_wcard = True;
2002 directory = talloc_strdup(talloc_tos(), "./");
2004 reply_nterror(req, NT_STATUS_NO_MEMORY);
2012 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2014 if (info_level == SMB_FIND_EA_LIST) {
2017 if (total_data < 4) {
2018 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2022 ea_size = IVAL(pdata,0);
2023 if (ea_size != total_data) {
2024 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2025 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2026 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2030 if (!lp_ea_support(SNUM(conn))) {
2031 reply_doserror(req, ERRDOS, ERReasnotsupported);
2035 /* Pull out the list of names. */
2036 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2038 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2043 *ppdata = (char *)SMB_REALLOC(
2044 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2045 if(*ppdata == NULL ) {
2046 reply_nterror(req, NT_STATUS_NO_MEMORY);
2050 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2052 /* Realloc the params space */
2053 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2054 if (*pparams == NULL) {
2055 reply_nterror(req, NT_STATUS_NO_MEMORY);
2060 /* Save the wildcard match and attribs we are using on this directory -
2061 needed as lanman2 assumes these are being saved between calls */
2063 ntstatus = dptr_create(conn,
2069 mask_contains_wcard,
2073 if (!NT_STATUS_IS_OK(ntstatus)) {
2074 reply_nterror(req, ntstatus);
2078 dptr_num = dptr_dnum(conn->dirptr);
2079 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2081 /* We don't need to check for VOL here as this is returned by
2082 a different TRANS2 call. */
2084 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2085 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2086 dont_descend = True;
2089 space_remaining = max_data_bytes;
2090 out_of_space = False;
2092 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2093 bool got_exact_match = False;
2095 /* this is a heuristic to avoid seeking the dirptr except when
2096 absolutely necessary. It allows for a filename of about 40 chars */
2097 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2098 out_of_space = True;
2101 finished = !get_lanman2_dir_entry(ctx,
2104 mask,dirtype,info_level,
2105 requires_resume_key,dont_descend,
2108 space_remaining, &out_of_space,
2110 &last_entry_off, ea_list);
2113 if (finished && out_of_space)
2116 if (!finished && !out_of_space)
2120 * As an optimisation if we know we aren't looking
2121 * for a wildcard name (ie. the name matches the wildcard exactly)
2122 * then we can finish on any (first) match.
2123 * This speeds up large directory searches. JRA.
2129 /* Ensure space_remaining never goes -ve. */
2130 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2131 space_remaining = 0;
2132 out_of_space = true;
2134 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2138 /* Check if we can close the dirptr */
2139 if(close_after_first || (finished && close_if_end)) {
2140 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2141 dptr_close(&dptr_num);
2145 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2146 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2147 * the protocol level is less than NT1. Tested with smbclient. JRA.
2148 * This should fix the OS/2 client bug #2335.
2151 if(numentries == 0) {
2152 dptr_close(&dptr_num);
2153 if (Protocol < PROTOCOL_NT1) {
2154 reply_doserror(req, ERRDOS, ERRnofiles);
2157 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2158 ERRDOS, ERRbadfile);
2163 /* At this point pdata points to numentries directory entries. */
2165 /* Set up the return parameter block */
2166 SSVAL(params,0,dptr_num);
2167 SSVAL(params,2,numentries);
2168 SSVAL(params,4,finished);
2169 SSVAL(params,6,0); /* Never an EA error */
2170 SSVAL(params,8,last_entry_off);
2172 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2175 if ((! *directory) && dptr_path(dptr_num)) {
2176 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2178 reply_nterror(req, NT_STATUS_NO_MEMORY);
2182 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2183 smb_fn_name(CVAL(req->inbuf,smb_com)),
2184 mask, directory, dirtype, numentries ) );
2187 * Force a name mangle here to ensure that the
2188 * mask as an 8.3 name is top of the mangled cache.
2189 * The reasons for this are subtle. Don't remove
2190 * this code unless you know what you are doing
2191 * (see PR#13758). JRA.
2194 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2195 char mangled_name[13];
2196 name_to_8_3(mask, mangled_name, True, conn->params);
2202 /****************************************************************************
2203 Reply to a TRANS2_FINDNEXT.
2204 ****************************************************************************/
2206 static void call_trans2findnext(connection_struct *conn,
2207 struct smb_request *req,
2208 char **pparams, int total_params,
2209 char **ppdata, int total_data,
2210 unsigned int max_data_bytes)
2212 /* We must be careful here that we don't return more than the
2213 allowed number of data bytes. If this means returning fewer than
2214 maxentries then so be it. We assume that the redirector has
2215 enough room for the fixed number of parameter bytes it has
2217 char *params = *pparams;
2218 char *pdata = *ppdata;
2224 uint16 findnext_flags;
2225 bool close_after_request;
2227 bool requires_resume_key;
2229 bool mask_contains_wcard = False;
2230 char *resume_name = NULL;
2231 const char *mask = NULL;
2232 const char *directory = NULL;
2236 int i, last_entry_off=0;
2237 bool finished = False;
2238 bool dont_descend = False;
2239 bool out_of_space = False;
2240 int space_remaining;
2241 struct ea_list *ea_list = NULL;
2242 NTSTATUS ntstatus = NT_STATUS_OK;
2243 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2244 TALLOC_CTX *ctx = talloc_tos();
2246 if (total_params < 13) {
2247 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2251 dptr_num = SVAL(params,0);
2252 maxentries = SVAL(params,2);
2253 info_level = SVAL(params,4);
2254 resume_key = IVAL(params,6);
2255 findnext_flags = SVAL(params,10);
2256 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2257 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2258 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2259 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2261 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2263 total_params - 12, STR_TERMINATE, &ntstatus,
2264 &mask_contains_wcard);
2265 if (!NT_STATUS_IS_OK(ntstatus)) {
2266 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2267 complain (it thinks we're asking for the directory above the shared
2268 path or an invalid name). Catch this as the resume name is only compared, never used in
2269 a file access. JRA. */
2270 srvstr_pull_talloc(ctx, params, req->flags2,
2271 &resume_name, params+12,
2275 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2276 reply_nterror(req, ntstatus);
2281 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2282 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2283 resume_key = %d resume name = %s continue=%d level = %d\n",
2284 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2285 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2288 /* W2K3 seems to treat zero as 1. */
2292 switch (info_level) {
2293 case SMB_FIND_INFO_STANDARD:
2294 case SMB_FIND_EA_SIZE:
2295 case SMB_FIND_EA_LIST:
2296 case SMB_FIND_FILE_DIRECTORY_INFO:
2297 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2298 case SMB_FIND_FILE_NAMES_INFO:
2299 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2300 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2301 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2303 case SMB_FIND_FILE_UNIX:
2304 case SMB_FIND_FILE_UNIX_INFO2:
2305 if (!lp_unix_extensions()) {
2306 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2311 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2315 if (info_level == SMB_FIND_EA_LIST) {
2318 if (total_data < 4) {
2319 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2323 ea_size = IVAL(pdata,0);
2324 if (ea_size != total_data) {
2325 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2326 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2327 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2331 if (!lp_ea_support(SNUM(conn))) {
2332 reply_doserror(req, ERRDOS, ERReasnotsupported);
2336 /* Pull out the list of names. */
2337 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2339 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2344 *ppdata = (char *)SMB_REALLOC(
2345 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2346 if(*ppdata == NULL) {
2347 reply_nterror(req, NT_STATUS_NO_MEMORY);
2352 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2354 /* Realloc the params space */
2355 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2356 if(*pparams == NULL ) {
2357 reply_nterror(req, NT_STATUS_NO_MEMORY);
2363 /* Check that the dptr is valid */
2364 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2365 reply_doserror(req, ERRDOS, ERRnofiles);
2369 string_set(&conn->dirpath,dptr_path(dptr_num));
2371 /* Get the wildcard mask from the dptr */
2372 if((p = dptr_wcard(dptr_num))== NULL) {
2373 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2374 reply_doserror(req, ERRDOS, ERRnofiles);
2379 directory = conn->dirpath;
2381 /* Get the attr mask from the dptr */
2382 dirtype = dptr_attr(dptr_num);
2384 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2385 dptr_num, mask, dirtype,
2387 dptr_TellDir(conn->dirptr)));
2389 /* We don't need to check for VOL here as this is returned by
2390 a different TRANS2 call. */
2392 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2393 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2394 dont_descend = True;
2397 space_remaining = max_data_bytes;
2398 out_of_space = False;
2401 * Seek to the correct position. We no longer use the resume key but
2402 * depend on the last file name instead.
2405 if(*resume_name && !continue_bit) {
2408 long current_pos = 0;
2410 * Remember, name_to_8_3 is called by
2411 * get_lanman2_dir_entry(), so the resume name
2412 * could be mangled. Ensure we check the unmangled name.
2415 if (mangle_is_mangled(resume_name, conn->params)) {
2416 char *new_resume_name = NULL;
2417 mangle_lookup_name_from_8_3(ctx,
2421 if (new_resume_name) {
2422 resume_name = new_resume_name;
2427 * Fix for NT redirector problem triggered by resume key indexes
2428 * changing between directory scans. We now return a resume key of 0
2429 * and instead look for the filename to continue from (also given
2430 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2431 * findfirst/findnext (as is usual) then the directory pointer
2432 * should already be at the correct place.
2435 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2436 } /* end if resume_name && !continue_bit */
2438 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2439 bool got_exact_match = False;
2441 /* this is a heuristic to avoid seeking the dirptr except when
2442 absolutely necessary. It allows for a filename of about 40 chars */
2443 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2444 out_of_space = True;
2447 finished = !get_lanman2_dir_entry(ctx,
2450 mask,dirtype,info_level,
2451 requires_resume_key,dont_descend,
2454 space_remaining, &out_of_space,
2456 &last_entry_off, ea_list);
2459 if (finished && out_of_space)
2462 if (!finished && !out_of_space)
2466 * As an optimisation if we know we aren't looking
2467 * for a wildcard name (ie. the name matches the wildcard exactly)
2468 * then we can finish on any (first) match.
2469 * This speeds up large directory searches. JRA.
2475 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2478 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2479 smb_fn_name(CVAL(req->inbuf,smb_com)),
2480 mask, directory, dirtype, numentries ) );
2482 /* Check if we can close the dirptr */
2483 if(close_after_request || (finished && close_if_end)) {
2484 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2485 dptr_close(&dptr_num); /* This frees up the saved mask */
2488 /* Set up the return parameter block */
2489 SSVAL(params,0,numentries);
2490 SSVAL(params,2,finished);
2491 SSVAL(params,4,0); /* Never an EA error */
2492 SSVAL(params,6,last_entry_off);
2494 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2500 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2502 E_md4hash(lp_servicename(SNUM(conn)),objid);
2506 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2508 SMB_ASSERT(extended_info != NULL);
2510 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2511 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2512 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2513 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2514 #ifdef SAMBA_VERSION_REVISION
2515 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2517 extended_info->samba_subversion = 0;
2518 #ifdef SAMBA_VERSION_RC_RELEASE
2519 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2521 #ifdef SAMBA_VERSION_PRE_RELEASE
2522 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2525 #ifdef SAMBA_VERSION_VENDOR_PATCH
2526 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2528 extended_info->samba_gitcommitdate = 0;
2529 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2530 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2533 memset(extended_info->samba_version_string, 0,
2534 sizeof(extended_info->samba_version_string));
2536 snprintf (extended_info->samba_version_string,
2537 sizeof(extended_info->samba_version_string),
2538 "%s", samba_version_string());
2541 /****************************************************************************
2542 Reply to a TRANS2_QFSINFO (query filesystem info).
2543 ****************************************************************************/
2545 static void call_trans2qfsinfo(connection_struct *conn,
2546 struct smb_request *req,
2547 char **pparams, int total_params,
2548 char **ppdata, int total_data,
2549 unsigned int max_data_bytes)
2551 char *pdata, *end_data;
2552 char *params = *pparams;
2556 const char *vname = volume_label(SNUM(conn));
2557 int snum = SNUM(conn);
2558 char *fstype = lp_fstype(SNUM(conn));
2559 uint32 additional_flags = 0;
2561 if (total_params < 2) {
2562 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2566 info_level = SVAL(params,0);
2569 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2570 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2571 "info level (0x%x) on IPC$.\n",
2572 (unsigned int)info_level));
2573 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2578 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2579 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2580 DEBUG(0,("call_trans2qfsinfo: encryption required "
2581 "and info level 0x%x sent.\n",
2582 (unsigned int)info_level));
2583 exit_server_cleanly("encryption required "
2589 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2591 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2592 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2593 reply_doserror(req, ERRSRV, ERRinvdevice);
2597 *ppdata = (char *)SMB_REALLOC(
2598 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2599 if (*ppdata == NULL ) {
2600 reply_nterror(req, NT_STATUS_NO_MEMORY);
2605 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2606 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2608 switch (info_level) {
2609 case SMB_INFO_ALLOCATION:
2611 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2613 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2614 reply_unixerror(req, ERRHRD, ERRgeneral);
2618 block_size = lp_block_size(snum);
2619 if (bsize < block_size) {
2620 SMB_BIG_UINT factor = block_size/bsize;
2625 if (bsize > block_size) {
2626 SMB_BIG_UINT factor = bsize/block_size;
2631 bytes_per_sector = 512;
2632 sectors_per_unit = bsize/bytes_per_sector;
2634 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2635 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2636 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2638 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2639 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2640 SIVAL(pdata,l1_cUnit,dsize);
2641 SIVAL(pdata,l1_cUnitAvail,dfree);
2642 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2646 case SMB_INFO_VOLUME:
2647 /* Return volume name */
2649 * Add volume serial number - hash of a combination of
2650 * the called hostname and the service name.
2652 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2654 * Win2k3 and previous mess this up by sending a name length
2655 * one byte short. I believe only older clients (OS/2 Win9x) use
2656 * this call so try fixing this by adding a terminating null to
2657 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2661 pdata+l2_vol_szVolLabel, vname,
2662 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2663 STR_NOALIGN|STR_TERMINATE);
2664 SCVAL(pdata,l2_vol_cch,len);
2665 data_len = l2_vol_szVolLabel + len;
2666 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2667 (unsigned)st.st_ctime, len, vname));
2670 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2671 case SMB_FS_ATTRIBUTE_INFORMATION:
2673 additional_flags = 0;
2674 #if defined(HAVE_SYS_QUOTAS)
2675 additional_flags |= FILE_VOLUME_QUOTAS;
2678 if(lp_nt_acl_support(SNUM(conn))) {
2679 additional_flags |= FILE_PERSISTENT_ACLS;
2682 /* Capabilities are filled in at connection time through STATVFS call */
2683 additional_flags |= conn->fs_capabilities;
2685 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2686 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2687 additional_flags); /* FS ATTRIBUTES */
2689 SIVAL(pdata,4,255); /* Max filename component length */
2690 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2691 and will think we can't do long filenames */
2692 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2693 PTR_DIFF(end_data, pdata+12),
2696 data_len = 12 + len;
2699 case SMB_QUERY_FS_LABEL_INFO:
2700 case SMB_FS_LABEL_INFORMATION:
2701 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2702 PTR_DIFF(end_data, pdata+4), 0);
2707 case SMB_QUERY_FS_VOLUME_INFO:
2708 case SMB_FS_VOLUME_INFORMATION:
2711 * Add volume serial number - hash of a combination of
2712 * the called hostname and the service name.
2714 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2715 (str_checksum(get_local_machine_name())<<16));
2717 /* Max label len is 32 characters. */
2718 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2719 PTR_DIFF(end_data, pdata+18),
2721 SIVAL(pdata,12,len);
2724 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2725 (int)strlen(vname),vname, lp_servicename(snum)));
2728 case SMB_QUERY_FS_SIZE_INFO:
2729 case SMB_FS_SIZE_INFORMATION:
2731 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2733 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2734 reply_unixerror(req, ERRHRD, ERRgeneral);
2737 block_size = lp_block_size(snum);
2738 if (bsize < block_size) {
2739 SMB_BIG_UINT factor = block_size/bsize;
2744 if (bsize > block_size) {
2745 SMB_BIG_UINT factor = bsize/block_size;
2750 bytes_per_sector = 512;
2751 sectors_per_unit = bsize/bytes_per_sector;
2752 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2753 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2754 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2755 SBIG_UINT(pdata,0,dsize);
2756 SBIG_UINT(pdata,8,dfree);
2757 SIVAL(pdata,16,sectors_per_unit);
2758 SIVAL(pdata,20,bytes_per_sector);
2762 case SMB_FS_FULL_SIZE_INFORMATION:
2764 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2766 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2767 reply_unixerror(req, ERRHRD, ERRgeneral);
2770 block_size = lp_block_size(snum);
2771 if (bsize < block_size) {
2772 SMB_BIG_UINT factor = block_size/bsize;
2777 if (bsize > block_size) {
2778 SMB_BIG_UINT factor = bsize/block_size;
2783 bytes_per_sector = 512;
2784 sectors_per_unit = bsize/bytes_per_sector;
2785 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2786 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2787 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2788 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2789 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2790 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2791 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2792 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2796 case SMB_QUERY_FS_DEVICE_INFO:
2797 case SMB_FS_DEVICE_INFORMATION:
2799 SIVAL(pdata,0,0); /* dev type */
2800 SIVAL(pdata,4,0); /* characteristics */
2803 #ifdef HAVE_SYS_QUOTAS
2804 case SMB_FS_QUOTA_INFORMATION:
2806 * what we have to send --metze:
2808 * Unknown1: 24 NULL bytes
2809 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2810 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2811 * Quota Flags: 2 byte :
2812 * Unknown3: 6 NULL bytes
2816 * details for Quota Flags:
2818 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2819 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2820 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2821 * 0x0001 Enable Quotas: enable quota for this fs
2825 /* we need to fake up a fsp here,
2826 * because its not send in this call
2829 SMB_NTQUOTA_STRUCT quotas;
2832 ZERO_STRUCT(quotas);
2838 if (conn->server_info->utok.uid != 0) {
2839 DEBUG(0,("set_user_quota: access_denied "
2840 "service [%s] user [%s]\n",
2841 lp_servicename(SNUM(conn)),
2842 conn->server_info->unix_name));
2843 reply_doserror(req, ERRDOS, ERRnoaccess);
2847 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2848 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2849 reply_doserror(req, ERRSRV, ERRerror);
2855 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2857 /* Unknown1 24 NULL bytes*/
2858 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2859 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2860 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2862 /* Default Soft Quota 8 bytes */
2863 SBIG_UINT(pdata,24,quotas.softlim);
2865 /* Default Hard Quota 8 bytes */
2866 SBIG_UINT(pdata,32,quotas.hardlim);
2868 /* Quota flag 2 bytes */
2869 SSVAL(pdata,40,quotas.qflags);
2871 /* Unknown3 6 NULL bytes */
2877 #endif /* HAVE_SYS_QUOTAS */
2878 case SMB_FS_OBJECTID_INFORMATION:
2880 unsigned char objid[16];
2881 struct smb_extended_info extended_info;
2882 memcpy(pdata,create_volume_objectid(conn, objid),16);
2883 samba_extended_info_version (&extended_info);
2884 SIVAL(pdata,16,extended_info.samba_magic);
2885 SIVAL(pdata,20,extended_info.samba_version);
2886 SIVAL(pdata,24,extended_info.samba_subversion);
2887 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2888 memcpy(pdata+36,extended_info.samba_version_string,28);
2894 * Query the version and capabilities of the CIFS UNIX extensions
2898 case SMB_QUERY_CIFS_UNIX_INFO:
2900 bool large_write = lp_min_receive_file_size() &&
2901 !srv_is_signing_active();
2902 bool large_read = !srv_is_signing_active();
2903 int encrypt_caps = 0;
2905 if (!lp_unix_extensions()) {
2906 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2910 switch (conn->encrypt_level) {
2916 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2919 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2920 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2921 large_write = false;
2927 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2928 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2930 /* We have POSIX ACLs, pathname, encryption,
2931 * large read/write, and locking capability. */
2933 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2934 CIFS_UNIX_POSIX_ACLS_CAP|
2935 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2936 CIFS_UNIX_FCNTL_LOCKS_CAP|
2937 CIFS_UNIX_EXTATTR_CAP|
2938 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2940 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2942 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2946 case SMB_QUERY_POSIX_FS_INFO:
2949 vfs_statvfs_struct svfs;
2951 if (!lp_unix_extensions()) {
2952 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2956 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2960 SIVAL(pdata,0,svfs.OptimalTransferSize);
2961 SIVAL(pdata,4,svfs.BlockSize);
2962 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2963 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2964 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2965 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2966 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2967 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2968 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2970 } else if (rc == EOPNOTSUPP) {
2971 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2973 #endif /* EOPNOTSUPP */
2975 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2976 reply_doserror(req, ERRSRV, ERRerror);
2982 case SMB_QUERY_POSIX_WHOAMI:
2988 if (!lp_unix_extensions()) {
2989 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2993 if (max_data_bytes < 40) {
2994 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2998 /* We ARE guest if global_sid_Builtin_Guests is
2999 * in our list of SIDs.
3001 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3002 conn->server_info->ptok)) {
3003 flags |= SMB_WHOAMI_GUEST;
3006 /* We are NOT guest if global_sid_Authenticated_Users
3007 * is in our list of SIDs.
3009 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3010 conn->server_info->ptok)) {
3011 flags &= ~SMB_WHOAMI_GUEST;
3014 /* NOTE: 8 bytes for UID/GID, irrespective of native
3015 * platform size. This matches
3016 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3018 data_len = 4 /* flags */
3025 + 4 /* pad/reserved */
3026 + (conn->server_info->utok.ngroups * 8)
3028 + (conn->server_info->ptok->num_sids *
3032 SIVAL(pdata, 0, flags);
3033 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3035 (SMB_BIG_UINT)conn->server_info->utok.uid);
3036 SBIG_UINT(pdata, 16,
3037 (SMB_BIG_UINT)conn->server_info->utok.gid);
3040 if (data_len >= max_data_bytes) {
3041 /* Potential overflow, skip the GIDs and SIDs. */
3043 SIVAL(pdata, 24, 0); /* num_groups */
3044 SIVAL(pdata, 28, 0); /* num_sids */
3045 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3046 SIVAL(pdata, 36, 0); /* reserved */
3052 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3053 SIVAL(pdata, 28, conn->server_info->num_sids);
3055 /* We walk the SID list twice, but this call is fairly
3056 * infrequent, and I don't expect that it's performance
3057 * sensitive -- jpeach
3059 for (i = 0, sid_bytes = 0;
3060 i < conn->server_info->ptok->num_sids; ++i) {
3061 sid_bytes += ndr_size_dom_sid(
3062 &conn->server_info->ptok->user_sids[i],
3066 /* SID list byte count */
3067 SIVAL(pdata, 32, sid_bytes);
3069 /* 4 bytes pad/reserved - must be zero */
3070 SIVAL(pdata, 36, 0);
3074 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3075 SBIG_UINT(pdata, data_len,
3076 (SMB_BIG_UINT)conn->server_info->utok.groups[i]);
3082 i < conn->server_info->ptok->num_sids; ++i) {
3083 int sid_len = ndr_size_dom_sid(
3084 &conn->server_info->ptok->user_sids[i],
3087 sid_linearize(pdata + data_len, sid_len,
3088 &conn->server_info->ptok->user_sids[i]);
3089 data_len += sid_len;
3095 case SMB_MAC_QUERY_FS_INFO:
3097 * Thursby MAC extension... ONLY on NTFS filesystems
3098 * once we do streams then we don't need this
3100 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3102 SIVAL(pdata,84,0x100); /* Don't support mac... */
3107 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3112 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3115 DEBUG( 4, ( "%s info_level = %d\n",
3116 smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
3121 /****************************************************************************
3122 Reply to a TRANS2_SETFSINFO (set filesystem info).
3123 ****************************************************************************/
3125 static void call_trans2setfsinfo(connection_struct *conn,
3126 struct smb_request *req,
3127 char **pparams, int total_params,
3128 char **ppdata, int total_data,
3129 unsigned int max_data_bytes)
3131 char *pdata = *ppdata;
3132 char *params = *pparams;
3135 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3138 if (total_params < 4) {
3139 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3141 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3145 info_level = SVAL(params,2);
3148 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3149 info_level != SMB_SET_CIFS_UNIX_INFO) {
3150 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3151 "info level (0x%x) on IPC$.\n",
3152 (unsigned int)info_level));
3153 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3158 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3159 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3160 DEBUG(0,("call_trans2setfsinfo: encryption required "
3161 "and info level 0x%x sent.\n",
3162 (unsigned int)info_level));
3163 exit_server_cleanly("encryption required "
3169 switch(info_level) {
3170 case SMB_SET_CIFS_UNIX_INFO:
3172 uint16 client_unix_major;
3173 uint16 client_unix_minor;
3174 uint32 client_unix_cap_low;
3175 uint32 client_unix_cap_high;
3177 if (!lp_unix_extensions()) {
3179 NT_STATUS_INVALID_LEVEL);
3183 /* There should be 12 bytes of capabilities set. */
3184 if (total_data < 8) {
3187 NT_STATUS_INVALID_PARAMETER);
3190 client_unix_major = SVAL(pdata,0);
3191 client_unix_minor = SVAL(pdata,2);
3192 client_unix_cap_low = IVAL(pdata,4);
3193 client_unix_cap_high = IVAL(pdata,8);
3194 /* Just print these values for now. */
3195 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3196 cap_low = 0x%x, cap_high = 0x%x\n",
3197 (unsigned int)client_unix_major,
3198 (unsigned int)client_unix_minor,
3199 (unsigned int)client_unix_cap_low,
3200 (unsigned int)client_unix_cap_high ));
3202 /* Here is where we must switch to posix pathname processing... */
3203 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3204 lp_set_posix_pathnames();
3205 mangle_change_to_posix();
3208 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3209 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3210 /* Client that knows how to do posix locks,
3211 * but not posix open/mkdir operations. Set a
3212 * default type for read/write checks. */
3214 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3220 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3223 size_t param_len = 0;
3224 size_t data_len = total_data;
3226 if (!lp_unix_extensions()) {
3229 NT_STATUS_INVALID_LEVEL);
3233 if (lp_smb_encrypt(SNUM(conn)) == false) {
3236 NT_STATUS_NOT_SUPPORTED);
3240 DEBUG( 4,("call_trans2setfsinfo: "
3241 "request transport encryption.\n"));
3243 status = srv_request_encryption_setup(conn,
3244 (unsigned char **)ppdata,
3246 (unsigned char **)pparams,
3249 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3250 !NT_STATUS_IS_OK(status)) {
3251 reply_nterror(req, status);
3255 send_trans2_replies(conn, req,
3262 if (NT_STATUS_IS_OK(status)) {
3263 /* Server-side transport
3264 * encryption is now *on*. */
3265 status = srv_encryption_start(conn);
3266 if (!NT_STATUS_IS_OK(status)) {
3267 exit_server_cleanly(
3268 "Failure in setting "
3269 "up encrypted transport");
3275 case SMB_FS_QUOTA_INFORMATION:
3277 files_struct *fsp = NULL;
3278 SMB_NTQUOTA_STRUCT quotas;
3280 ZERO_STRUCT(quotas);
3283 if ((conn->server_info->utok.uid != 0)
3284 ||!CAN_WRITE(conn)) {
3285 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3286 lp_servicename(SNUM(conn)),
3287 conn->server_info->unix_name));
3288 reply_doserror(req, ERRSRV, ERRaccess);
3292 /* note: normaly there're 48 bytes,
3293 * but we didn't use the last 6 bytes for now
3296 fsp = file_fsp(SVAL(params,0));
3298 if (!check_fsp_ntquota_handle(conn, req,
3300 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3302 req, NT_STATUS_INVALID_HANDLE);
3306 if (total_data < 42) {
3307 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3311 NT_STATUS_INVALID_PARAMETER);
3315 /* unknown_1 24 NULL bytes in pdata*/
3317 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3318 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
3319 #ifdef LARGE_SMB_OFF_T
3320 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
3321 #else /* LARGE_SMB_OFF_T */
3322 if ((IVAL(pdata,28) != 0)&&
3323 ((quotas.softlim != 0xFFFFFFFF)||
3324 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3325 /* more than 32 bits? */
3328 NT_STATUS_INVALID_PARAMETER);
3331 #endif /* LARGE_SMB_OFF_T */
3333 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3334 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3335 #ifdef LARGE_SMB_OFF_T
3336 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3337 #else /* LARGE_SMB_OFF_T */
3338 if ((IVAL(pdata,36) != 0)&&
3339 ((quotas.hardlim != 0xFFFFFFFF)||
3340 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3341 /* more than 32 bits? */
3344 NT_STATUS_INVALID_PARAMETER);
3347 #endif /* LARGE_SMB_OFF_T */
3349 /* quota_flags 2 bytes **/
3350 quotas.qflags = SVAL(pdata,40);
3352 /* unknown_2 6 NULL bytes follow*/
3354 /* now set the quotas */
3355 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3356 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3357 reply_doserror(req, ERRSRV, ERRerror);
3364 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3366 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3372 * sending this reply works fine,
3373 * but I'm not sure it's the same
3374 * like windows do...
3377 reply_outbuf(req, 10, 0);
3380 #if defined(HAVE_POSIX_ACLS)
3381 /****************************************************************************
3382 Utility function to count the number of entries in a POSIX acl.
3383 ****************************************************************************/
3385 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3387 unsigned int ace_count = 0;
3388 int entry_id = SMB_ACL_FIRST_ENTRY;
3389 SMB_ACL_ENTRY_T entry;
3391 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3393 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3394 entry_id = SMB_ACL_NEXT_ENTRY;
3401 /****************************************************************************
3402 Utility function to marshall a POSIX acl into wire format.
3403 ****************************************************************************/
3405 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3407 int entry_id = SMB_ACL_FIRST_ENTRY;
3408 SMB_ACL_ENTRY_T entry;
3410 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3411 SMB_ACL_TAG_T tagtype;
3412 SMB_ACL_PERMSET_T permset;
3413 unsigned char perms = 0;
3414 unsigned int own_grp;
3417 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3418 entry_id = SMB_ACL_NEXT_ENTRY;
3421 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3422 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3426 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3427 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3431 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3432 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3433 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3435 SCVAL(pdata,1,perms);
3438 case SMB_ACL_USER_OBJ:
3439 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3440 own_grp = (unsigned int)pst->st_uid;
3441 SIVAL(pdata,2,own_grp);
3446 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3448 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3451 own_grp = (unsigned int)*puid;
3452 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3453 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3454 SIVAL(pdata,2,own_grp);
3458 case SMB_ACL_GROUP_OBJ:
3459 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3460 own_grp = (unsigned int)pst->st_gid;
3461 SIVAL(pdata,2,own_grp);
3466 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3468 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3471 own_grp = (unsigned int)*pgid;
3472 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3473 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3474 SIVAL(pdata,2,own_grp);
3479 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3480 SIVAL(pdata,2,0xFFFFFFFF);
3481 SIVAL(pdata,6,0xFFFFFFFF);
3484 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3485 SIVAL(pdata,2,0xFFFFFFFF);
3486 SIVAL(pdata,6,0xFFFFFFFF);
3489 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3492 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3499 /****************************************************************************
3500 Store the FILE_UNIX_BASIC info.
3501 ****************************************************************************/
3503 static char *store_file_unix_basic(connection_struct *conn,
3506 const SMB_STRUCT_STAT *psbuf)
3508 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3509 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3511 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3514 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3517 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3518 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3519 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3522 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3526 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3530 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3533 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3537 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3541 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3544 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3548 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3555 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3556 * the chflags(2) (or equivalent) flags.
3558 * XXX: this really should be behind the VFS interface. To do this, we would
3559 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3560 * Each VFS module could then implement its own mapping as appropriate for the
3561 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3563 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3567 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3571 { UF_IMMUTABLE, EXT_IMMUTABLE },
3575 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3579 { UF_HIDDEN, EXT_HIDDEN },
3582 /* Do not remove. We need to guarantee that this array has at least one
3583 * entry to build on HP-UX.
3589 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3590 uint32 *smb_fflags, uint32 *smb_fmask)
3592 #ifdef HAVE_STAT_ST_FLAGS
3595 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3596 *smb_fmask |= info2_flags_map[i].smb_fflag;
3597 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3598 *smb_fflags |= info2_flags_map[i].smb_fflag;
3601 #endif /* HAVE_STAT_ST_FLAGS */
3604 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3605 const uint32 smb_fflags,
3606 const uint32 smb_fmask,
3609 #ifdef HAVE_STAT_ST_FLAGS
3610 uint32 max_fmask = 0;
3613 *stat_fflags = psbuf->st_flags;
3615 /* For each flags requested in smb_fmask, check the state of the
3616 * corresponding flag in smb_fflags and set or clear the matching
3620 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3621 max_fmask |= info2_flags_map[i].smb_fflag;
3622 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3623 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3624 *stat_fflags |= info2_flags_map[i].stat_fflag;
3626 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3631 /* If smb_fmask is asking to set any bits that are not supported by
3632 * our flag mappings, we should fail.
3634 if ((smb_fmask & max_fmask) != smb_fmask) {
3641 #endif /* HAVE_STAT_ST_FLAGS */
3645 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3646 * of file flags and birth (create) time.
3648 static char *store_file_unix_basic_info2(connection_struct *conn,
3651 const SMB_STRUCT_STAT *psbuf)
3653 uint32 file_flags = 0;
3654 uint32 flags_mask = 0;
3656 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3658 /* Create (birth) time 64 bit */
3659 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3662 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3663 SIVAL(pdata, 0, file_flags); /* flags */
3664 SIVAL(pdata, 4, flags_mask); /* mask */
3670 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3671 const struct stream_struct *streams,
3673 unsigned int max_data_bytes,
3674 unsigned int *data_size)
3677 unsigned int ofs = 0;
3679 for (i=0; i<num_streams; i++) {
3680 unsigned int next_offset;
3682 smb_ucs2_t *namebuf;
3684 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3685 streams[i].name, &namelen) ||
3688 return NT_STATUS_INVALID_PARAMETER;
3692 * name_buf is now null-terminated, we need to marshall as not
3698 if (ofs + 24 + namelen > max_data_bytes) {
3699 TALLOC_FREE(namebuf);
3700 return NT_STATUS_BUFFER_TOO_SMALL;
3703 SIVAL(data, ofs+4, namelen);
3704 SOFF_T(data, ofs+8, streams[i].size);
3705 SOFF_T(data, ofs+16, streams[i].alloc_size);
3706 memcpy(data+ofs+24, namebuf, namelen);
3707 TALLOC_FREE(namebuf);
3709 next_offset = ofs + 24 + namelen;
3711 if (i == num_streams-1) {
3712 SIVAL(data, ofs, 0);
3715 unsigned int align = ndr_align_size(next_offset, 8);
3717 if (next_offset + align > max_data_bytes) {
3718 return NT_STATUS_BUFFER_TOO_SMALL;
3721 memset(data+next_offset, 0, align);
3722 next_offset += align;
3724 SIVAL(data, ofs, next_offset - ofs);
3733 return NT_STATUS_OK;
3736 /****************************************************************************
3737 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3738 ****************************************************************************/
3740 static void call_trans2qpipeinfo(connection_struct *conn,
3741 struct smb_request *req,
3742 unsigned int tran_call,
3743 char **pparams, int total_params,
3744 char **ppdata, int total_data,
3745 unsigned int max_data_bytes)
3747 char *params = *pparams;
3748 char *pdata = *ppdata;
3749 unsigned int data_size = 0;
3750 unsigned int param_size = 2;
3752 smb_np_struct *p_pipe = NULL;
3755 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3759 if (total_params < 4) {
3760 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3764 p_pipe = get_rpc_pipe_p(SVAL(params,0));
3765 if (p_pipe == NULL) {
3766 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3770 info_level = SVAL(params,2);
3772 *pparams = (char *)SMB_REALLOC(*pparams,2);
3773 if (*pparams == NULL) {
3774 reply_nterror(req, NT_STATUS_NO_MEMORY);
3779 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3780 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3781 if (*ppdata == NULL ) {
3782 reply_nterror(req, NT_STATUS_NO_MEMORY);
3787 switch (info_level) {
3788 case SMB_FILE_STANDARD_INFORMATION:
3790 SOFF_T(pdata,0,4096LL);
3797 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3801 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3807 /****************************************************************************
3808 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3809 file name or file id).
3810 ****************************************************************************/
3812 static void call_trans2qfilepathinfo(connection_struct *conn,
3813 struct smb_request *req,
3814 unsigned int tran_call,
3815 char **pparams, int total_params,
3816 char **ppdata, int total_data,
3817 unsigned int max_data_bytes)
3819 char *params = *pparams;
3820 char *pdata = *ppdata;
3821 char *dstart, *dend;
3825 SMB_OFF_T file_size=0;
3826 SMB_BIG_UINT allocation_size=0;
3827 unsigned int data_size = 0;
3828 unsigned int param_size = 2;
3829 SMB_STRUCT_STAT sbuf;
3830 char *dos_fname = NULL;
3836 bool delete_pending = False;
3838 time_t create_time, mtime, atime;
3839 struct timespec create_time_ts, mtime_ts, atime_ts;
3840 struct timespec write_time_ts;
3841 files_struct *fsp = NULL;
3842 struct file_id fileid;
3843 struct ea_list *ea_list = NULL;
3844 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3845 char *lock_data = NULL;
3846 bool ms_dfs_link = false;
3847 TALLOC_CTX *ctx = talloc_tos();
3850 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3855 ZERO_STRUCT(write_time_ts);
3857 if (tran_call == TRANSACT2_QFILEINFO) {
3858 if (total_params < 4) {
3859 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3864 call_trans2qpipeinfo(conn, req, tran_call,
3865 pparams, total_params,
3871 fsp = file_fsp(SVAL(params,0));
3872 info_level = SVAL(params,2);
3874 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3876 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3877 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3881 /* Initial check for valid fsp ptr. */
3882 if (!check_fsp_open(conn, req, fsp)) {
3886 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3888 reply_nterror(req, NT_STATUS_NO_MEMORY);
3892 if(fsp->fake_file_handle) {
3894 * This is actually for the QUOTA_FAKE_FILE --metze
3897 /* We know this name is ok, it's already passed the checks. */
3899 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3901 * This is actually a QFILEINFO on a directory
3902 * handle (returned from an NT SMB). NT5.0 seems
3903 * to do this call. JRA.
3906 if (INFO_LEVEL_IS_UNIX(info_level)) {
3907 /* Always do lstat for UNIX calls. */
3908 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3909 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3910 reply_unixerror(req,ERRDOS,ERRbadpath);
3913 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3914 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3915 reply_unixerror(req, ERRDOS, ERRbadpath);
3919 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3920 get_file_infos(fileid, &delete_pending, &write_time_ts);
3923 * Original code - this is an open file.
3925 if (!check_fsp(conn, req, fsp)) {
3929 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3930 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3931 reply_unixerror(req, ERRDOS, ERRbadfid);
3934 pos = fsp->fh->position_information;
3935 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3936 get_file_infos(fileid, &delete_pending, &write_time_ts);
3937 access_mask = fsp->access_mask;
3941 NTSTATUS status = NT_STATUS_OK;
3944 if (total_params < 7) {
3945 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3949 info_level = SVAL(params,0);
3951 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3953 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3954 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3958 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
3960 STR_TERMINATE, &status);
3961 if (!NT_STATUS_IS_OK(status)) {
3962 reply_nterror(req, status);
3966 status = resolve_dfspath(ctx,
3968 req->flags2 & FLAGS2_DFS_PATHNAMES,
3971 if (!NT_STATUS_IS_OK(status)) {
3972 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3973 reply_botherror(req,
3974 NT_STATUS_PATH_NOT_COVERED,
3975 ERRSRV, ERRbadpath);
3977 reply_nterror(req, status);
3981 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3982 if (!NT_STATUS_IS_OK(status)) {
3983 reply_nterror(req, status);
3986 status = check_name(conn, fname);
3987 if (!NT_STATUS_IS_OK(status)) {
3988 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3989 reply_nterror(req, status);
3993 if (INFO_LEVEL_IS_UNIX(info_level)) {
3994 /* Always do lstat for UNIX calls. */
3995 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3996 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3997 reply_unixerror(req, ERRDOS, ERRbadpath);
4001 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
4002 ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
4005 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
4006 reply_unixerror(req, ERRDOS, ERRbadpath);
4011 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4012 get_file_infos(fileid, &delete_pending, &write_time_ts);
4013 if (delete_pending) {
4014 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4019 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4020 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4024 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4025 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4027 p = strrchr_m(fname,'/');
4034 mode = dos_mode_msdfs(conn,fname,&sbuf);
4036 mode = dos_mode(conn,fname,&sbuf);
4039 mode = FILE_ATTRIBUTE_NORMAL;
4041 nlink = sbuf.st_nlink;
4043 if (nlink && (mode&aDIR)) {
4047 if ((nlink > 0) && delete_pending) {
4051 fullpathname = fname;
4053 file_size = get_file_size(sbuf);
4055 /* Pull out any data sent here before we realloc. */
4056 switch (info_level) {
4057 case SMB_INFO_QUERY_EAS_FROM_LIST:
4059 /* Pull any EA list from the data portion. */
4062 if (total_data < 4) {
4064 req, NT_STATUS_INVALID_PARAMETER);
4067 ea_size = IVAL(pdata,0);
4069 if (total_data > 0 && ea_size != total_data) {
4070 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4071 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4073 req, NT_STATUS_INVALID_PARAMETER);
4077 if (!lp_ea_support(SNUM(conn))) {
4078 reply_doserror(req, ERRDOS,
4079 ERReasnotsupported);
4083 /* Pull out the list of names. */
4084 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4087 req, NT_STATUS_INVALID_PARAMETER);
4093 case SMB_QUERY_POSIX_LOCK:
4095 if (fsp == NULL || fsp->fh->fd == -1) {
4096 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4100 if (total_data != POSIX_LOCK_DATA_SIZE) {
4102 req, NT_STATUS_INVALID_PARAMETER);
4106 /* Copy the lock range data. */
4107 lock_data = (char *)TALLOC_MEMDUP(
4108 ctx, pdata, total_data);
4110 reply_nterror(req, NT_STATUS_NO_MEMORY);
4118 *pparams = (char *)SMB_REALLOC(*pparams,2);
4119 if (*pparams == NULL) {
4120 reply_nterror(req, NT_STATUS_NO_MEMORY);
4125 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4126 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4127 if (*ppdata == NULL ) {
4128 reply_nterror(req, NT_STATUS_NO_MEMORY);
4133 dend = dstart + data_size - 1;
4135 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
4136 mtime_ts = get_mtimespec(&sbuf);
4137 atime_ts = get_atimespec(&sbuf);
4139 allocation_size = get_allocation_size(conn,fsp,&sbuf);
4142 /* Do we have this path open ? */
4144 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4145 fsp1 = file_find_di_first(fileid);
4146 if (fsp1 && fsp1->initial_allocation_size) {
4147 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
4151 if (!null_timespec(write_time_ts)) {
4152 mtime_ts = write_time_ts;
4155 if (lp_dos_filetime_resolution(SNUM(conn))) {
4156 dos_filetime_timespec(&create_time_ts);
4157 dos_filetime_timespec(&mtime_ts);
4158 dos_filetime_timespec(&atime_ts);
4161 create_time = convert_timespec_to_time_t(create_time_ts);
4162 mtime = convert_timespec_to_time_t(mtime_ts);
4163 atime = convert_timespec_to_time_t(atime_ts);
4165 /* NT expects the name to be in an exact form of the *full*
4166 filename. See the trans2 torture test */
4167 if (ISDOT(base_name)) {
4168 dos_fname = talloc_strdup(ctx, "\\");
4170 reply_nterror(req, NT_STATUS_NO_MEMORY);
4174 dos_fname = talloc_asprintf(ctx,
4178 reply_nterror(req, NT_STATUS_NO_MEMORY);
4181 string_replace(dos_fname, '/', '\\');
4184 switch (info_level) {
4185 case SMB_INFO_STANDARD:
4186 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4188 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4189 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4190 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4191 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4192 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4193 SSVAL(pdata,l1_attrFile,mode);
4196 case SMB_INFO_QUERY_EA_SIZE:
4198 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4199 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4201 srv_put_dos_date2(pdata,0,create_time);
4202 srv_put_dos_date2(pdata,4,atime);
4203 srv_put_dos_date2(pdata,8,mtime); /* write time */
4204 SIVAL(pdata,12,(uint32)file_size);
4205 SIVAL(pdata,16,(uint32)allocation_size);
4206 SSVAL(pdata,20,mode);
4207 SIVAL(pdata,22,ea_size);
4211 case SMB_INFO_IS_NAME_VALID:
4212 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4213 if (tran_call == TRANSACT2_QFILEINFO) {
4214 /* os/2 needs this ? really ?*/
4215 reply_doserror(req, ERRDOS, ERRbadfunc);
4222 case SMB_INFO_QUERY_EAS_FROM_LIST:
4224 size_t total_ea_len = 0;
4225 struct ea_list *ea_file_list = NULL;
4227 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4229 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4230 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4232 if (!ea_list || (total_ea_len > data_size)) {
4234 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4238 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4242 case SMB_INFO_QUERY_ALL_EAS:
4244 /* We have data_size bytes to put EA's into. */
4245 size_t total_ea_len = 0;
4247 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4249 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4250 if (!ea_list || (total_ea_len > data_size)) {
4252 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4256 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4260 case SMB_FILE_BASIC_INFORMATION:
4261 case SMB_QUERY_FILE_BASIC_INFO:
4263 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4264 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4265 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4267 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4271 put_long_date_timespec(pdata,create_time_ts);
4272 put_long_date_timespec(pdata+8,atime_ts);
4273 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4274 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4275 SIVAL(pdata,32,mode);
4277 DEBUG(5,("SMB_QFBI - "));
4278 DEBUG(5,("create: %s ", ctime(&create_time)));
4279 DEBUG(5,("access: %s ", ctime(&atime)));
4280 DEBUG(5,("write: %s ", ctime(&mtime)));
4281 DEBUG(5,("change: %s ", ctime(&mtime)));
4282 DEBUG(5,("mode: %x\n", mode));
4285 case SMB_FILE_STANDARD_INFORMATION:
4286 case SMB_QUERY_FILE_STANDARD_INFO:
4288 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4290 SOFF_T(pdata,0,allocation_size);
4291 SOFF_T(pdata,8,file_size);
4292 SIVAL(pdata,16,nlink);
4293 SCVAL(pdata,20,delete_pending?1:0);
4294 SCVAL(pdata,21,(mode&aDIR)?1:0);
4295 SSVAL(pdata,22,0); /* Padding. */
4298 case SMB_FILE_EA_INFORMATION:
4299 case SMB_QUERY_FILE_EA_INFO:
4301 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4302 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4304 SIVAL(pdata,0,ea_size);
4308 /* Get the 8.3 name - used if NT SMB was negotiated. */
4309 case SMB_QUERY_FILE_ALT_NAME_INFO:
4310 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4312 char mangled_name[13];
4313 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4314 if (!name_to_8_3(base_name,mangled_name,
4315 True,conn->params)) {
4318 NT_STATUS_NO_MEMORY);
4320 len = srvstr_push(dstart, req->flags2,
4321 pdata+4, mangled_name,
4322 PTR_DIFF(dend, pdata+4),
4324 data_size = 4 + len;
4329 case SMB_QUERY_FILE_NAME_INFO:
4331 this must be *exactly* right for ACLs on mapped drives to work
4333 len = srvstr_push(dstart, req->flags2,
4335 PTR_DIFF(dend, pdata+4),
4337 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4338 data_size = 4 + len;
4342 case SMB_FILE_ALLOCATION_INFORMATION:
4343 case SMB_QUERY_FILE_ALLOCATION_INFO:
4344 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4346 SOFF_T(pdata,0,allocation_size);
4349 case SMB_FILE_END_OF_FILE_INFORMATION:
4350 case SMB_QUERY_FILE_END_OF_FILEINFO:
4351 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4353 SOFF_T(pdata,0,file_size);
4356 case SMB_QUERY_FILE_ALL_INFO:
4357 case SMB_FILE_ALL_INFORMATION:
4359 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4360 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4361 put_long_date_timespec(pdata,create_time_ts);
4362 put_long_date_timespec(pdata+8,atime_ts);
4363 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4364 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4365 SIVAL(pdata,32,mode);
4366 SIVAL(pdata,36,0); /* padding. */
4368 SOFF_T(pdata,0,allocation_size);
4369 SOFF_T(pdata,8,file_size);
4370 SIVAL(pdata,16,nlink);
4371 SCVAL(pdata,20,delete_pending);
4372 SCVAL(pdata,21,(mode&aDIR)?1:0);
4375 SIVAL(pdata,0,ea_size);
4376 pdata += 4; /* EA info */
4377 len = srvstr_push(dstart, req->flags2,
4379 PTR_DIFF(dend, pdata+4),
4383 data_size = PTR_DIFF(pdata,(*ppdata));
4386 case SMB_FILE_INTERNAL_INFORMATION:
4387 /* This should be an index number - looks like
4390 I think this causes us to fail the IFSKIT
4391 BasicFileInformationTest. -tpot */
4393 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4394 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4395 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4399 case SMB_FILE_ACCESS_INFORMATION:
4400 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4401 SIVAL(pdata,0,access_mask);
4405 case SMB_FILE_NAME_INFORMATION:
4406 /* Pathname with leading '\'. */
4409 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4410 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4411 SIVAL(pdata,0,byte_len);
4412 data_size = 4 + byte_len;
4416 case SMB_FILE_DISPOSITION_INFORMATION:
4417 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4419 SCVAL(pdata,0,delete_pending);
4422 case SMB_FILE_POSITION_INFORMATION:
4423 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4425 SOFF_T(pdata,0,pos);
4428 case SMB_FILE_MODE_INFORMATION:
4429 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4430 SIVAL(pdata,0,mode);
4434 case SMB_FILE_ALIGNMENT_INFORMATION:
4435 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4436 SIVAL(pdata,0,0); /* No alignment needed. */
4441 * NT4 server just returns "invalid query" to this - if we try
4442 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4445 /* The first statement above is false - verified using Thursby
4446 * client against NT4 -- gcolley.
4448 case SMB_QUERY_FILE_STREAM_INFO:
4449 case SMB_FILE_STREAM_INFORMATION: {
4450 unsigned int num_streams;
4451 struct stream_struct *streams;
4454 DEBUG(10,("call_trans2qfilepathinfo: "
4455 "SMB_FILE_STREAM_INFORMATION\n"));
4457 status = SMB_VFS_STREAMINFO(
4458 conn, fsp, fname, talloc_tos(),
4459 &num_streams, &streams);
4461 if (!NT_STATUS_IS_OK(status)) {
4462 DEBUG(10, ("could not get stream info: %s\n",
4463 nt_errstr(status)));
4464 reply_nterror(req, status);
4468 status = marshall_stream_info(num_streams, streams,
4469 pdata, max_data_bytes,
4472 if (!NT_STATUS_IS_OK(status)) {
4473 DEBUG(10, ("marshall_stream_info failed: %s\n",
4474 nt_errstr(status)));
4475 reply_nterror(req, status);
4479 TALLOC_FREE(streams);
4483 case SMB_QUERY_COMPRESSION_INFO:
4484 case SMB_FILE_COMPRESSION_INFORMATION:
4485 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4486 SOFF_T(pdata,0,file_size);
4487 SIVAL(pdata,8,0); /* ??? */
4488 SIVAL(pdata,12,0); /* ??? */
4492 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4493 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4494 put_long_date_timespec(pdata,create_time_ts);
4495 put_long_date_timespec(pdata+8,atime_ts);
4496 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4497 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4498 SOFF_T(pdata,32,allocation_size);
4499 SOFF_T(pdata,40,file_size);
4500 SIVAL(pdata,48,mode);
4501 SIVAL(pdata,52,0); /* ??? */
4505 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4506 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4507 SIVAL(pdata,0,mode);
4513 * CIFS UNIX Extensions.
4516 case SMB_QUERY_FILE_UNIX_BASIC:
4518 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4519 data_size = PTR_DIFF(pdata,(*ppdata));
4523 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4525 for (i=0; i<100; i++)
4526 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4532 case SMB_QUERY_FILE_UNIX_INFO2:
4534 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4535 data_size = PTR_DIFF(pdata,(*ppdata));
4539 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4541 for (i=0; i<100; i++)
4542 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4548 case SMB_QUERY_FILE_UNIX_LINK:
4550 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4553 reply_nterror(req, NT_STATUS_NO_MEMORY);
4557 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4559 if(!S_ISLNK(sbuf.st_mode)) {
4560 reply_unixerror(req, ERRSRV,
4565 reply_unixerror(req, ERRDOS, ERRbadlink);
4568 len = SMB_VFS_READLINK(conn,fullpathname,
4571 reply_unixerror(req, ERRDOS,
4576 len = srvstr_push(dstart, req->flags2,
4578 PTR_DIFF(dend, pdata),
4581 data_size = PTR_DIFF(pdata,(*ppdata));
4586 #if defined(HAVE_POSIX_ACLS)
4587 case SMB_QUERY_POSIX_ACL:
4589 SMB_ACL_T file_acl = NULL;
4590 SMB_ACL_T def_acl = NULL;
4591 uint16 num_file_acls = 0;
4592 uint16 num_def_acls = 0;
4594 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4595 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4597 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4600 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4601 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4605 NT_STATUS_NOT_IMPLEMENTED);
4609 if (S_ISDIR(sbuf.st_mode)) {
4610 if (fsp && fsp->is_directory) {
4611 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4613 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4615 def_acl = free_empty_sys_acl(conn, def_acl);
4618 num_file_acls = count_acl_entries(conn, file_acl);
4619 num_def_acls = count_acl_entries(conn, def_acl);
4621 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4622 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4624 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4625 SMB_POSIX_ACL_HEADER_SIZE) ));
4627 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4630 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4634 NT_STATUS_BUFFER_TOO_SMALL);
4638 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4639 SSVAL(pdata,2,num_file_acls);
4640 SSVAL(pdata,4,num_def_acls);
4641 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4643 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4646 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4649 req, NT_STATUS_INTERNAL_ERROR);
4652 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4654 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4657 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4661 NT_STATUS_INTERNAL_ERROR);
4666 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4669 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4671 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4677 case SMB_QUERY_POSIX_LOCK:
4679 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4681 SMB_BIG_UINT offset;
4683 enum brl_type lock_type;
4685 if (total_data != POSIX_LOCK_DATA_SIZE) {
4687 req, NT_STATUS_INVALID_PARAMETER);
4691 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4692 case POSIX_LOCK_TYPE_READ:
4693 lock_type = READ_LOCK;
4695 case POSIX_LOCK_TYPE_WRITE:
4696 lock_type = WRITE_LOCK;
4698 case POSIX_LOCK_TYPE_UNLOCK:
4700 /* There's no point in asking for an unlock... */
4703 NT_STATUS_INVALID_PARAMETER);
4707 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4708 #if defined(HAVE_LONGLONG)
4709 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4710 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4711 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4712 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4713 #else /* HAVE_LONGLONG */
4714 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4715 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4716 #endif /* HAVE_LONGLONG */
4718 status = query_lock(fsp,
4725 if (ERROR_WAS_LOCK_DENIED(status)) {
4726 /* Here we need to report who has it locked... */
4727 data_size = POSIX_LOCK_DATA_SIZE;
4729 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4730 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4731 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4732 #if defined(HAVE_LONGLONG)
4733 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4734 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4735 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4736 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4737 #else /* HAVE_LONGLONG */
4738 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4739 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4740 #endif /* HAVE_LONGLONG */
4742 } else if (NT_STATUS_IS_OK(status)) {
4743 /* For success we just return a copy of what we sent
4744 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4745 data_size = POSIX_LOCK_DATA_SIZE;
4746 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4747 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4749 reply_nterror(req, status);
4756 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4760 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4766 /****************************************************************************
4767 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4769 ****************************************************************************/
4771 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4772 connection_struct *conn,
4773 const char *oldname_in,
4774 const char *newname_in)
4776 SMB_STRUCT_STAT sbuf1, sbuf2;
4777 char *last_component_oldname = NULL;
4778 char *last_component_newname = NULL;
4779 char *oldname = NULL;
4780 char *newname = NULL;
4781 NTSTATUS status = NT_STATUS_OK;
4786 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4787 &last_component_oldname, &sbuf1);
4788 if (!NT_STATUS_IS_OK(status)) {
4792 status = check_name(conn, oldname);
4793 if (!NT_STATUS_IS_OK(status)) {
4797 /* source must already exist. */
4798 if (!VALID_STAT(sbuf1)) {
4799 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4802 status = unix_convert(ctx, conn, newname_in, False, &newname,
4803 &last_component_newname, &sbuf2);
4804 if (!NT_STATUS_IS_OK(status)) {
4808 status = check_name(conn, newname);
4809 if (!NT_STATUS_IS_OK(status)) {
4813 /* Disallow if newname already exists. */
4814 if (VALID_STAT(sbuf2)) {
4815 return NT_STATUS_OBJECT_NAME_COLLISION;
4818 /* No links from a directory. */
4819 if (S_ISDIR(sbuf1.st_mode)) {
4820 return NT_STATUS_FILE_IS_A_DIRECTORY;
4823 /* Ensure this is within the share. */
4824 status = check_reduced_name(conn, oldname);
4825 if (!NT_STATUS_IS_OK(status)) {
4829 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4831 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4832 status = map_nt_error_from_unix(errno);
4833 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4834 nt_errstr(status), newname, oldname));
4840 /****************************************************************************
4841 Deal with setting the time from any of the setfilepathinfo functions.
4842 ****************************************************************************/
4844 NTSTATUS smb_set_file_time(connection_struct *conn,
4847 const SMB_STRUCT_STAT *psbuf,
4848 struct timespec ts[2],
4849 bool setting_write_time)
4852 FILE_NOTIFY_CHANGE_LAST_ACCESS
4853 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4855 if (!VALID_STAT(*psbuf)) {
4856 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4859 /* get some defaults (no modifications) if any info is zero or -1. */
4860 if (null_timespec(ts[0])) {
4861 ts[0] = get_atimespec(psbuf);
4862 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4865 if (null_timespec(ts[1])) {
4866 ts[1] = get_mtimespec(psbuf);
4867 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4870 if (!setting_write_time) {
4871 /* ts[1] comes from change time, not write time. */
4872 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4875 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4876 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4879 * Try and set the times of this file if
4880 * they are different from the current values.
4884 struct timespec mts = get_mtimespec(psbuf);
4885 struct timespec ats = get_atimespec(psbuf);
4886 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4887 return NT_STATUS_OK;
4891 if (setting_write_time) {
4893 * This was a setfileinfo on an open file.
4894 * NT does this a lot. We also need to
4895 * set the time here, as it can be read by
4896 * FindFirst/FindNext and with the patch for bug #2045
4897 * in smbd/fileio.c it ensures that this timestamp is
4898 * kept sticky even after a write. We save the request
4899 * away and will set it on file close and after a write. JRA.
4902 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4903 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4906 set_sticky_write_time_fsp(fsp, ts[1]);
4908 set_sticky_write_time_path(conn, fname,
4909 vfs_file_id_from_sbuf(conn, psbuf),
4914 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4916 if(file_ntimes(conn, fname, ts)!=0) {
4917 return map_nt_error_from_unix(errno);
4919 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4921 return NT_STATUS_OK;
4924 /****************************************************************************
4925 Deal with setting the dosmode from any of the setfilepathinfo functions.
4926 ****************************************************************************/
4928 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4930 SMB_STRUCT_STAT *psbuf,
4933 if (!VALID_STAT(*psbuf)) {
4934 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4938 if (S_ISDIR(psbuf->st_mode)) {
4945 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4947 /* check the mode isn't different, before changing it */
4948 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4950 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4951 fname, (unsigned int)dosmode ));
4953 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
4954 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4955 fname, strerror(errno)));
4956 return map_nt_error_from_unix(errno);
4959 return NT_STATUS_OK;
4962 /****************************************************************************
4963 Deal with setting the size from any of the setfilepathinfo functions.
4964 ****************************************************************************/
4966 static NTSTATUS smb_set_file_size(connection_struct *conn,
4967 struct smb_request *req,
4970 SMB_STRUCT_STAT *psbuf,
4973 NTSTATUS status = NT_STATUS_OK;
4974 files_struct *new_fsp = NULL;
4976 if (!VALID_STAT(*psbuf)) {
4977 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4980 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4982 if (size == get_file_size(*psbuf)) {
4983 return NT_STATUS_OK;
4986 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4987 fname, (double)size ));
4989 if (fsp && fsp->fh->fd != -1) {
4990 /* Handle based call. */
4991 if (vfs_set_filelen(fsp, size) == -1) {
4992 return map_nt_error_from_unix(errno);
4994 trigger_write_time_update_immediate(fsp);
4995 return NT_STATUS_OK;
4998 status = open_file_ntcreate(conn, req, fname, psbuf,
4999 FILE_WRITE_ATTRIBUTES,
5000 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5003 FILE_ATTRIBUTE_NORMAL,
5004 FORCE_OPLOCK_BREAK_TO_NONE,
5007 if (!NT_STATUS_IS_OK(status)) {
5008 /* NB. We check for open_was_deferred in the caller. */
5012 if (vfs_set_filelen(new_fsp, size) == -1) {
5013 status = map_nt_error_from_unix(errno);
5014 close_file(new_fsp,NORMAL_CLOSE);
5018 trigger_write_time_update_immediate(new_fsp);
5019 close_file(new_fsp,NORMAL_CLOSE);
5020 return NT_STATUS_OK;
5023 /****************************************************************************
5024 Deal with SMB_INFO_SET_EA.
5025 ****************************************************************************/
5027 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5033 struct ea_list *ea_list = NULL;
5034 TALLOC_CTX *ctx = NULL;
5035 NTSTATUS status = NT_STATUS_OK;
5037 if (total_data < 10) {
5039 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5040 length. They seem to have no effect. Bug #3212. JRA */
5042 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5043 /* We're done. We only get EA info in this call. */
5044 return NT_STATUS_OK;
5047 return NT_STATUS_INVALID_PARAMETER;
5050 if (IVAL(pdata,0) > total_data) {
5051 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5052 IVAL(pdata,0), (unsigned int)total_data));
5053 return NT_STATUS_INVALID_PARAMETER;
5057 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5059 return NT_STATUS_INVALID_PARAMETER;
5061 status = set_ea(conn, fsp, fname, ea_list);
5066 /****************************************************************************
5067 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5068 ****************************************************************************/
5070 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5075 SMB_STRUCT_STAT *psbuf)
5077 NTSTATUS status = NT_STATUS_OK;
5078 bool delete_on_close;
5081 if (total_data < 1) {
5082 return NT_STATUS_INVALID_PARAMETER;
5086 return NT_STATUS_INVALID_HANDLE;
5089 delete_on_close = (CVAL(pdata,0) ? True : False);
5090 dosmode = dos_mode(conn, fname, psbuf);
5092 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5093 "delete_on_close = %u\n",
5095 (unsigned int)dosmode,
5096 (unsigned int)delete_on_close ));
5098 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5100 if (!NT_STATUS_IS_OK(status)) {
5104 /* The set is across all open files on this dev/inode pair. */
5105 if (!set_delete_on_close(fsp, delete_on_close,
5106 &conn->server_info->utok)) {
5107 return NT_STATUS_ACCESS_DENIED;
5109 return NT_STATUS_OK;
5112 /****************************************************************************
5113 Deal with SMB_FILE_POSITION_INFORMATION.
5114 ****************************************************************************/
5116 static NTSTATUS smb_file_position_information(connection_struct *conn,
5121 SMB_BIG_UINT position_information;
5123 if (total_data < 8) {
5124 return NT_STATUS_INVALID_PARAMETER;
5128 /* Ignore on pathname based set. */
5129 return NT_STATUS_OK;
5132 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
5133 #ifdef LARGE_SMB_OFF_T
5134 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5135 #else /* LARGE_SMB_OFF_T */
5136 if (IVAL(pdata,4) != 0) {
5137 /* more than 32 bits? */
5138 return NT_STATUS_INVALID_PARAMETER;
5140 #endif /* LARGE_SMB_OFF_T */
5142 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5143 fsp->fsp_name, (double)position_information ));
5144 fsp->fh->position_information = position_information;
5145 return NT_STATUS_OK;
5148 /****************************************************************************
5149 Deal with SMB_FILE_MODE_INFORMATION.
5150 ****************************************************************************/
5152 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5158 if (total_data < 4) {
5159 return NT_STATUS_INVALID_PARAMETER;
5161 mode = IVAL(pdata,0);
5162 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5163 return NT_STATUS_INVALID_PARAMETER;
5165 return NT_STATUS_OK;
5168 /****************************************************************************
5169 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5170 ****************************************************************************/
5172 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5173 struct smb_request *req,
5178 char *link_target = NULL;
5179 const char *newname = fname;
5180 NTSTATUS status = NT_STATUS_OK;
5181 TALLOC_CTX *ctx = talloc_tos();
5183 /* Set a symbolic link. */
5184 /* Don't allow this if follow links is false. */
5186 if (total_data == 0) {
5187 return NT_STATUS_INVALID_PARAMETER;
5190 if (!lp_symlinks(SNUM(conn))) {
5191 return NT_STATUS_ACCESS_DENIED;
5194 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5195 total_data, STR_TERMINATE);
5198 return NT_STATUS_INVALID_PARAMETER;
5201 /* !widelinks forces the target path to be within the share. */
5202 /* This means we can interpret the target as a pathname. */
5203 if (!lp_widelinks(SNUM(conn))) {
5204 char *rel_name = NULL;
5205 char *last_dirp = NULL;
5207 if (*link_target == '/') {
5208 /* No absolute paths allowed. */
5209 return NT_STATUS_ACCESS_DENIED;
5211 rel_name = talloc_strdup(ctx,newname);
5213 return NT_STATUS_NO_MEMORY;
5215 last_dirp = strrchr_m(rel_name, '/');
5217 last_dirp[1] = '\0';
5219 rel_name = talloc_strdup(ctx,"./");
5221 return NT_STATUS_NO_MEMORY;
5224 rel_name = talloc_asprintf_append(rel_name,
5228 return NT_STATUS_NO_MEMORY;
5231 status = check_name(conn, rel_name);
5232 if (!NT_STATUS_IS_OK(status)) {
5237 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5238 newname, link_target ));
5240 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5241 return map_nt_error_from_unix(errno);
5244 return NT_STATUS_OK;
5247 /****************************************************************************
5248 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5249 ****************************************************************************/
5251 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5252 struct smb_request *req,
5253 const char *pdata, int total_data,
5256 char *oldname = NULL;
5257 TALLOC_CTX *ctx = talloc_tos();
5258 NTSTATUS status = NT_STATUS_OK;
5260 /* Set a hard link. */
5261 if (total_data == 0) {
5262 return NT_STATUS_INVALID_PARAMETER;
5265 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5266 total_data, STR_TERMINATE, &status);
5267 if (!NT_STATUS_IS_OK(status)) {
5271 status = resolve_dfspath(ctx, conn,
5272 req->flags2 & FLAGS2_DFS_PATHNAMES,
5275 if (!NT_STATUS_IS_OK(status)) {
5279 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5282 return hardlink_internals(ctx, conn, oldname, fname);
5285 /****************************************************************************
5286 Deal with SMB_FILE_RENAME_INFORMATION.
5287 ****************************************************************************/
5289 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5290 struct smb_request *req,
5299 char *newname = NULL;
5300 char *base_name = NULL;
5301 bool dest_has_wcard = False;
5302 NTSTATUS status = NT_STATUS_OK;
5304 TALLOC_CTX *ctx = talloc_tos();
5306 if (total_data < 13) {
5307 return NT_STATUS_INVALID_PARAMETER;
5310 overwrite = (CVAL(pdata,0) ? True : False);
5311 root_fid = IVAL(pdata,4);
5312 len = IVAL(pdata,8);
5314 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5315 return NT_STATUS_INVALID_PARAMETER;
5318 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5321 if (!NT_STATUS_IS_OK(status)) {
5325 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5328 status = resolve_dfspath_wcard(ctx, conn,
5329 req->flags2 & FLAGS2_DFS_PATHNAMES,
5333 if (!NT_STATUS_IS_OK(status)) {
5337 /* Check the new name has no '/' characters. */
5338 if (strchr_m(newname, '/')) {
5339 return NT_STATUS_NOT_SUPPORTED;
5342 /* Create the base directory. */
5343 base_name = talloc_strdup(ctx, fname);
5345 return NT_STATUS_NO_MEMORY;
5347 p = strrchr_m(base_name, '/');
5351 base_name = talloc_strdup(ctx, "./");
5353 return NT_STATUS_NO_MEMORY;
5356 /* Append the new name. */
5357 base_name = talloc_asprintf_append(base_name,
5361 return NT_STATUS_NO_MEMORY;
5365 SMB_STRUCT_STAT sbuf;
5366 char *newname_last_component = NULL;
5370 status = unix_convert(ctx, conn, newname, False,
5372 &newname_last_component,
5375 /* If an error we expect this to be
5376 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5378 if (!NT_STATUS_IS_OK(status)
5379 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5384 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5385 fsp->fnum, fsp->fsp_name, base_name ));
5386 status = rename_internals_fsp(conn, fsp, base_name,
5387 newname_last_component, 0,
5390 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5391 fname, base_name ));
5392 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5393 overwrite, False, dest_has_wcard,
5394 FILE_WRITE_ATTRIBUTES);
5400 /****************************************************************************
5401 Deal with SMB_SET_POSIX_ACL.
5402 ****************************************************************************/
5404 #if defined(HAVE_POSIX_ACLS)
5405 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5410 SMB_STRUCT_STAT *psbuf)
5412 uint16 posix_acl_version;
5413 uint16 num_file_acls;
5414 uint16 num_def_acls;
5415 bool valid_file_acls = True;
5416 bool valid_def_acls = True;
5418 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5419 return NT_STATUS_INVALID_PARAMETER;
5421 posix_acl_version = SVAL(pdata,0);
5422 num_file_acls = SVAL(pdata,2);
5423 num_def_acls = SVAL(pdata,4);
5425 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5426 valid_file_acls = False;
5430 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5431 valid_def_acls = False;
5435 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5436 return NT_STATUS_INVALID_PARAMETER;
5439 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5440 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5441 return NT_STATUS_INVALID_PARAMETER;
5444 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5445 fname ? fname : fsp->fsp_name,
5446 (unsigned int)num_file_acls,
5447 (unsigned int)num_def_acls));
5449 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5450 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5451 return map_nt_error_from_unix(errno);
5454 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5455 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5456 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5457 return map_nt_error_from_unix(errno);
5459 return NT_STATUS_OK;
5463 /****************************************************************************
5464 Deal with SMB_SET_POSIX_LOCK.
5465 ****************************************************************************/
5467 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5468 const struct smb_request *req,
5474 SMB_BIG_UINT offset;
5476 bool blocking_lock = False;
5477 enum brl_type lock_type;
5479 NTSTATUS status = NT_STATUS_OK;
5481 if (fsp == NULL || fsp->fh->fd == -1) {
5482 return NT_STATUS_INVALID_HANDLE;
5485 if (total_data != POSIX_LOCK_DATA_SIZE) {
5486 return NT_STATUS_INVALID_PARAMETER;
5489 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5490 case POSIX_LOCK_TYPE_READ:
5491 lock_type = READ_LOCK;
5493 case POSIX_LOCK_TYPE_WRITE:
5494 /* Return the right POSIX-mappable error code for files opened read-only. */
5495 if (!fsp->can_write) {
5496 return NT_STATUS_INVALID_HANDLE;
5498 lock_type = WRITE_LOCK;
5500 case POSIX_LOCK_TYPE_UNLOCK:
5501 lock_type = UNLOCK_LOCK;
5504 return NT_STATUS_INVALID_PARAMETER;
5507 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5508 blocking_lock = False;
5509 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5510 blocking_lock = True;
5512 return NT_STATUS_INVALID_PARAMETER;
5515 if (!lp_blocking_locks(SNUM(conn))) {
5516 blocking_lock = False;
5519 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5520 #if defined(HAVE_LONGLONG)
5521 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5522 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5523 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5524 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5525 #else /* HAVE_LONGLONG */
5526 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5527 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5528 #endif /* HAVE_LONGLONG */
5530 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5531 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5533 (unsigned int)lock_type,
5534 (unsigned int)lock_pid,
5538 if (lock_type == UNLOCK_LOCK) {
5539 status = do_unlock(smbd_messaging_context(),
5546 uint32 block_smbpid;
5548 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5559 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5561 * A blocking lock was requested. Package up
5562 * this smb into a queued request and push it
5563 * onto the blocking lock queue.
5565 if(push_blocking_lock_request(br_lck,
5568 -1, /* infinite timeout. */
5576 TALLOC_FREE(br_lck);
5580 TALLOC_FREE(br_lck);
5586 /****************************************************************************
5587 Deal with SMB_INFO_STANDARD.
5588 ****************************************************************************/
5590 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5595 const SMB_STRUCT_STAT *psbuf)
5597 struct timespec ts[2];
5599 if (total_data < 12) {
5600 return NT_STATUS_INVALID_PARAMETER;
5604 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5606 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5608 DEBUG(10,("smb_set_info_standard: file %s\n",
5609 fname ? fname : fsp->fsp_name ));
5611 return smb_set_file_time(conn,
5619 /****************************************************************************
5620 Deal with SMB_SET_FILE_BASIC_INFO.
5621 ****************************************************************************/
5623 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5628 SMB_STRUCT_STAT *psbuf)
5630 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5631 struct timespec write_time;
5632 struct timespec changed_time;
5634 struct timespec ts[2];
5635 NTSTATUS status = NT_STATUS_OK;
5636 bool setting_write_time = true;
5638 if (total_data < 36) {
5639 return NT_STATUS_INVALID_PARAMETER;
5642 /* Set the attributes */
5643 dosmode = IVAL(pdata,32);
5644 status = smb_set_file_dosmode(conn,
5648 if (!NT_STATUS_IS_OK(status)) {
5652 /* Ignore create time at offset pdata. */
5655 ts[0] = interpret_long_date(pdata+8);
5657 write_time = interpret_long_date(pdata+16);
5658 changed_time = interpret_long_date(pdata+24);
5661 ts[1] = timespec_min(&write_time, &changed_time);
5663 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5667 /* Prefer a defined time to an undefined one. */
5668 if (null_timespec(ts[1])) {
5669 if (null_timespec(write_time)) {
5670 ts[1] = changed_time;
5671 setting_write_time = false;
5677 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5678 fname ? fname : fsp->fsp_name ));
5680 return smb_set_file_time(conn,
5685 setting_write_time);
5688 /****************************************************************************
5689 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5690 ****************************************************************************/
5692 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5693 struct smb_request *req,
5698 SMB_STRUCT_STAT *psbuf)
5700 SMB_BIG_UINT allocation_size = 0;
5701 NTSTATUS status = NT_STATUS_OK;
5702 files_struct *new_fsp = NULL;
5704 if (!VALID_STAT(*psbuf)) {
5705 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5708 if (total_data < 8) {
5709 return NT_STATUS_INVALID_PARAMETER;
5712 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5713 #ifdef LARGE_SMB_OFF_T
5714 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5715 #else /* LARGE_SMB_OFF_T */
5716 if (IVAL(pdata,4) != 0) {
5717 /* more than 32 bits? */
5718 return NT_STATUS_INVALID_PARAMETER;
5720 #endif /* LARGE_SMB_OFF_T */
5722 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5723 fname, (double)allocation_size ));
5725 if (allocation_size) {
5726 allocation_size = smb_roundup(conn, allocation_size);
5729 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5730 fname, (double)allocation_size ));
5732 if (fsp && fsp->fh->fd != -1) {
5733 /* Open file handle. */
5734 /* Only change if needed. */
5735 if (allocation_size != get_file_size(*psbuf)) {
5736 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5737 return map_nt_error_from_unix(errno);
5740 /* But always update the time. */
5742 * This is equivalent to a write. Ensure it's seen immediately
5743 * if there are no pending writes.
5745 trigger_write_time_update_immediate(fsp);
5746 return NT_STATUS_OK;
5749 /* Pathname or stat or directory file. */
5751 status = open_file_ntcreate(conn, req, fname, psbuf,
5753 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5756 FILE_ATTRIBUTE_NORMAL,
5757 FORCE_OPLOCK_BREAK_TO_NONE,
5760 if (!NT_STATUS_IS_OK(status)) {
5761 /* NB. We check for open_was_deferred in the caller. */
5765 /* Only change if needed. */
5766 if (allocation_size != get_file_size(*psbuf)) {
5767 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5768 status = map_nt_error_from_unix(errno);
5769 close_file(new_fsp,NORMAL_CLOSE);
5774 /* Changing the allocation size should set the last mod time. */
5776 * This is equivalent to a write. Ensure it's seen immediately
5777 * if there are no pending writes.
5779 trigger_write_time_update_immediate(new_fsp);
5781 close_file(new_fsp,NORMAL_CLOSE);
5782 return NT_STATUS_OK;
5785 /****************************************************************************
5786 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5787 ****************************************************************************/
5789 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5790 struct smb_request *req,
5795 SMB_STRUCT_STAT *psbuf)
5799 if (total_data < 8) {
5800 return NT_STATUS_INVALID_PARAMETER;
5803 size = IVAL(pdata,0);
5804 #ifdef LARGE_SMB_OFF_T
5805 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5806 #else /* LARGE_SMB_OFF_T */
5807 if (IVAL(pdata,4) != 0) {
5808 /* more than 32 bits? */
5809 return NT_STATUS_INVALID_PARAMETER;
5811 #endif /* LARGE_SMB_OFF_T */
5812 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5813 "file %s to %.0f\n", fname, (double)size ));
5815 return smb_set_file_size(conn, req,
5822 /****************************************************************************
5823 Allow a UNIX info mknod.
5824 ****************************************************************************/
5826 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5830 SMB_STRUCT_STAT *psbuf)
5832 uint32 file_type = IVAL(pdata,56);
5833 #if defined(HAVE_MAKEDEV)
5834 uint32 dev_major = IVAL(pdata,60);
5835 uint32 dev_minor = IVAL(pdata,68);
5837 SMB_DEV_T dev = (SMB_DEV_T)0;
5838 uint32 raw_unixmode = IVAL(pdata,84);
5842 if (total_data < 100) {
5843 return NT_STATUS_INVALID_PARAMETER;
5846 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5847 if (!NT_STATUS_IS_OK(status)) {
5851 #if defined(HAVE_MAKEDEV)
5852 dev = makedev(dev_major, dev_minor);
5855 switch (file_type) {
5856 #if defined(S_IFIFO)
5857 case UNIX_TYPE_FIFO:
5858 unixmode |= S_IFIFO;
5861 #if defined(S_IFSOCK)
5862 case UNIX_TYPE_SOCKET:
5863 unixmode |= S_IFSOCK;
5866 #if defined(S_IFCHR)
5867 case UNIX_TYPE_CHARDEV:
5868 unixmode |= S_IFCHR;
5871 #if defined(S_IFBLK)
5872 case UNIX_TYPE_BLKDEV:
5873 unixmode |= S_IFBLK;
5877 return NT_STATUS_INVALID_PARAMETER;
5880 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5881 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5883 /* Ok - do the mknod. */
5884 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5885 return map_nt_error_from_unix(errno);
5888 /* If any of the other "set" calls fail we
5889 * don't want to end up with a half-constructed mknod.
5892 if (lp_inherit_perms(SNUM(conn))) {
5893 inherit_access_posix_acl(
5894 conn, parent_dirname(fname),
5898 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5899 status = map_nt_error_from_unix(errno);
5900 SMB_VFS_UNLINK(conn,fname);
5903 return NT_STATUS_OK;
5906 /****************************************************************************
5907 Deal with SMB_SET_FILE_UNIX_BASIC.
5908 ****************************************************************************/
5910 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5911 struct smb_request *req,
5916 SMB_STRUCT_STAT *psbuf)
5918 struct timespec ts[2];
5919 uint32 raw_unixmode;
5922 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5923 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5924 NTSTATUS status = NT_STATUS_OK;
5925 bool delete_on_fail = False;
5926 enum perm_type ptype;
5928 if (total_data < 100) {
5929 return NT_STATUS_INVALID_PARAMETER;
5932 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5933 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5934 size=IVAL(pdata,0); /* first 8 Bytes are size */
5935 #ifdef LARGE_SMB_OFF_T
5936 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5937 #else /* LARGE_SMB_OFF_T */
5938 if (IVAL(pdata,4) != 0) {
5939 /* more than 32 bits? */
5940 return NT_STATUS_INVALID_PARAMETER;
5942 #endif /* LARGE_SMB_OFF_T */
5945 ts[0] = interpret_long_date(pdata+24); /* access_time */
5946 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5947 set_owner = (uid_t)IVAL(pdata,40);
5948 set_grp = (gid_t)IVAL(pdata,48);
5949 raw_unixmode = IVAL(pdata,84);
5951 if (VALID_STAT(*psbuf)) {
5952 if (S_ISDIR(psbuf->st_mode)) {
5953 ptype = PERM_EXISTING_DIR;
5955 ptype = PERM_EXISTING_FILE;
5958 ptype = PERM_NEW_FILE;
5961 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5962 if (!NT_STATUS_IS_OK(status)) {
5966 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5967 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5968 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5970 if (!VALID_STAT(*psbuf)) {
5972 * The only valid use of this is to create character and block
5973 * devices, and named pipes. This is deprecated (IMHO) and
5974 * a new info level should be used for mknod. JRA.
5977 status = smb_unix_mknod(conn,
5982 if (!NT_STATUS_IS_OK(status)) {
5986 /* Ensure we don't try and change anything else. */
5987 raw_unixmode = SMB_MODE_NO_CHANGE;
5988 size = get_file_size(*psbuf);
5989 ts[0] = get_atimespec(psbuf);
5990 ts[1] = get_mtimespec(psbuf);
5992 * We continue here as we might want to change the
5995 delete_on_fail = True;
5999 /* Horrible backwards compatibility hack as an old server bug
6000 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6004 size = get_file_size(*psbuf);
6009 * Deal with the UNIX specific mode set.
6012 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6013 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6014 (unsigned int)unixmode, fname ));
6015 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6016 return map_nt_error_from_unix(errno);
6021 * Deal with the UNIX specific uid set.
6024 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
6027 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6028 (unsigned int)set_owner, fname ));
6030 if (S_ISLNK(psbuf->st_mode)) {
6031 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6033 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6037 status = map_nt_error_from_unix(errno);
6038 if (delete_on_fail) {
6039 SMB_VFS_UNLINK(conn,fname);
6046 * Deal with the UNIX specific gid set.
6049 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
6050 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6051 (unsigned int)set_owner, fname ));
6052 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6053 status = map_nt_error_from_unix(errno);
6054 if (delete_on_fail) {
6055 SMB_VFS_UNLINK(conn,fname);
6061 /* Deal with any size changes. */
6063 status = smb_set_file_size(conn, req,
6068 if (!NT_STATUS_IS_OK(status)) {
6072 /* Deal with any time changes. */
6074 return smb_set_file_time(conn,
6082 /****************************************************************************
6083 Deal with SMB_SET_FILE_UNIX_INFO2.
6084 ****************************************************************************/
6086 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6087 struct smb_request *req,
6092 SMB_STRUCT_STAT *psbuf)
6098 if (total_data < 116) {
6099 return NT_STATUS_INVALID_PARAMETER;
6102 /* Start by setting all the fields that are common between UNIX_BASIC
6105 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6107 if (!NT_STATUS_IS_OK(status)) {
6111 smb_fflags = IVAL(pdata, 108);
6112 smb_fmask = IVAL(pdata, 112);
6114 /* NB: We should only attempt to alter the file flags if the client
6115 * sends a non-zero mask.
6117 if (smb_fmask != 0) {
6118 int stat_fflags = 0;
6120 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6122 /* Client asked to alter a flag we don't understand. */
6123 return NT_STATUS_INVALID_PARAMETER;
6126 if (fsp && fsp->fh->fd != -1) {
6127 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6128 return NT_STATUS_NOT_SUPPORTED;
6130 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6131 return map_nt_error_from_unix(errno);
6136 /* XXX: need to add support for changing the create_time here. You
6137 * can do this for paths on Darwin with setattrlist(2). The right way
6138 * to hook this up is probably by extending the VFS utimes interface.
6141 return NT_STATUS_OK;
6144 /****************************************************************************
6145 Create a directory with POSIX semantics.
6146 ****************************************************************************/
6148 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6149 struct smb_request *req,
6153 SMB_STRUCT_STAT *psbuf,
6154 int *pdata_return_size)
6156 NTSTATUS status = NT_STATUS_OK;
6157 uint32 raw_unixmode = 0;
6158 uint32 mod_unixmode = 0;
6159 mode_t unixmode = (mode_t)0;
6160 files_struct *fsp = NULL;
6161 uint16 info_level_return = 0;
6163 char *pdata = *ppdata;
6165 if (total_data < 18) {
6166 return NT_STATUS_INVALID_PARAMETER;
6169 raw_unixmode = IVAL(pdata,8);
6170 /* Next 4 bytes are not yet defined. */
6172 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6173 if (!NT_STATUS_IS_OK(status)) {
6177 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6179 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6180 fname, (unsigned int)unixmode ));
6182 status = open_directory(conn, req,
6185 FILE_READ_ATTRIBUTES, /* Just a stat open */
6186 FILE_SHARE_NONE, /* Ignored for stat opens */
6193 if (NT_STATUS_IS_OK(status)) {
6194 close_file(fsp, NORMAL_CLOSE);
6197 info_level_return = SVAL(pdata,16);
6199 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6200 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6201 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6202 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6204 *pdata_return_size = 12;
6207 /* Realloc the data size */
6208 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6209 if (*ppdata == NULL) {
6210 *pdata_return_size = 0;
6211 return NT_STATUS_NO_MEMORY;
6215 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6216 SSVAL(pdata,2,0); /* No fnum. */
6217 SIVAL(pdata,4,info); /* Was directory created. */
6219 switch (info_level_return) {
6220 case SMB_QUERY_FILE_UNIX_BASIC:
6221 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6222 SSVAL(pdata,10,0); /* Padding. */
6223 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6225 case SMB_QUERY_FILE_UNIX_INFO2:
6226 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6227 SSVAL(pdata,10,0); /* Padding. */
6228 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6231 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6232 SSVAL(pdata,10,0); /* Padding. */
6239 /****************************************************************************
6240 Open/Create a file with POSIX semantics.
6241 ****************************************************************************/
6243 static NTSTATUS smb_posix_open(connection_struct *conn,
6244 struct smb_request *req,
6248 SMB_STRUCT_STAT *psbuf,
6249 int *pdata_return_size)
6251 bool extended_oplock_granted = False;
6252 char *pdata = *ppdata;
6254 uint32 wire_open_mode = 0;
6255 uint32 raw_unixmode = 0;
6256 uint32 mod_unixmode = 0;
6257 uint32 create_disp = 0;
6258 uint32 access_mask = 0;
6259 uint32 create_options = 0;
6260 NTSTATUS status = NT_STATUS_OK;
6261 mode_t unixmode = (mode_t)0;
6262 files_struct *fsp = NULL;
6263 int oplock_request = 0;
6265 uint16 info_level_return = 0;
6267 if (total_data < 18) {
6268 return NT_STATUS_INVALID_PARAMETER;
6271 flags = IVAL(pdata,0);
6272 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6273 if (oplock_request) {
6274 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6277 wire_open_mode = IVAL(pdata,4);
6279 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6280 return smb_posix_mkdir(conn, req,
6288 switch (wire_open_mode & SMB_ACCMODE) {
6290 access_mask = FILE_READ_DATA;
6293 access_mask = FILE_WRITE_DATA;
6296 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6299 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6300 (unsigned int)wire_open_mode ));
6301 return NT_STATUS_INVALID_PARAMETER;
6304 wire_open_mode &= ~SMB_ACCMODE;
6306 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6307 create_disp = FILE_CREATE;
6308 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6309 create_disp = FILE_OVERWRITE_IF;
6310 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6311 create_disp = FILE_OPEN_IF;
6313 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6314 (unsigned int)wire_open_mode ));
6315 return NT_STATUS_INVALID_PARAMETER;
6318 raw_unixmode = IVAL(pdata,8);
6319 /* Next 4 bytes are not yet defined. */
6321 status = unix_perms_from_wire(conn,
6324 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6327 if (!NT_STATUS_IS_OK(status)) {
6331 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6333 if (wire_open_mode & SMB_O_SYNC) {
6334 create_options |= FILE_WRITE_THROUGH;
6336 if (wire_open_mode & SMB_O_APPEND) {
6337 access_mask |= FILE_APPEND_DATA;
6339 if (wire_open_mode & SMB_O_DIRECT) {
6340 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6343 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6345 (unsigned int)wire_open_mode,
6346 (unsigned int)unixmode ));
6348 status = open_file_ntcreate(conn, req,
6352 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6354 0, /* no create options yet. */
6360 if (!NT_STATUS_IS_OK(status)) {
6364 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6365 extended_oplock_granted = True;
6368 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6369 extended_oplock_granted = True;
6372 info_level_return = SVAL(pdata,16);
6374 /* Allocate the correct return size. */
6376 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6377 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6378 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6379 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6381 *pdata_return_size = 12;
6384 /* Realloc the data size */
6385 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6386 if (*ppdata == NULL) {
6387 close_file(fsp,ERROR_CLOSE);
6388 *pdata_return_size = 0;
6389 return NT_STATUS_NO_MEMORY;
6393 if (extended_oplock_granted) {
6394 if (flags & REQUEST_BATCH_OPLOCK) {
6395 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6397 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6399 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6400 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6402 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6405 SSVAL(pdata,2,fsp->fnum);
6406 SIVAL(pdata,4,info); /* Was file created etc. */
6408 switch (info_level_return) {
6409 case SMB_QUERY_FILE_UNIX_BASIC:
6410 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6411 SSVAL(pdata,10,0); /* padding. */
6412 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6414 case SMB_QUERY_FILE_UNIX_INFO2:
6415 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6416 SSVAL(pdata,10,0); /* padding. */
6417 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6420 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6421 SSVAL(pdata,10,0); /* padding. */
6424 return NT_STATUS_OK;
6427 /****************************************************************************
6428 Delete a file with POSIX semantics.
6429 ****************************************************************************/
6431 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6432 struct smb_request *req,
6436 SMB_STRUCT_STAT *psbuf)
6438 NTSTATUS status = NT_STATUS_OK;
6439 files_struct *fsp = NULL;
6444 struct share_mode_lock *lck = NULL;
6446 if (total_data < 2) {
6447 return NT_STATUS_INVALID_PARAMETER;
6450 flags = SVAL(pdata,0);
6452 if (!VALID_STAT(*psbuf)) {
6453 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6456 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6457 !VALID_STAT_OF_DIR(*psbuf)) {
6458 return NT_STATUS_NOT_A_DIRECTORY;
6461 DEBUG(10,("smb_posix_unlink: %s %s\n",
6462 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6465 if (VALID_STAT_OF_DIR(*psbuf)) {
6466 status = open_directory(conn, req,
6470 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6473 FILE_FLAG_POSIX_SEMANTICS|0777,
6478 status = open_file_ntcreate(conn, req,
6482 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6485 FILE_FLAG_POSIX_SEMANTICS|0777,
6486 0, /* No oplock, but break existing ones. */
6491 if (!NT_STATUS_IS_OK(status)) {
6496 * Don't lie to client. If we can't really delete due to
6497 * non-POSIX opens return SHARING_VIOLATION.
6500 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6503 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6504 "lock for file %s\n", fsp->fsp_name));
6505 close_file(fsp, NORMAL_CLOSE);
6506 return NT_STATUS_INVALID_PARAMETER;
6510 * See if others still have the file open. If this is the case, then
6511 * don't delete. If all opens are POSIX delete we can set the delete
6512 * on close disposition.
6514 for (i=0; i<lck->num_share_modes; i++) {
6515 struct share_mode_entry *e = &lck->share_modes[i];
6516 if (is_valid_share_mode_entry(e)) {
6517 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6520 /* Fail with sharing violation. */
6521 close_file(fsp, NORMAL_CLOSE);
6523 return NT_STATUS_SHARING_VIOLATION;
6528 * Set the delete on close.
6530 status = smb_set_file_disposition_info(conn,
6537 if (!NT_STATUS_IS_OK(status)) {
6538 close_file(fsp, NORMAL_CLOSE);
6543 return close_file(fsp, NORMAL_CLOSE);
6546 /****************************************************************************
6547 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6548 ****************************************************************************/
6550 static void call_trans2setfilepathinfo(connection_struct *conn,
6551 struct smb_request *req,
6552 unsigned int tran_call,
6553 char **pparams, int total_params,
6554 char **ppdata, int total_data,
6555 unsigned int max_data_bytes)
6557 char *params = *pparams;
6558 char *pdata = *ppdata;
6560 SMB_STRUCT_STAT sbuf;
6562 files_struct *fsp = NULL;
6563 NTSTATUS status = NT_STATUS_OK;
6564 int data_return_size = 0;
6565 TALLOC_CTX *ctx = talloc_tos();
6568 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6574 if (tran_call == TRANSACT2_SETFILEINFO) {
6575 if (total_params < 4) {
6576 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6580 fsp = file_fsp(SVAL(params,0));
6581 /* Basic check for non-null fsp. */
6582 if (!check_fsp_open(conn, req, fsp)) {
6585 info_level = SVAL(params,2);
6587 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6589 reply_nterror(req, NT_STATUS_NO_MEMORY);
6593 if(fsp->is_directory || fsp->fh->fd == -1) {
6595 * This is actually a SETFILEINFO on a directory
6596 * handle (returned from an NT SMB). NT5.0 seems
6597 * to do this call. JRA.
6599 if (INFO_LEVEL_IS_UNIX(info_level)) {
6600 /* Always do lstat for UNIX calls. */
6601 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6602 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6603 reply_unixerror(req,ERRDOS,ERRbadpath);
6607 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6608 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6609 reply_unixerror(req,ERRDOS,ERRbadpath);
6613 } else if (fsp->print_file) {
6615 * Doing a DELETE_ON_CLOSE should cancel a print job.
6617 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6618 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6620 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6623 send_trans2_replies(conn, req, params, 2,
6628 reply_unixerror(req, ERRDOS, ERRbadpath);
6633 * Original code - this is an open file.
6635 if (!check_fsp(conn, req, fsp)) {
6639 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6640 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6641 reply_unixerror(req, ERRDOS, ERRbadfid);
6647 if (total_params < 7) {
6648 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6652 info_level = SVAL(params,0);
6653 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
6654 total_params - 6, STR_TERMINATE,
6656 if (!NT_STATUS_IS_OK(status)) {
6657 reply_nterror(req, status);
6661 status = resolve_dfspath(ctx, conn,
6662 req->flags2 & FLAGS2_DFS_PATHNAMES,
6665 if (!NT_STATUS_IS_OK(status)) {
6666 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6667 reply_botherror(req,
6668 NT_STATUS_PATH_NOT_COVERED,
6669 ERRSRV, ERRbadpath);
6672 reply_nterror(req, status);
6676 status = unix_convert(ctx, conn, fname, False,
6677 &fname, NULL, &sbuf);
6678 if (!NT_STATUS_IS_OK(status)) {
6679 reply_nterror(req, status);
6683 status = check_name(conn, fname);
6684 if (!NT_STATUS_IS_OK(status)) {
6685 reply_nterror(req, status);
6689 if (INFO_LEVEL_IS_UNIX(info_level)) {
6691 * For CIFS UNIX extensions the target name may not exist.
6694 /* Always do lstat for UNIX calls. */
6695 SMB_VFS_LSTAT(conn,fname,&sbuf);
6697 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6698 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6699 reply_unixerror(req, ERRDOS, ERRbadpath);
6704 if (!CAN_WRITE(conn)) {
6705 reply_doserror(req, ERRSRV, ERRaccess);
6709 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6710 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6714 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6715 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6717 /* Realloc the parameter size */
6718 *pparams = (char *)SMB_REALLOC(*pparams,2);
6719 if (*pparams == NULL) {
6720 reply_nterror(req, NT_STATUS_NO_MEMORY);
6727 switch (info_level) {
6729 case SMB_INFO_STANDARD:
6731 status = smb_set_info_standard(conn,
6740 case SMB_INFO_SET_EA:
6742 status = smb_info_set_ea(conn,
6750 case SMB_SET_FILE_BASIC_INFO:
6751 case SMB_FILE_BASIC_INFORMATION:
6753 status = smb_set_file_basic_info(conn,
6762 case SMB_FILE_ALLOCATION_INFORMATION:
6763 case SMB_SET_FILE_ALLOCATION_INFO:
6765 status = smb_set_file_allocation_info(conn, req,
6774 case SMB_FILE_END_OF_FILE_INFORMATION:
6775 case SMB_SET_FILE_END_OF_FILE_INFO:
6777 status = smb_set_file_end_of_file_info(conn, req,
6786 case SMB_FILE_DISPOSITION_INFORMATION:
6787 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6790 /* JRA - We used to just ignore this on a path ?
6791 * Shouldn't this be invalid level on a pathname
6794 if (tran_call != TRANSACT2_SETFILEINFO) {
6795 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6798 status = smb_set_file_disposition_info(conn,
6807 case SMB_FILE_POSITION_INFORMATION:
6809 status = smb_file_position_information(conn,
6816 /* From tridge Samba4 :
6817 * MODE_INFORMATION in setfileinfo (I have no
6818 * idea what "mode information" on a file is - it takes a value of 0,
6819 * 2, 4 or 6. What could it be?).
6822 case SMB_FILE_MODE_INFORMATION:
6824 status = smb_file_mode_information(conn,
6831 * CIFS UNIX extensions.
6834 case SMB_SET_FILE_UNIX_BASIC:
6836 status = smb_set_file_unix_basic(conn, req,
6845 case SMB_SET_FILE_UNIX_INFO2:
6847 status = smb_set_file_unix_info2(conn, req,
6856 case SMB_SET_FILE_UNIX_LINK:
6858 if (tran_call != TRANSACT2_SETPATHINFO) {
6859 /* We must have a pathname for this. */
6860 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6863 status = smb_set_file_unix_link(conn, req, pdata,
6868 case SMB_SET_FILE_UNIX_HLINK:
6870 if (tran_call != TRANSACT2_SETPATHINFO) {
6871 /* We must have a pathname for this. */
6872 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6875 status = smb_set_file_unix_hlink(conn, req,
6881 case SMB_FILE_RENAME_INFORMATION:
6883 status = smb_file_rename_information(conn, req,
6889 #if defined(HAVE_POSIX_ACLS)
6890 case SMB_SET_POSIX_ACL:
6892 status = smb_set_posix_acl(conn,
6902 case SMB_SET_POSIX_LOCK:
6904 if (tran_call != TRANSACT2_SETFILEINFO) {
6905 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6908 status = smb_set_posix_lock(conn, req,
6909 pdata, total_data, fsp);
6913 case SMB_POSIX_PATH_OPEN:
6915 if (tran_call != TRANSACT2_SETPATHINFO) {
6916 /* We must have a pathname for this. */
6917 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6921 status = smb_posix_open(conn, req,
6930 case SMB_POSIX_PATH_UNLINK:
6932 if (tran_call != TRANSACT2_SETPATHINFO) {
6933 /* We must have a pathname for this. */
6934 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6938 status = smb_posix_unlink(conn, req,
6947 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6952 if (!NT_STATUS_IS_OK(status)) {
6953 if (open_was_deferred(req->mid)) {
6954 /* We have re-scheduled this call. */
6957 if (blocking_lock_was_deferred(req->mid)) {
6958 /* We have re-scheduled this call. */
6961 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6962 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6963 ERRSRV, ERRbadpath);
6966 if (info_level == SMB_POSIX_PATH_OPEN) {
6967 reply_openerror(req, status);
6971 reply_nterror(req, status);
6976 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
6982 /****************************************************************************
6983 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6984 ****************************************************************************/
6986 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
6987 char **pparams, int total_params,
6988 char **ppdata, int total_data,
6989 unsigned int max_data_bytes)
6991 char *params = *pparams;
6992 char *pdata = *ppdata;
6993 char *directory = NULL;
6994 SMB_STRUCT_STAT sbuf;
6995 NTSTATUS status = NT_STATUS_OK;
6996 struct ea_list *ea_list = NULL;
6997 TALLOC_CTX *ctx = talloc_tos();
6999 if (!CAN_WRITE(conn)) {
7000 reply_doserror(req, ERRSRV, ERRaccess);
7004 if (total_params < 5) {
7005 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7009 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7010 total_params - 4, STR_TERMINATE,
7012 if (!NT_STATUS_IS_OK(status)) {
7013 reply_nterror(req, status);
7017 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7019 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
7020 if (!NT_STATUS_IS_OK(status)) {
7021 reply_nterror(req, status);
7025 status = check_name(conn, directory);
7026 if (!NT_STATUS_IS_OK(status)) {
7027 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7028 reply_nterror(req, status);
7032 /* Any data in this call is an EA list. */
7033 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7034 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7039 * OS/2 workplace shell seems to send SET_EA requests of "null"
7040 * length (4 bytes containing IVAL 4).
7041 * They seem to have no effect. Bug #3212. JRA.
7044 if (total_data != 4) {
7045 if (total_data < 10) {
7046 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7050 if (IVAL(pdata,0) > total_data) {
7051 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7052 IVAL(pdata,0), (unsigned int)total_data));
7053 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7057 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7060 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7063 } else if (IVAL(pdata,0) != 4) {
7064 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7068 status = create_directory(conn, req, directory);
7070 if (!NT_STATUS_IS_OK(status)) {
7071 reply_nterror(req, status);
7075 /* Try and set any given EA. */
7077 status = set_ea(conn, NULL, directory, ea_list);
7078 if (!NT_STATUS_IS_OK(status)) {
7079 reply_nterror(req, status);
7084 /* Realloc the parameter and data sizes */
7085 *pparams = (char *)SMB_REALLOC(*pparams,2);
7086 if(*pparams == NULL) {
7087 reply_nterror(req, NT_STATUS_NO_MEMORY);
7094 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7099 /****************************************************************************
7100 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7101 We don't actually do this - we just send a null response.
7102 ****************************************************************************/
7104 static void call_trans2findnotifyfirst(connection_struct *conn,
7105 struct smb_request *req,
7106 char **pparams, int total_params,
7107 char **ppdata, int total_data,
7108 unsigned int max_data_bytes)
7110 static uint16 fnf_handle = 257;
7111 char *params = *pparams;
7114 if (total_params < 6) {
7115 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7119 info_level = SVAL(params,4);
7120 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7122 switch (info_level) {
7127 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7131 /* Realloc the parameter and data sizes */
7132 *pparams = (char *)SMB_REALLOC(*pparams,6);
7133 if (*pparams == NULL) {
7134 reply_nterror(req, NT_STATUS_NO_MEMORY);
7139 SSVAL(params,0,fnf_handle);
7140 SSVAL(params,2,0); /* No changes */
7141 SSVAL(params,4,0); /* No EA errors */
7148 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7153 /****************************************************************************
7154 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7155 changes). Currently this does nothing.
7156 ****************************************************************************/
7158 static void call_trans2findnotifynext(connection_struct *conn,
7159 struct smb_request *req,
7160 char **pparams, int total_params,
7161 char **ppdata, int total_data,
7162 unsigned int max_data_bytes)
7164 char *params = *pparams;
7166 DEBUG(3,("call_trans2findnotifynext\n"));
7168 /* Realloc the parameter and data sizes */
7169 *pparams = (char *)SMB_REALLOC(*pparams,4);
7170 if (*pparams == NULL) {
7171 reply_nterror(req, NT_STATUS_NO_MEMORY);
7176 SSVAL(params,0,0); /* No changes */
7177 SSVAL(params,2,0); /* No EA errors */
7179 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7184 /****************************************************************************
7185 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7186 ****************************************************************************/
7188 static void call_trans2getdfsreferral(connection_struct *conn,
7189 struct smb_request *req,
7190 char **pparams, int total_params,
7191 char **ppdata, int total_data,
7192 unsigned int max_data_bytes)
7194 char *params = *pparams;
7195 char *pathname = NULL;
7197 int max_referral_level;
7198 NTSTATUS status = NT_STATUS_OK;
7199 TALLOC_CTX *ctx = talloc_tos();
7201 DEBUG(10,("call_trans2getdfsreferral\n"));
7203 if (total_params < 3) {
7204 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7208 max_referral_level = SVAL(params,0);
7210 if(!lp_host_msdfs()) {
7211 reply_doserror(req, ERRDOS, ERRbadfunc);
7215 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7216 total_params - 2, STR_TERMINATE);
7218 reply_nterror(req, NT_STATUS_NOT_FOUND);
7221 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7222 ppdata,&status)) < 0) {
7223 reply_nterror(req, status);
7227 SSVAL(req->inbuf, smb_flg2,
7228 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7229 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7234 #define LMCAT_SPL 0x53
7235 #define LMFUNC_GETJOBID 0x60
7237 /****************************************************************************
7238 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7239 ****************************************************************************/
7241 static void call_trans2ioctl(connection_struct *conn,
7242 struct smb_request *req,
7243 char **pparams, int total_params,
7244 char **ppdata, int total_data,
7245 unsigned int max_data_bytes)
7247 char *pdata = *ppdata;
7248 files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
7250 /* check for an invalid fid before proceeding */
7253 reply_doserror(req, ERRDOS, ERRbadfid);
7257 if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7258 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7259 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7260 if (*ppdata == NULL) {
7261 reply_nterror(req, NT_STATUS_NO_MEMORY);
7266 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7267 CAN ACCEPT THIS IN UNICODE. JRA. */
7269 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7270 srvstr_push(pdata, req->flags2, pdata + 2,
7271 global_myname(), 15,
7272 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7273 srvstr_push(pdata, req->flags2, pdata+18,
7274 lp_servicename(SNUM(conn)), 13,
7275 STR_ASCII|STR_TERMINATE); /* Service name */
7276 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7281 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7282 reply_doserror(req, ERRSRV, ERRerror);
7285 /****************************************************************************
7286 Reply to a SMBfindclose (stop trans2 directory search).
7287 ****************************************************************************/
7289 void reply_findclose(struct smb_request *req)
7293 START_PROFILE(SMBfindclose);
7296 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7297 END_PROFILE(SMBfindclose);
7301 dptr_num = SVALS(req->inbuf,smb_vwv0);
7303 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7305 dptr_close(&dptr_num);
7307 reply_outbuf(req, 0, 0);
7309 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7311 END_PROFILE(SMBfindclose);
7315 /****************************************************************************
7316 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7317 ****************************************************************************/
7319 void reply_findnclose(struct smb_request *req)
7323 START_PROFILE(SMBfindnclose);
7326 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7327 END_PROFILE(SMBfindnclose);
7331 dptr_num = SVAL(req->inbuf,smb_vwv0);
7333 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7335 /* We never give out valid handles for a
7336 findnotifyfirst - so any dptr_num is ok here.
7339 reply_outbuf(req, 0, 0);
7341 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7343 END_PROFILE(SMBfindnclose);
7347 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7348 struct trans_state *state)
7350 if (Protocol >= PROTOCOL_NT1) {
7351 req->flags2 |= 0x40; /* IS_LONG_NAME */
7352 SSVAL(req->inbuf,smb_flg2,req->flags2);
7355 if (conn->encrypt_level == Required && !req->encrypted) {
7356 if (state->call != TRANSACT2_QFSINFO &&
7357 state->call != TRANSACT2_SETFSINFO) {
7358 DEBUG(0,("handle_trans2: encryption required "
7360 (unsigned int)state->call));
7361 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7366 /* Now we must call the relevant TRANS2 function */
7367 switch(state->call) {
7368 case TRANSACT2_OPEN:
7370 START_PROFILE(Trans2_open);
7371 call_trans2open(conn, req,
7372 &state->param, state->total_param,
7373 &state->data, state->total_data,
7374 state->max_data_return);
7375 END_PROFILE(Trans2_open);
7379 case TRANSACT2_FINDFIRST:
7381 START_PROFILE(Trans2_findfirst);
7382 call_trans2findfirst(conn, req,
7383 &state->param, state->total_param,
7384 &state->data, state->total_data,
7385 state->max_data_return);
7386 END_PROFILE(Trans2_findfirst);
7390 case TRANSACT2_FINDNEXT:
7392 START_PROFILE(Trans2_findnext);
7393 call_trans2findnext(conn, req,
7394 &state->param, state->total_param,
7395 &state->data, state->total_data,
7396 state->max_data_return);
7397 END_PROFILE(Trans2_findnext);
7401 case TRANSACT2_QFSINFO:
7403 START_PROFILE(Trans2_qfsinfo);
7404 call_trans2qfsinfo(conn, req,
7405 &state->param, state->total_param,
7406 &state->data, state->total_data,
7407 state->max_data_return);
7408 END_PROFILE(Trans2_qfsinfo);
7412 case TRANSACT2_SETFSINFO:
7414 START_PROFILE(Trans2_setfsinfo);
7415 call_trans2setfsinfo(conn, req,
7416 &state->param, state->total_param,
7417 &state->data, state->total_data,
7418 state->max_data_return);
7419 END_PROFILE(Trans2_setfsinfo);
7423 case TRANSACT2_QPATHINFO:
7424 case TRANSACT2_QFILEINFO:
7426 START_PROFILE(Trans2_qpathinfo);
7427 call_trans2qfilepathinfo(conn, req, state->call,
7428 &state->param, state->total_param,
7429 &state->data, state->total_data,
7430 state->max_data_return);
7431 END_PROFILE(Trans2_qpathinfo);
7435 case TRANSACT2_SETPATHINFO:
7436 case TRANSACT2_SETFILEINFO:
7438 START_PROFILE(Trans2_setpathinfo);
7439 call_trans2setfilepathinfo(conn, req, state->call,
7440 &state->param, state->total_param,
7441 &state->data, state->total_data,
7442 state->max_data_return);
7443 END_PROFILE(Trans2_setpathinfo);
7447 case TRANSACT2_FINDNOTIFYFIRST:
7449 START_PROFILE(Trans2_findnotifyfirst);
7450 call_trans2findnotifyfirst(conn, req,
7451 &state->param, state->total_param,
7452 &state->data, state->total_data,
7453 state->max_data_return);
7454 END_PROFILE(Trans2_findnotifyfirst);
7458 case TRANSACT2_FINDNOTIFYNEXT:
7460 START_PROFILE(Trans2_findnotifynext);
7461 call_trans2findnotifynext(conn, req,
7462 &state->param, state->total_param,
7463 &state->data, state->total_data,
7464 state->max_data_return);
7465 END_PROFILE(Trans2_findnotifynext);
7469 case TRANSACT2_MKDIR:
7471 START_PROFILE(Trans2_mkdir);
7472 call_trans2mkdir(conn, req,
7473 &state->param, state->total_param,
7474 &state->data, state->total_data,
7475 state->max_data_return);
7476 END_PROFILE(Trans2_mkdir);
7480 case TRANSACT2_GET_DFS_REFERRAL:
7482 START_PROFILE(Trans2_get_dfs_referral);
7483 call_trans2getdfsreferral(conn, req,
7484 &state->param, state->total_param,
7485 &state->data, state->total_data,
7486 state->max_data_return);
7487 END_PROFILE(Trans2_get_dfs_referral);
7491 case TRANSACT2_IOCTL:
7493 START_PROFILE(Trans2_ioctl);
7494 call_trans2ioctl(conn, req,
7495 &state->param, state->total_param,
7496 &state->data, state->total_data,
7497 state->max_data_return);
7498 END_PROFILE(Trans2_ioctl);
7503 /* Error in request */
7504 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7505 reply_doserror(req, ERRSRV,ERRerror);
7509 /****************************************************************************
7510 Reply to a SMBtrans2.
7511 ****************************************************************************/
7513 void reply_trans2(struct smb_request *req)
7515 connection_struct *conn = req->conn;
7520 unsigned int tran_call;
7522 unsigned int av_size;
7523 struct trans_state *state;
7526 START_PROFILE(SMBtrans2);
7528 if (req->wct < 14) {
7529 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7530 END_PROFILE(SMBtrans2);
7534 dsoff = SVAL(req->inbuf, smb_dsoff);
7535 dscnt = SVAL(req->inbuf, smb_dscnt);
7536 psoff = SVAL(req->inbuf, smb_psoff);
7537 pscnt = SVAL(req->inbuf, smb_pscnt);
7538 tran_call = SVAL(req->inbuf, smb_setup0);
7539 size = smb_len(req->inbuf) + 4;
7540 av_size = smb_len(req->inbuf);
7542 result = allow_new_trans(conn->pending_trans, req->mid);
7543 if (!NT_STATUS_IS_OK(result)) {
7544 DEBUG(2, ("Got invalid trans2 request: %s\n",
7545 nt_errstr(result)));
7546 reply_nterror(req, result);
7547 END_PROFILE(SMBtrans2);
7552 switch (tran_call) {
7553 /* List the allowed trans2 calls on IPC$ */
7554 case TRANSACT2_OPEN:
7555 case TRANSACT2_GET_DFS_REFERRAL:
7556 case TRANSACT2_QFILEINFO:
7557 case TRANSACT2_QFSINFO:
7558 case TRANSACT2_SETFSINFO:
7561 reply_doserror(req, ERRSRV, ERRaccess);
7562 END_PROFILE(SMBtrans2);
7567 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7568 DEBUG(0, ("talloc failed\n"));
7569 reply_nterror(req, NT_STATUS_NO_MEMORY);
7570 END_PROFILE(SMBtrans2);
7574 state->cmd = SMBtrans2;
7576 state->mid = req->mid;
7577 state->vuid = req->vuid;
7578 state->setup_count = SVAL(req->inbuf, smb_suwcnt);
7579 state->setup = NULL;
7580 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7581 state->param = NULL;
7582 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7584 state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
7585 state->max_data_return = SVAL(req->inbuf, smb_mdrcnt);
7586 state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
7587 state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
7588 state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
7590 state->call = tran_call;
7592 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7593 is so as a sanity check */
7594 if (state->setup_count != 1) {
7596 * Need to have rc=0 for ioctl to get job id for OS/2.
7597 * Network printing will fail if function is not successful.
7598 * Similar function in reply.c will be used if protocol
7599 * is LANMAN1.0 instead of LM1.2X002.
7600 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7601 * outbuf doesn't have to be set(only job id is used).
7603 if ( (state->setup_count == 4)
7604 && (tran_call == TRANSACT2_IOCTL)
7605 && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7606 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7607 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7609 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7610 DEBUG(2,("Transaction is %d\n",tran_call));
7612 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7613 END_PROFILE(SMBtrans2);
7618 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7621 if (state->total_data) {
7622 /* Can't use talloc here, the core routines do realloc on the
7623 * params and data. */
7624 state->data = (char *)SMB_MALLOC(state->total_data);
7625 if (state->data == NULL) {
7626 DEBUG(0,("reply_trans2: data malloc fail for %u "
7627 "bytes !\n", (unsigned int)state->total_data));
7629 reply_nterror(req, NT_STATUS_NO_MEMORY);
7630 END_PROFILE(SMBtrans2);
7634 if (dscnt > state->total_data ||
7635 dsoff+dscnt < dsoff) {
7639 if (dsoff > av_size ||
7641 dsoff+dscnt > av_size) {
7645 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7648 if (state->total_param) {
7649 /* Can't use talloc here, the core routines do realloc on the
7650 * params and data. */
7651 state->param = (char *)SMB_MALLOC(state->total_param);
7652 if (state->param == NULL) {
7653 DEBUG(0,("reply_trans: param malloc fail for %u "
7654 "bytes !\n", (unsigned int)state->total_param));
7655 SAFE_FREE(state->data);
7657 reply_nterror(req, NT_STATUS_NO_MEMORY);
7658 END_PROFILE(SMBtrans2);
7662 if (pscnt > state->total_param ||
7663 psoff+pscnt < psoff) {
7667 if (psoff > av_size ||
7669 psoff+pscnt > av_size) {
7673 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7676 state->received_data = dscnt;
7677 state->received_param = pscnt;
7679 if ((state->received_param == state->total_param) &&
7680 (state->received_data == state->total_data)) {
7682 handle_trans2(conn, req, state);
7684 SAFE_FREE(state->data);
7685 SAFE_FREE(state->param);
7687 END_PROFILE(SMBtrans2);
7691 DLIST_ADD(conn->pending_trans, state);
7693 /* We need to send an interim response then receive the rest
7694 of the parameter/data bytes */
7695 reply_outbuf(req, 0, 0);
7696 show_msg((char *)req->outbuf);
7697 END_PROFILE(SMBtrans2);
7702 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7703 SAFE_FREE(state->data);
7704 SAFE_FREE(state->param);
7706 END_PROFILE(SMBtrans2);
7707 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7711 /****************************************************************************
7712 Reply to a SMBtranss2
7713 ****************************************************************************/
7715 void reply_transs2(struct smb_request *req)
7717 connection_struct *conn = req->conn;
7718 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7719 struct trans_state *state;
7721 unsigned int av_size;
7723 START_PROFILE(SMBtranss2);
7725 show_msg((char *)req->inbuf);
7728 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7729 END_PROFILE(SMBtranss2);
7733 size = smb_len(req->inbuf)+4;
7734 av_size = smb_len(req->inbuf);
7736 for (state = conn->pending_trans; state != NULL;
7737 state = state->next) {
7738 if (state->mid == req->mid) {
7743 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7744 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7745 END_PROFILE(SMBtranss2);
7749 /* Revise state->total_param and state->total_data in case they have
7750 changed downwards */
7752 if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
7753 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7754 if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
7755 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7757 pcnt = SVAL(req->inbuf, smb_spscnt);
7758 poff = SVAL(req->inbuf, smb_spsoff);
7759 pdisp = SVAL(req->inbuf, smb_spsdisp);
7761 dcnt = SVAL(req->inbuf, smb_sdscnt);
7762 doff = SVAL(req->inbuf, smb_sdsoff);
7763 ddisp = SVAL(req->inbuf, smb_sdsdisp);
7765 state->received_param += pcnt;
7766 state->received_data += dcnt;
7768 if ((state->received_data > state->total_data) ||
7769 (state->received_param > state->total_param))
7773 if (pdisp > state->total_param ||
7774 pcnt > state->total_param ||
7775 pdisp+pcnt > state->total_param ||
7776 pdisp+pcnt < pdisp) {
7780 if (poff > av_size ||
7782 poff+pcnt > av_size ||
7787 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7792 if (ddisp > state->total_data ||
7793 dcnt > state->total_data ||
7794 ddisp+dcnt > state->total_data ||
7795 ddisp+dcnt < ddisp) {
7799 if (ddisp > av_size ||
7801 ddisp+dcnt > av_size ||
7802 ddisp+dcnt < ddisp) {
7806 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7810 if ((state->received_param < state->total_param) ||
7811 (state->received_data < state->total_data)) {
7812 END_PROFILE(SMBtranss2);
7817 * construct_reply_common will copy smb_com from inbuf to
7818 * outbuf. SMBtranss2 is wrong here.
7820 SCVAL(req->inbuf,smb_com,SMBtrans2);
7822 handle_trans2(conn, req, state);
7824 DLIST_REMOVE(conn->pending_trans, state);
7825 SAFE_FREE(state->data);
7826 SAFE_FREE(state->param);
7829 END_PROFILE(SMBtranss2);
7834 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7835 DLIST_REMOVE(conn->pending_trans, state);
7836 SAFE_FREE(state->data);
7837 SAFE_FREE(state->param);
7839 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7840 END_PROFILE(SMBtranss2);