summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGordon Ross <gwr@nexenta.com>2017-10-19 16:40:37 -0400
committerGordon Ross <gwr@nexenta.com>2019-06-08 20:48:23 -0400
commitd2488fe8c5950495aef5404c8d98081be7d43487 (patch)
tree141dcbff65d732f0b2e5bd57f4193cf3fb49e630
parentd6390ef7453a176bd5e16ae9fde5ebe59c15f298 (diff)
downloadillumos-joyent-d2488fe8c5950495aef5404c8d98081be7d43487.tar.gz
11014 should pass smtorture smb2.create.blob
Reviewed by: Matt Barden <matt.barden@nexenta.com> Reviewed by: Evan Layton <evan.layton@nexenta.com> Approved by: Garrett D'Amore <garrett@damore.org>
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb2_create.c3
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb2_dispatch.c7
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb2_query_dir.c9
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_delete.c12
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_directory.c12
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_errno.c13
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_find.c6
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_fsops.c10
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_mangle_name.c114
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_mbuf_marshaling.c17
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_node.c67
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_odir.c12
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_query_fileinfo.c8
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_set_fileinfo.c7
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_trans2_find.c3
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_vops.c3
-rw-r--r--usr/src/uts/common/smbsrv/smb_fsops.h3
-rw-r--r--usr/src/uts/common/smbsrv/smb_kproto.h1
18 files changed, 161 insertions, 146 deletions
diff --git a/usr/src/uts/common/fs/smbsrv/smb2_create.c b/usr/src/uts/common/fs/smbsrv/smb2_create.c
index f2ad134f84..473f878ba3 100644
--- a/usr/src/uts/common/fs/smbsrv/smb2_create.c
+++ b/usr/src/uts/common/fs/smbsrv/smb2_create.c
@@ -985,6 +985,7 @@ smb2_encode_create_ctx_elem(mbuf_chain_t *out_mbc,
* a: this header (16 bytes)
* b: the name (4 bytes, 4 pad)
* c: the payload (variable)
+ * d: padding (to align 8)
*
* Note that "Next elem." is filled in later.
*/
@@ -1008,6 +1009,8 @@ smb2_encode_create_ctx_elem(mbuf_chain_t *out_mbc,
cce->cce_len, /* # */
&cce->cce_mbc); /* C */
+ (void) smb_mbc_put_align(out_mbc, 8);
+
return (rc);
}
diff --git a/usr/src/uts/common/fs/smbsrv/smb2_dispatch.c b/usr/src/uts/common/fs/smbsrv/smb2_dispatch.c
index b0bbbd4f40..b35b91ff7c 100644
--- a/usr/src/uts/common/fs/smbsrv/smb2_dispatch.c
+++ b/usr/src/uts/common/fs/smbsrv/smb2_dispatch.c
@@ -723,11 +723,8 @@ cmd_done:
/*
* Pad the reply to align(8) if necessary.
*/
- if (sr->reply.chain_offset & 7) {
- int padsz = 8 - (sr->reply.chain_offset & 7);
- (void) smb_mbc_encodef(&sr->reply, "#.", padsz);
- }
- ASSERT((sr->reply.chain_offset & 7) == 0);
+ if (sr->smb2_next_command != 0)
+ (void) smb_mbc_put_align(&sr->reply, 8);
/*
* Record some statistics: latency, rx bytes, tx bytes.
diff --git a/usr/src/uts/common/fs/smbsrv/smb2_query_dir.c b/usr/src/uts/common/fs/smbsrv/smb2_query_dir.c
index 11f3515504..5859314b47 100644
--- a/usr/src/uts/common/fs/smbsrv/smb2_query_dir.c
+++ b/usr/src/uts/common/fs/smbsrv/smb2_query_dir.c
@@ -437,7 +437,7 @@ smb2_find_mbc_encode(smb_request_t *sr, smb2_find_args_t *args)
smb_macinfo_t *macinfo = &args->fa_mi;
uint8_t buf83[26];
smb_msgbuf_t mb;
- int namelen, padsz;
+ int namelen;
int shortlen = 0;
int rc, starting_offset;
uint32_t next_entry_offset;
@@ -647,11 +647,8 @@ smb2_find_mbc_encode(smb_request_t *sr, smb2_find_args_t *args)
return (NT_STATUS_BUFFER_OVERFLOW);
/* Next entry needs to be 8-byte aligned. */
- padsz = sr->raw_data.chain_offset & 7;
- if (padsz) {
- padsz = 8 - padsz;
- (void) smb_mbc_encodef(&sr->raw_data, "#.", padsz);
- }
+ (void) smb_mbc_put_align(&sr->raw_data, 8);
+
next_entry_offset = sr->raw_data.chain_offset - starting_offset;
(void) smb_mbc_poke(&sr->raw_data, starting_offset, "l",
next_entry_offset);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_delete.c b/usr/src/uts/common/fs/smbsrv/smb_delete.c
index 95c2063bca..3902764d23 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_delete.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_delete.c
@@ -544,18 +544,12 @@ smb_delete_remove_file(smb_request_t *sr, smb_error_t *err)
rc = smb_fsop_remove(sr, sr->user_cr, node->n_dnode,
node->od_name, flags);
if (rc != 0) {
- if (rc == ENOENT)
- smb_delete_error(err, NT_STATUS_OBJECT_NAME_NOT_FOUND,
- ERRDOS, ERROR_FILE_NOT_FOUND);
- else
- smbsr_map_errno(rc, err);
-
- smb_node_end_crit(node);
- return (-1);
+ smbsr_map_errno(rc, err);
+ rc = -1;
}
smb_node_end_crit(node);
- return (0);
+ return (rc);
}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_directory.c b/usr/src/uts/common/fs/smbsrv/smb_directory.c
index 007f34fb45..f009c32580 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_directory.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_directory.c
@@ -250,11 +250,7 @@ smb_com_delete_directory(smb_request_t *sr)
rc = smb_fsop_lookup(sr, sr->user_cr, SMB_FOLLOW_LINKS,
tnode, fqi->fq_dnode, fqi->fq_last_comp, &fqi->fq_fnode);
if (rc != 0) {
- if (rc == ENOENT)
- smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND,
- ERRDOS, ERROR_FILE_NOT_FOUND);
- else
- smbsr_errno(sr, rc);
+ smbsr_errno(sr, rc);
smb_node_release(fqi->fq_dnode);
return (SDRC_ERROR);
}
@@ -414,11 +410,7 @@ smb_com_check_directory(smb_request_t *sr)
tnode, fqi->fq_dnode, fqi->fq_last_comp, &fqi->fq_fnode);
smb_node_release(fqi->fq_dnode);
if (rc != 0) {
- if (rc == ENOENT)
- smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND,
- ERRDOS, ERROR_PATH_NOT_FOUND);
- else
- smbsr_errno(sr, rc);
+ smbsr_errno(sr, rc);
return (SDRC_ERROR);
}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_errno.c b/usr/src/uts/common/fs/smbsrv/smb_errno.c
index 533d099b4a..fe0ea8c7c6 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_errno.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_errno.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -47,9 +47,9 @@ struct errno2status {
static const struct errno2status
smb_errno2status_map[] = {
{ EPERM, NT_STATUS_ACCESS_DENIED },
- { ENOENT, NT_STATUS_NO_SUCH_FILE },
- /* NB: ESRCH is used to represent stream lookup failures. */
- { ESRCH, NT_STATUS_OBJECT_NAME_NOT_FOUND },
+ { ENOENT, NT_STATUS_OBJECT_NAME_NOT_FOUND },
+ /* NB: ESRCH is used in rename and stream ops. */
+ { ESRCH, NT_STATUS_NO_SUCH_FILE },
{ EINTR, NT_STATUS_CANCELLED },
{ EIO, NT_STATUS_IO_DEVICE_ERROR },
{ ENXIO, NT_STATUS_BAD_DEVICE_TYPE },
@@ -60,9 +60,8 @@ smb_errno2status_map[] = {
{ EACCES, NT_STATUS_ACCESS_DENIED },
/* EFAULT, ENOTBLK, EBUSY */
{ EEXIST, NT_STATUS_OBJECT_NAME_COLLISION },
- { EXDEV, NT_STATUS_NOT_SAME_DEVICE },
+ { EXDEV, NT_STATUS_NOT_SAME_DEVICE },
{ ENODEV, NT_STATUS_NO_SUCH_DEVICE },
- /* ENOTDIR should be: NT_STATUS_NOT_A_DIRECTORY, but not yet */
{ ENOTDIR, NT_STATUS_OBJECT_PATH_NOT_FOUND },
{ EISDIR, NT_STATUS_FILE_IS_A_DIRECTORY },
{ EINVAL, NT_STATUS_INVALID_PARAMETER },
@@ -81,7 +80,7 @@ smb_errno2status_map[] = {
/* ENOMSG, EIDRM, ... */
{ ENOTSUP, NT_STATUS_NOT_SUPPORTED },
{ EDQUOT, NT_STATUS_DISK_FULL },
- { EREMOTE, NT_STATUS_PATH_NOT_COVERED},
+ { EREMOTE, NT_STATUS_PATH_NOT_COVERED},
{ ENAMETOOLONG, NT_STATUS_OBJECT_NAME_INVALID },
{ EILSEQ, NT_STATUS_OBJECT_NAME_INVALID },
{ ENOTEMPTY, NT_STATUS_DIRECTORY_NOT_EMPTY },
diff --git a/usr/src/uts/common/fs/smbsrv/smb_find.c b/usr/src/uts/common/fs/smbsrv/smb_find.c
index a8774f72e2..9dc3689652 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_find.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_find.c
@@ -300,6 +300,7 @@ smb_com_search(smb_request_t *sr)
ERRDOS, ERROR_NO_MORE_FILES);
return (SDRC_ERROR);
}
+ odid = od->d_odid;
} else {
if (smb_mbc_decodef(&sr->smb_data, "b12.wwl",
&resume_char, &index, &odid, &client_key) != 0) {
@@ -455,6 +456,7 @@ smb_com_find(smb_request_t *sr)
smbsr_error(sr, status, 0, 0);
return (SDRC_ERROR);
}
+ odid = od->d_odid;
} else {
if (smb_mbc_decodef(&sr->smb_data, "b12.wwl",
&resume_char, &index, &odid, &client_key) != 0) {
@@ -691,8 +693,8 @@ smb_com_find_unique(struct smb_request *sr)
smb_name83(fileinfo.fi_shortname, name83, SMB_SHORTNAMELEN);
(void) smb_mbc_encodef(&sr->reply, "b11c.wwlbYl13c",
- resume_char, name83, index, od->d_odid,
- client_key, fileinfo.fi_dosattr & 0xff,
+ resume_char, name83, index, od->d_odid, client_key,
+ fileinfo.fi_dosattr & 0xff,
smb_time_gmt_to_local(sr, fileinfo.fi_mtime.tv_sec),
(int32_t)fileinfo.fi_size,
fileinfo.fi_shortname);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_fsops.c b/usr/src/uts/common/fs/smbsrv/smb_fsops.c
index 819547773d..abe69a9017 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_fsops.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_fsops.c
@@ -820,6 +820,7 @@ smb_fsop_remove_streams(smb_request_t *sr, cred_t *cr, smb_node_t *fnode)
switch (status) {
case 0:
break;
+ case NT_STATUS_OBJECT_NAME_NOT_FOUND:
case NT_STATUS_NO_SUCH_FILE:
case NT_STATUS_NOT_SUPPORTED:
/* No streams to remove. */
@@ -2541,6 +2542,15 @@ smb_fsop_eaccess(smb_request_t *sr, cred_t *cr, smb_node_t *snode,
if (access & VWRITE)
*eaccess |= FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES |
FILE_WRITE_EA | FILE_APPEND_DATA | FILE_DELETE_CHILD;
+
+ if (access & (VREAD | VWRITE))
+ *eaccess |= SYNCHRONIZE;
+
+#ifdef _FAKE_KERNEL
+ /* Should be: if (we are the owner)... */
+ if (access & VWRITE)
+ *eaccess |= DELETE | WRITE_DAC | WRITE_OWNER;
+#endif
}
/*
diff --git a/usr/src/uts/common/fs/smbsrv/smb_mangle_name.c b/usr/src/uts/common/fs/smbsrv/smb_mangle_name.c
index 7555441f01..b504911f8d 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_mangle_name.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_mangle_name.c
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
*/
#include <sys/types.h>
@@ -351,11 +351,8 @@ smb_mangle(const char *name, ino64_t fid, char *buf, size_t buflen)
* smb_unmangle should only be called on names for which
* smb_maybe_mangled() is true
*
- * File systems which support VFSFT_EDIRENT_FLAGS will return the
- * directory entries as a buffer of edirent_t structure. Others will
- * return a buffer of dirent64_t structures. A union is used for the
- * the pointer into the buffer (bufptr, edp and dp).
- * The ed_name/d_name is NULL terminated by the file system.
+ * The flags arg is no longer used, but retained just to avoid
+ * changing the many callers of this function.
*
* Returns:
* 0 - SUCCESS. Unmangled name is returned in namebuf.
@@ -368,21 +365,17 @@ int
smb_unmangle(smb_node_t *dnode, char *name, char *namebuf,
int buflen, uint32_t flags)
{
- int err, eof, bufsize, reclen;
+ _NOTE(ARGUNUSED(flags)) // avoid changing all callers
+ int err, eof, bufsize;
uint64_t offset;
ino64_t ino;
- boolean_t is_edp;
char *namep, *buf;
char shortname[SMB_SHORTNAMELEN];
vnode_t *vp;
- union {
- char *u_bufptr;
- edirent_t *u_edp;
- dirent64_t *u_dp;
- } u;
-#define bufptr u.u_bufptr
-#define edp u.u_edp
-#define dp u.u_dp
+ char *bufptr;
+ dirent64_t *dp;
+ cred_t *cr = zone_kcred();
+ int rc = ENOENT;
if (dnode == NULL || name == NULL || namebuf == NULL || buflen == 0)
return (EINVAL);
@@ -394,57 +387,62 @@ smb_unmangle(smb_node_t *dnode, char *name, char *namebuf,
vp = dnode->vp;
*namebuf = '\0';
- is_edp = vfs_has_feature(vp->v_vfsp, VFSFT_DIRENTFLAGS);
buf = kmem_alloc(SMB_UNMANGLE_BUFSIZE, KM_SLEEP);
- bufsize = SMB_UNMANGLE_BUFSIZE;
- offset = 0;
-
- while ((err = smb_vop_readdir(vp, offset, buf, &bufsize,
- &eof, flags, zone_kcred())) == 0) {
- if (bufsize == 0) {
- err = ENOENT;
- break;
- }
-
- bufptr = buf;
- reclen = 0;
-
- while ((bufptr += reclen) < buf + bufsize) {
- if (is_edp) {
- reclen = edp->ed_reclen;
- offset = edp->ed_off;
- ino = edp->ed_ino;
- namep = edp->ed_name;
- } else {
- reclen = dp->d_reclen;
- offset = dp->d_off;
- ino = dp->d_ino;
- namep = dp->d_name;
+ bufptr = buf;
+ bufsize = 0;
+ offset = 0; // next entry offset
+ eof = B_FALSE;
+
+ for (;;) {
+ /*
+ * Read some entries, if buffer empty or
+ * we've scanned all of it. Flags zero
+ * (no edirent, no ABE wanted here)
+ */
+ if (bufsize <= 0) {
+ bufsize = SMB_UNMANGLE_BUFSIZE;
+ rc = smb_vop_readdir(vp, offset, buf,
+ &bufsize, &eof, 0, cr);
+ if (rc != 0)
+ break; /* error */
+ if (bufsize == 0) {
+ eof = B_TRUE;
+ rc = ENOENT;
+ break;
}
+ bufptr = buf;
+ }
+ /* LINTED pointer alignment */
+ dp = (dirent64_t *)bufptr;
+
+ /*
+ * Partial records are not supposed to happen,
+ * but let's be defensive. If this happens,
+ * restart at the current offset.
+ */
+ bufptr += dp->d_reclen;
+ bufsize -= dp->d_reclen;
+ if (bufsize < 0)
+ continue;
- /* skip non utf8 filename */
- if (u8_validate(namep, strlen(namep), NULL,
- U8_VALIDATE_ENTIRE, &err) < 0)
- continue;
-
- smb_mangle(namep, ino, shortname, SMB_SHORTNAMELEN);
+ offset = dp->d_off;
+ ino = dp->d_ino;
+ namep = dp->d_name;
- if (smb_strcasecmp(name, shortname, 0) == 0) {
- (void) strlcpy(namebuf, namep, buflen);
- kmem_free(buf, SMB_UNMANGLE_BUFSIZE);
- return (0);
- }
- }
+ /* skip non utf8 filename */
+ if (u8_validate(namep, strlen(namep), NULL,
+ U8_VALIDATE_ENTIRE, &err) < 0)
+ continue;
- if (eof) {
- err = ENOENT;
+ smb_mangle(namep, ino, shortname, SMB_SHORTNAMELEN);
+ if (smb_strcasecmp(name, shortname, 0) == 0) {
+ (void) strlcpy(namebuf, namep, buflen);
+ rc = 0;
break;
}
-
- bufsize = SMB_UNMANGLE_BUFSIZE;
}
kmem_free(buf, SMB_UNMANGLE_BUFSIZE);
- return (err);
+ return (rc);
}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_mbuf_marshaling.c b/usr/src/uts/common/fs/smbsrv/smb_mbuf_marshaling.c
index f9b629b24f..132820a147 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_mbuf_marshaling.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_mbuf_marshaling.c
@@ -916,6 +916,23 @@ smb_mbc_put_mem(mbuf_chain_t *mbc, void *vmem, int mem_len)
}
/*
+ * Put padding sufficient to align to A, where
+ * A is some power of 2 greater than zero.
+ */
+int
+smb_mbc_put_align(mbuf_chain_t *mbc, int align)
+{
+ int mask = align - 1;
+ int padsz;
+
+ ASSERT(align > 0 && (align & mask) == 0);
+ if ((mbc->chain_offset & mask) == 0)
+ return (0);
+ padsz = align - (mbc->chain_offset & mask);
+ return (smb_mbc_encodef(mbc, "#.", padsz));
+}
+
+/*
* Put data into mbuf chain allocating as needed.
* Adds room to end of mbuf chain if needed.
*/
diff --git a/usr/src/uts/common/fs/smbsrv/smb_node.c b/usr/src/uts/common/fs/smbsrv/smb_node.c
index 66eabe3fe2..2d16395ad3 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_node.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_node.c
@@ -611,40 +611,47 @@ smb_node_root_init(smb_server_t *sv, smb_node_t **svrootp)
* and check for anything other than "." or ".." in the readdir buf.
*/
static uint32_t
-smb_rmdir_possible(smb_node_t *n, uint32_t flags)
+smb_rmdir_possible(smb_node_t *n)
{
ASSERT(n->vp->v_type == VDIR);
- char buf[512]; /* Only large enough to see if the dir is empty. */
- int eof, bsize = sizeof (buf), reclen = 0;
- char *name;
- boolean_t edp = vfs_has_feature(n->vp->v_vfsp, VFSFT_DIRENTFLAGS);
-
- union {
- char *u_bufptr;
- struct edirent *u_edp;
- struct dirent64 *u_dp;
- } u;
-#define bufptr u.u_bufptr
-#define extdp u.u_edp
-#define dp u.u_dp
-
- if (smb_vop_readdir(n->vp, 0, buf, &bsize, &eof, flags, zone_kcred()))
- return (NT_STATUS_INTERNAL_ERROR);
- if (bsize == 0)
- return (0); /* empty dir */
+ char *buf;
+ char *bufptr;
+ struct dirent64 *dp;
+ uint32_t status = NT_STATUS_SUCCESS;
+ int bsize = SMB_ODIR_BUFSIZE;
+ int eof = 0;
+
+ buf = kmem_alloc(SMB_ODIR_BUFSIZE, KM_SLEEP);
+
+ /* Flags zero: no edirent, no ABE wanted here */
+ if (smb_vop_readdir(n->vp, 0, buf, &bsize, &eof, 0, zone_kcred())) {
+ status = NT_STATUS_INTERNAL_ERROR;
+ goto out;
+ }
+
bufptr = buf;
- while ((bufptr += reclen) < buf + bsize) {
- if (edp) {
- reclen = extdp->ed_reclen;
- name = extdp->ed_name;
- } else {
- reclen = dp->d_reclen;
- name = dp->d_name;
+ while (bsize > 0) {
+ /* LINTED pointer alignment */
+ dp = (struct dirent64 *)bufptr;
+
+ bufptr += dp->d_reclen;
+ bsize -= dp->d_reclen;
+ if (bsize < 0) {
+ /* partial record */
+ status = NT_STATUS_DIRECTORY_NOT_EMPTY;
+ break;
+ }
+
+ if (strcmp(dp->d_name, ".") != 0 &&
+ strcmp(dp->d_name, "..") != 0) {
+ status = NT_STATUS_DIRECTORY_NOT_EMPTY;
+ break;
}
- if (strcmp(name, ".") != 0 && strcmp(name, "..") != 0)
- return (NT_STATUS_DIRECTORY_NOT_EMPTY);
}
- return (0);
+
+out:
+ kmem_free(buf, SMB_ODIR_BUFSIZE);
+ return (status);
}
/*
@@ -672,7 +679,7 @@ smb_node_set_delete_on_close(smb_node_t *node, cred_t *cr, uint32_t flags)
* "File System Behavior Overview" doc section 4.3.2
*/
if (smb_node_is_dir(node)) {
- status = smb_rmdir_possible(node, flags);
+ status = smb_rmdir_possible(node);
if (status != 0) {
return (status);
}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_odir.c b/usr/src/uts/common/fs/smbsrv/smb_odir.c
index 55a6c38dd1..d2f56b47b0 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_odir.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_odir.c
@@ -1059,12 +1059,17 @@ smb_odir_next_odirent(smb_odir_t *od, smb_odirent_t *odirent)
dirent64_t *dp;
edirent_t *edp;
char *np;
- uint32_t abe_flag = 0;
+ uint32_t rddir_flags = 0;
ASSERT(MUTEX_HELD(&od->d_mutex));
bzero(odirent, sizeof (smb_odirent_t));
+ if (od->d_flags & SMB_ODIR_FLAG_ABE)
+ rddir_flags |= SMB_ABE;
+ if (od->d_flags & SMB_ODIR_FLAG_EDIRENT)
+ rddir_flags |= SMB_EDIRENT;
+
if (od->d_bufptr != NULL) {
if (od->d_flags & SMB_ODIR_FLAG_EDIRENT)
reclen = od->d_edp->ed_reclen;
@@ -1086,11 +1091,8 @@ smb_odir_next_odirent(smb_odir_t *od, smb_odirent_t *odirent)
od->d_bufsize = sizeof (od->d_buf);
- if (od->d_flags & SMB_ODIR_FLAG_ABE)
- abe_flag = SMB_ABE;
-
rc = smb_vop_readdir(od->d_dnode->vp, od->d_offset,
- od->d_buf, &od->d_bufsize, &eof, abe_flag, od->d_cred);
+ od->d_buf, &od->d_bufsize, &eof, rddir_flags, od->d_cred);
if ((rc == 0) && (od->d_bufsize == 0))
rc = ENOENT;
diff --git a/usr/src/uts/common/fs/smbsrv/smb_query_fileinfo.c b/usr/src/uts/common/fs/smbsrv/smb_query_fileinfo.c
index 2504f524c9..cfa3ab4aca 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_query_fileinfo.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_query_fileinfo.c
@@ -329,11 +329,7 @@ smb_query_by_path(smb_request_t *sr, smb_xa_t *xa, uint16_t infolev)
}
if (rc != 0) {
- if (rc == ENOENT)
- smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND,
- ERRDOS, ERROR_FILE_NOT_FOUND);
- else
- smbsr_errno(sr, rc);
+ smbsr_errno(sr, rc);
kmem_free(qinfo, sizeof (smb_queryinfo_t));
return (-1);
@@ -654,9 +650,11 @@ smb_query_stream_info(smb_request_t *sr, mbuf_chain_t *mbc,
switch (status) {
case 0:
break;
+ case NT_STATUS_OBJECT_NAME_NOT_FOUND:
case NT_STATUS_NO_SUCH_FILE:
case NT_STATUS_NOT_SUPPORTED:
/* No streams. */
+ status = 0;
done = B_TRUE;
break;
default:
diff --git a/usr/src/uts/common/fs/smbsrv/smb_set_fileinfo.c b/usr/src/uts/common/fs/smbsrv/smb_set_fileinfo.c
index 160459ab7f..32df1912e0 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_set_fileinfo.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_set_fileinfo.c
@@ -293,12 +293,7 @@ smb_set_by_path(smb_request_t *sr, smb_xa_t *xa, uint16_t infolev)
kmem_free(name, MAXNAMELEN);
if (rc != 0) {
- if (rc == ENOENT) {
- smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND,
- ERRDOS, ERROR_FILE_NOT_FOUND);
- } else {
- smbsr_errno(sr, rc);
- }
+ smbsr_errno(sr, rc);
return (-1);
}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c b/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c
index ecb7c5c639..d7d1565b2a 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c
@@ -344,7 +344,8 @@ smb_com_trans2_find_first2(smb_request_t *sr, smb_xa_t *xa)
if (count == 0) {
smb_odir_close(od);
smb_odir_release(od);
- smbsr_errno(sr, ENOENT);
+ smbsr_status(sr, NT_STATUS_NO_SUCH_FILE,
+ ERRDOS, ERROR_FILE_NOT_FOUND);
return (SDRC_ERROR);
}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_vops.c b/usr/src/uts/common/fs/smbsrv/smb_vops.c
index 7a3905d7bb..f90c2d837d 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_vops.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_vops.c
@@ -1006,7 +1006,8 @@ smb_vop_readdir(vnode_t *vp, uint32_t offset,
if (vp->v_type != VDIR)
return (ENOTDIR);
- if (vfs_has_feature(vp->v_vfsp, VFSFT_DIRENTFLAGS)) {
+ if ((rddir_flag & SMB_EDIRENT) != 0 &&
+ vfs_has_feature(vp->v_vfsp, VFSFT_DIRENTFLAGS)) {
flags |= V_RDDIR_ENTFLAGS;
rdirent_size = sizeof (edirent_t);
} else {
diff --git a/usr/src/uts/common/smbsrv/smb_fsops.h b/usr/src/uts/common/smbsrv/smb_fsops.h
index f4421fe733..377dfe257a 100644
--- a/usr/src/uts/common/smbsrv/smb_fsops.h
+++ b/usr/src/uts/common/smbsrv/smb_fsops.h
@@ -22,7 +22,7 @@
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
- * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
*/
#ifndef _SMBSRV_SMB_FSOPS_H
@@ -123,6 +123,7 @@ int smb_fsop_frlock(smb_node_t *, smb_lock_t *, boolean_t, cred_t *);
#define SMB_CATIA 0x00000004
#define SMB_ABE 0x00000008
#define SMB_CASE_SENSITIVE 0x00000010
+#define SMB_EDIRENT 0x00000020
/*
* Increased MAXPATHLEN for SMB. Essentially, we want to allow a
diff --git a/usr/src/uts/common/smbsrv/smb_kproto.h b/usr/src/uts/common/smbsrv/smb_kproto.h
index 61d2b7b42e..2e5839f8b0 100644
--- a/usr/src/uts/common/smbsrv/smb_kproto.h
+++ b/usr/src/uts/common/smbsrv/smb_kproto.h
@@ -370,6 +370,7 @@ int smb_mbc_peek(mbuf_chain_t *, int, const char *, ...);
int smb_mbc_poke(mbuf_chain_t *, int, const char *, ...);
int smb_mbc_put_mem(mbuf_chain_t *, void *, int);
int smb_mbc_copy(mbuf_chain_t *, const mbuf_chain_t *, int, int);
+int smb_mbc_put_align(mbuf_chain_t *, int);
void smbsr_encode_header(smb_request_t *sr, int wct,
int bcc, const char *fmt, ...);