summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGordon Ross <Gordon.Ross@Sun.COM>2009-12-16 15:03:38 -0500
committerGordon Ross <Gordon.Ross@Sun.COM>2009-12-16 15:03:38 -0500
commit02d09e03eb27f3a2dc299de704e45dae5173f43f (patch)
treed01a29c58a8a455627b355abb83addad11802bd6
parentaab2fe4104e428e5213f84aee65b9905ec97cf9a (diff)
downloadillumos-gate-02d09e03eb27f3a2dc299de704e45dae5173f43f.tar.gz
6650611 Attribute cache logic needs improvement
6876185 common I/F for net message build/parse in kernel vs user code 6891728 syslog shows: smbfs_close: error 9 closing /dirname 6906037 smbfs_mount() doesn't ASSERT the return value of smbfs_make_node() 6607536 the size of a dir on smbfs is not correct 6648146 smbfs should implement reclaim from node cache --HG-- rename : usr/src/lib/libsmbfs/smb/acl_conv.c => usr/src/common/smbclnt/smbfs_ntacl.c rename : usr/src/lib/libsmbfs/smb/acl_nt.h => usr/src/common/smbclnt/smbfs_ntacl.h
-rw-r--r--usr/src/cmd/fs.d/smbclnt/lsacl/lsacl.c2
-rw-r--r--usr/src/cmd/fs.d/smbclnt/mount/mntopts.h110
-rw-r--r--usr/src/cmd/fs.d/smbclnt/mount/mount.c400
-rw-r--r--usr/src/cmd/mdb/common/modules/smbfs/smbfs.c176
-rw-r--r--usr/src/common/smbclnt/smbfs_ntacl.c (renamed from usr/src/lib/libsmbfs/smb/acl_conv.c)190
-rw-r--r--usr/src/common/smbclnt/smbfs_ntacl.h (renamed from usr/src/lib/libsmbfs/smb/acl_nt.h)48
-rw-r--r--usr/src/lib/libsmbfs/Makefile.com32
-rw-r--r--usr/src/lib/libsmbfs/netsmb/smbfs_acl.h25
-rw-r--r--usr/src/lib/libsmbfs/smb/acl_api.c10
-rw-r--r--usr/src/lib/libsmbfs/smb/acl_print.c2
-rw-r--r--usr/src/lib/libsmbfs/smb/ctx.c27
-rw-r--r--usr/src/lib/libsmbfs/smb/file.c38
-rw-r--r--usr/src/lib/libsmbfs/smb/iod_cl.c4
-rw-r--r--usr/src/lib/libsmbfs/smb/keychain.c7
-rw-r--r--usr/src/lib/libsmbfs/smb/krb5ssp.c4
-rw-r--r--usr/src/lib/libsmbfs/smb/lgrep.awk54
-rw-r--r--usr/src/lib/libsmbfs/smb/mbuf.c181
-rw-r--r--usr/src/lib/libsmbfs/smb/nb_name.c4
-rw-r--r--usr/src/lib/libsmbfs/smb/nb_ssn.c4
-rw-r--r--usr/src/lib/libsmbfs/smb/nbns_rq.c44
-rw-r--r--usr/src/lib/libsmbfs/smb/negprot.c35
-rw-r--r--usr/src/lib/libsmbfs/smb/netshareenum.c6
-rw-r--r--usr/src/lib/libsmbfs/smb/ntlm.c32
-rw-r--r--usr/src/lib/libsmbfs/smb/ntlmssp.c50
-rw-r--r--usr/src/lib/libsmbfs/smb/print.c6
-rw-r--r--usr/src/lib/libsmbfs/smb/private.h80
-rw-r--r--usr/src/lib/libsmbfs/smb/rap.c8
-rw-r--r--usr/src/lib/libsmbfs/smb/rq.c75
-rw-r--r--usr/src/lib/libsmbfs/smb/signing.c12
-rw-r--r--usr/src/lib/libsmbfs/smb/ssnsetup.c34
-rw-r--r--usr/src/lib/libsmbfs/smb/ssp.c4
-rw-r--r--usr/src/pkgdefs/SUNWsmbfsu/prototype_com1
-rw-r--r--usr/src/uts/common/Makefile.files12
-rw-r--r--usr/src/uts/common/Makefile.rules7
-rw-r--r--usr/src/uts/common/fs/smbclnt/netsmb/smb_conn.c7
-rw-r--r--usr/src/uts/common/fs/smbclnt/netsmb/smb_conn.h14
-rw-r--r--usr/src/uts/common/fs/smbclnt/netsmb/smb_dev.c15
-rw-r--r--usr/src/uts/common/fs/smbclnt/netsmb/smb_iod.c22
-rw-r--r--usr/src/uts/common/fs/smbclnt/netsmb/smb_pass.c13
-rw-r--r--usr/src/uts/common/fs/smbclnt/netsmb/smb_rq.c44
-rw-r--r--usr/src/uts/common/fs/smbclnt/netsmb/smb_sign.c25
-rw-r--r--usr/src/uts/common/fs/smbclnt/netsmb/smb_smb.c392
-rw-r--r--usr/src/uts/common/fs/smbclnt/netsmb/smb_subr.h14
-rw-r--r--usr/src/uts/common/fs/smbclnt/netsmb/smb_subrs.c53
-rw-r--r--usr/src/uts/common/fs/smbclnt/netsmb/smb_time.c353
-rw-r--r--usr/src/uts/common/fs/smbclnt/netsmb/smb_tran.c9
-rw-r--r--usr/src/uts/common/fs/smbclnt/netsmb/smb_trantcp.c22
-rw-r--r--usr/src/uts/common/fs/smbclnt/netsmb/smb_usr.c8
-rw-r--r--usr/src/uts/common/fs/smbclnt/netsmb/subr_mchain.c37
-rw-r--r--usr/src/uts/common/fs/smbclnt/smbfs/smbfs.h55
-rw-r--r--usr/src/uts/common/fs/smbclnt/smbfs/smbfs_acl.c130
-rw-r--r--usr/src/uts/common/fs/smbclnt/smbfs/smbfs_client.c448
-rw-r--r--usr/src/uts/common/fs/smbclnt/smbfs/smbfs_node.c392
-rw-r--r--usr/src/uts/common/fs/smbclnt/smbfs/smbfs_node.h247
-rw-r--r--usr/src/uts/common/fs/smbclnt/smbfs/smbfs_smb.c1449
-rw-r--r--usr/src/uts/common/fs/smbclnt/smbfs/smbfs_subr.c205
-rw-r--r--usr/src/uts/common/fs/smbclnt/smbfs/smbfs_subr.h88
-rw-r--r--usr/src/uts/common/fs/smbclnt/smbfs/smbfs_subr2.c912
-rw-r--r--usr/src/uts/common/fs/smbclnt/smbfs/smbfs_vfsops.c208
-rw-r--r--usr/src/uts/common/fs/smbclnt/smbfs/smbfs_vnops.c653
-rw-r--r--usr/src/uts/common/fs/smbclnt/smbfs/smbfs_xattr.c36
-rw-r--r--usr/src/uts/common/netsmb/mchain.h160
-rw-r--r--usr/src/uts/common/sys/fs/smbfs_mount.h61
-rw-r--r--usr/src/uts/intel/nsmb/Makefile6
-rw-r--r--usr/src/uts/intel/smbfs/Makefile5
-rw-r--r--usr/src/uts/sparc/nsmb/Makefile4
-rw-r--r--usr/src/uts/sparc/smbfs/Makefile5
67 files changed, 3990 insertions, 3826 deletions
diff --git a/usr/src/cmd/fs.d/smbclnt/lsacl/lsacl.c b/usr/src/cmd/fs.d/smbclnt/lsacl/lsacl.c
index 1285251898..afce3a64fd 100644
--- a/usr/src/cmd/fs.d/smbclnt/lsacl/lsacl.c
+++ b/usr/src/cmd/fs.d/smbclnt/lsacl/lsacl.c
@@ -61,7 +61,7 @@ main(int argc, char **argv)
uid_t uid;
gid_t gid;
int error, fd;
- i_ntsd_t *sd;
+ struct i_ntsd *sd;
progname = argv[0];
diff --git a/usr/src/cmd/fs.d/smbclnt/mount/mntopts.h b/usr/src/cmd/fs.d/smbclnt/mount/mntopts.h
deleted file mode 100644
index 6b908f3c7f..0000000000
--- a/usr/src/cmd/fs.d/smbclnt/mount/mntopts.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (c) 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)mntopts.h 8.7 (Berkeley) 3/29/95
- * $Id: mntopts.h,v 1.4 2004/03/19 01:49:47 lindak Exp $
- */
-
-/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _CIFS_MNTOPTS_H
-#define _CIFS_MNTOPTS_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <sys/vfs.h>
-#ifdef UNPORTED
-/* In solaris this is defined in proto/root_i386/usr/include/sys/vfs.h */
-struct mntopt {
- const char *m_option; /* option name */
- int m_inverse; /* if a negative option, e.g. "dev" */
- int m_flag; /* bit to set, e.g. MNT_RDONLY */
- int m_altloc; /* 1 => set bit in altflags */
-};
-#endif /* UNPORTED */
-
-/* User-visible MNT_ flags. */
-#define MOPT_ASYNC { "async", 0, MNT_ASYNC, 0 }
-#define MOPT_NODEV { "dev", 1, MNT_NODEV, 0 }
-#define MOPT_NOEXEC { "exec", 1, MNT_NOEXEC, 0 }
-#define MOPT_NOSUID { "suid", 1, MNT_NOSUID, 0 }
-#define MOPT_RDONLY { "rdonly", 0, MNT_RDONLY, 0 }
-#define MOPT_SYNC { "sync", 0, MNT_SYNCHRONOUS, 0 }
-#define MOPT_UNION { "union", 0, MNT_UNION, 0 }
-#define MOPT_USERQUOTA { "userquota", 0, 0, 0 }
-#define MOPT_GROUPQUOTA { "groupquota", 0, 0, 0 }
-#define MOPT_BROWSE { "browse", 1, MNT_DONTBROWSE, 0 }
-#define MOPT_AUTOMOUNTED { "automounted", 0, MNT_AUTOMOUNTED, 0 }
-
-/* Control flags. */
-#define MOPT_FORCE { "force", 0, MNT_FORCE, 0 }
-#define MOPT_UPDATE { "update", 0, MNT_UPDATE, 0 }
-#define MOPT_RO { "ro", 0, MNT_RDONLY, 0 }
-#define MOPT_RW { "rw", 1, MNT_RDONLY, 0 }
-
-/* This is parsed by mount(1m), but is ignored by specific mount_*(1m)s. */
-#define MOPT_AUTO { "auto", 0, 0, 0 }
-
-#define MOPT_FSTAB_COMPAT \
- MOPT_RO, \
- MOPT_RW, \
- MOPT_AUTO
-
-/* Standard options which all mounts can understand. */
-#define MOPT_STDOPTS \
- MOPT_USERQUOTA, \
- MOPT_GROUPQUOTA, \
- MOPT_FSTAB_COMPAT, \
- MOPT_NODEV, \
- MOPT_NOEXEC, \
- MOPT_NOSUID, \
- MOPT_RDONLY, \
- MOPT_UNION, \
- MOPT_BROWSE, \
- MOPT_AUTOMOUNTED
-
-void getmntopts(const char *, const mntopt_t *, int *, int *);
-
-extern int getmnt_silent;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _CIFS_MNTOPTS_H */
diff --git a/usr/src/cmd/fs.d/smbclnt/mount/mount.c b/usr/src/cmd/fs.d/smbclnt/mount/mount.c
index 9068d093b6..5b2cac4ee7 100644
--- a/usr/src/cmd/fs.d/smbclnt/mount/mount.c
+++ b/usr/src/cmd/fs.d/smbclnt/mount/mount.c
@@ -47,7 +47,6 @@
#include <stdlib.h>
#include <errno.h>
#include <err.h>
-#include <sysexits.h>
#include <libintl.h>
#include <locale.h>
#include <libscf.h>
@@ -59,93 +58,110 @@
#include <sys/mntent.h>
#include <sys/mnttab.h>
-/* This needs to know ctx->ct_dev_fd, etc. */
-#include <netsmb/smb_lib.h>
-
#include <sys/fs/smbfs_mount.h>
-#include "mntopts.h"
+/* This needs to know ctx->ct_dev_fd, etc. */
+#include <netsmb/smb_lib.h>
extern char *optarg;
extern int optind;
static char mount_point[MAXPATHLEN + 1];
static void usage(void);
-static int setsubopt(smb_ctx_t *, struct smbfs_args *, int, char *);
-
-/* smbfs options */
-#define MNTOPT_DOMAIN "domain"
-#define MNTOPT_USER "user"
-#define MNTOPT_DIRPERMS "dirperms"
-#define MNTOPT_FILEPERMS "fileperms"
-#define MNTOPT_GID "gid"
-#define MNTOPT_UID "uid"
-#define MNTOPT_NOPROMPT "noprompt"
-
-#define OPT_DOMAIN 1
-#define OPT_USER 2
-#define OPT_DIRPERMS 3
-#define OPT_FILEPERMS 4
-#define OPT_GID 5
-#define OPT_UID 6
-#define OPT_NOPROMPT 7
-
-/* generic VFS options */
-#define OPT_RO 10
-#define OPT_RW 11
-#define OPT_SUID 12
-#define OPT_NOSUID 13
-#define OPT_DEVICES 14
-#define OPT_NODEVICES 15
-#define OPT_SETUID 16
-#define OPT_NOSETUID 17
-#define OPT_EXEC 18
-#define OPT_NOEXEC 19
-
-struct smbfsopts {
- char *name;
- int index;
-};
-
-struct smbfsopts opts[] = {
- {MNTOPT_DOMAIN, OPT_DOMAIN},
- {MNTOPT_USER, OPT_USER},
- {MNTOPT_DIRPERMS, OPT_DIRPERMS},
- {MNTOPT_FILEPERMS, OPT_FILEPERMS},
- {MNTOPT_GID, OPT_GID},
- {MNTOPT_UID, OPT_UID},
- {MNTOPT_NOPROMPT, OPT_NOPROMPT},
- {MNTOPT_RO, OPT_RO},
- {MNTOPT_RW, OPT_RW},
- {MNTOPT_SUID, OPT_SUID},
- {MNTOPT_NOSUID, OPT_NOSUID},
- {MNTOPT_DEVICES, OPT_DEVICES},
- {MNTOPT_NODEVICES, OPT_NODEVICES},
- {MNTOPT_SETUID, OPT_SETUID},
- {MNTOPT_NOSETUID, OPT_NOSETUID},
- {MNTOPT_EXEC, OPT_EXEC},
- {MNTOPT_NOEXEC, OPT_NOEXEC},
- {NULL, 0}
+static int setsubopt(smb_ctx_t *, struct smbfs_args *, char *);
+
+const char * const optlist[] = {
+
+ /* Generic VFS options. */
+#define OPT_RO 0
+ MNTOPT_RO,
+#define OPT_RW 1
+ MNTOPT_RW,
+#define OPT_SUID 2
+ MNTOPT_SUID,
+#define OPT_NOSUID 3
+ MNTOPT_NOSUID,
+#define OPT_DEVICES 4
+ MNTOPT_DEVICES,
+#define OPT_NODEVICES 5
+ MNTOPT_NODEVICES,
+#define OPT_SETUID 6
+ MNTOPT_SETUID,
+#define OPT_NOSETUID 7
+ MNTOPT_NOSETUID,
+#define OPT_EXEC 8
+ MNTOPT_EXEC,
+#define OPT_NOEXEC 9
+ MNTOPT_NOEXEC,
+#define OPT_XATTR 10
+ MNTOPT_XATTR,
+#define OPT_NOXATTR 11
+ MNTOPT_NOXATTR,
+
+ /* Sort of generic (from NFS) */
+#define OPT_NOAC 12
+ MNTOPT_NOAC,
+#define OPT_ACTIMEO 13
+ MNTOPT_ACTIMEO,
+#define OPT_ACREGMIN 14
+ MNTOPT_ACREGMIN,
+#define OPT_ACREGMAX 15
+ MNTOPT_ACREGMAX,
+#define OPT_ACDIRMIN 16
+ MNTOPT_ACDIRMIN,
+#define OPT_ACDIRMAX 17
+ MNTOPT_ACDIRMAX,
+
+ /* smbfs-specifis options */
+#define OPT_DOMAIN 18
+ "domain",
+#define OPT_USER 19
+ "user",
+#define OPT_UID 20
+ "uid",
+#define OPT_GID 21
+ "gid",
+#define OPT_DIRPERMS 22
+ "dirperms",
+#define OPT_FILEPERMS 23
+ "fileperms",
+#define OPT_NOPROMPT 24
+ "noprompt",
+
+ NULL
};
static int Oflg = 0; /* Overlay mounts */
static int qflg = 0; /* quiet - don't print warnings on bad options */
-static int ro = 0; /* read-only mount */
static int noprompt = 0; /* don't prompt for password */
-#define RET_ERR 33
+/* Note: smbfs uses _both_ kinds of options. */
+static int mntflags = MS_DATA | MS_OPTIONSTR;
+
+#define EX_OK 0 /* normal */
+#define EX_OPT 1 /* bad options, usage, etc */
+#define EX_MNT 2 /* mount point problems, etc */
+#define RET_ERR 3 /* later errors */
+
#define SERVICE "svc:/network/smb/client:default"
struct smbfs_args mdata;
struct mnttab mnt;
-char optbuf[MAX_MNTOPT_STR];
+
+/*
+ * Initialize this with "rw" just to have something there,
+ * so we don't have to decide whether to add a comma when
+ * we strcat another option. Note the "rw" may be changed
+ * to an "ro" by option processing.
+ */
+char optbuf[MAX_MNTOPT_STR] = "rw";
int
main(int argc, char *argv[])
{
struct smb_ctx *ctx = NULL;
struct stat st;
- int opt, error, err2, mntflags;
+ int opt, error, err2;
static char *fstype = MNTTYPE_SMBFS;
char *env, *state;
@@ -188,13 +204,11 @@ main(int argc, char *argv[])
exit(RET_ERR);
mnt.mnt_mntopts = optbuf;
- mntflags = MS_DATA;
bzero(&mdata, sizeof (mdata));
mdata.version = SMBFS_VERSION; /* smbfs mount version */
mdata.uid = (uid_t)-1;
mdata.gid = (gid_t)-1;
- mdata.caseopt = SMB_CS_NONE;
error = smb_ctx_alloc(&ctx);
if (error)
@@ -209,11 +223,11 @@ main(int argc, char *argv[])
error = smb_ctx_parseunc(ctx, argv[argc - 2],
SMBL_SHARE, SMBL_SHARE, USE_DISKDEV, NULL);
if (error)
- exit(RET_ERR);
+ exit(EX_OPT);
error = smb_ctx_readrc(ctx);
if (error)
- exit(RET_ERR);
+ exit(EX_OPT);
while ((opt = getopt(argc, argv, "ro:Oq")) != -1) {
switch (opt) {
@@ -226,19 +240,13 @@ main(int argc, char *argv[])
break;
case 'r':
- ro++;
+ mntflags |= MS_RDONLY;
break;
case 'o': {
- char *nextopt, *comma, *equals, *sopt, *soptval;
- int i, ret;
-
- if (strlen(optarg) >= MAX_MNTOPT_STR) {
- if (!qflg)
- warnx(gettext(
- "option string too long"));
- exit(RET_ERR);
- }
+ char *nextopt, *comma, *sopt;
+ int ret;
+
for (sopt = optarg; sopt != NULL; sopt = nextopt) {
comma = strchr(sopt, ',');
if (comma) {
@@ -246,33 +254,10 @@ main(int argc, char *argv[])
*comma = '\0';
} else
nextopt = NULL;
- equals = strchr(sopt, '=');
- if (equals) {
- soptval = equals + 1;
- *equals = '\0';
- } else
- soptval = NULL;
- for (i = 0; opts[i].name != NULL; i++) {
- if (strcmp(sopt, opts[i].name) == 0)
- break;
- }
- if (opts[i].name == NULL) {
- if (equals)
- *equals = '=';
- if (!qflg)
- errx(RET_ERR, gettext(
- "Bad option '%s'"), sopt);
- if (comma)
- *comma = ',';
- continue;
- }
- ret = setsubopt(ctx, &mdata,
- opts[i].index, soptval);
+ ret = setsubopt(ctx, &mdata, sopt);
if (ret != 0)
- exit(RET_ERR);
- if (equals)
- *equals = '=';
- (void) strcat(mnt.mnt_mntopts, sopt);
+ exit(EX_OPT);
+ /* undo changes to optarg */
if (comma)
*comma = ',';
}
@@ -288,12 +273,10 @@ main(int argc, char *argv[])
if (Oflg)
mntflags |= MS_OVERLAY;
- if (ro) {
+ if (mntflags & MS_RDONLY) {
char *p;
-
- mntflags |= MS_RDONLY;
/* convert "rw"->"ro" */
- if (p = strstr(mnt.mnt_mntopts, "rw")) {
+ if (p = strstr(optbuf, "rw")) {
if (*(p+2) == ',' || *(p+2) == '\0')
*(p+1) = 'o';
}
@@ -307,11 +290,11 @@ main(int argc, char *argv[])
realpath(argv[optind+1], mount_point);
if (stat(mount_point, &st) == -1)
- err(EX_OSERR, gettext("could not find mount point %s"),
+ err(EX_MNT, gettext("could not find mount point %s"),
mount_point);
if (!S_ISDIR(st.st_mode)) {
errno = ENOTDIR;
- err(EX_OSERR, gettext("can't mount on %s"), mount_point);
+ err(EX_MNT, gettext("can't mount on %s"), mount_point);
}
/*
@@ -379,40 +362,57 @@ again:
mntflags, fstype, &mdata, sizeof (mdata),
mnt.mnt_mntopts, MAX_MNTOPT_STR) < 0) {
if (errno != ENOENT) {
- err(EX_OSERR, gettext("mount_smbfs: %s"),
+ err(EX_MNT, gettext("mount_smbfs: %s"),
mnt.mnt_mountp);
} else {
struct stat sb;
if (stat(mnt.mnt_mountp, &sb) < 0 &&
errno == ENOENT)
- err(EX_OSERR, gettext("mount_smbfs: %s"),
+ err(EX_MNT, gettext("mount_smbfs: %s"),
mnt.mnt_mountp);
else
- err(EX_OSERR, gettext("mount_smbfs: %s"),
+ err(EX_MNT, gettext("mount_smbfs: %s"),
mnt.mnt_special);
}
}
smb_ctx_free(ctx);
- if (error) {
- smb_error(gettext("mount error: %s"), error, mount_point);
- exit(RET_ERR);
- }
return (0);
}
+#define bad(val) (val == NULL || !isdigit(*val))
+
int
-setsubopt(smb_ctx_t *ctx, struct smbfs_args *mdatap, int index, char *optarg)
+setsubopt(smb_ctx_t *ctx, struct smbfs_args *mdatap, char *subopt)
{
+ char *equals, *optarg;
struct passwd *pwd;
struct group *grp;
- long l;
- int err = 0;
- char *next;
+ long val;
+ int rc = EX_OK;
+ int index;
+ char *p;
+
+ equals = strchr(subopt, '=');
+ if (equals) {
+ *equals = '\0';
+ optarg = equals + 1;
+ } else
+ optarg = NULL;
+
+ for (index = 0; optlist[index] != NULL; index++) {
+ if (strcmp(subopt, optlist[index]) == 0)
+ break;
+ }
+
+ /*
+ * Note: if the option was unknown, index will
+ * point to the NULL at the end of optlist[],
+ * and we'll take the switch default.
+ */
switch (index) {
- case OPT_RO:
- case OPT_RW:
+
case OPT_SUID:
case OPT_NOSUID:
case OPT_DEVICES:
@@ -421,15 +421,106 @@ setsubopt(smb_ctx_t *ctx, struct smbfs_args *mdatap, int index, char *optarg)
case OPT_NOSETUID:
case OPT_EXEC:
case OPT_NOEXEC:
- /* We don't have to handle generic options here */
- return (0);
+ case OPT_XATTR:
+ case OPT_NOXATTR:
+ /*
+ * These options are handled via the
+ * generic option string mechanism.
+ * None of these take an optarg.
+ */
+ if (optarg != NULL)
+ goto badval;
+ (void) strlcat(optbuf, ",", sizeof (optbuf));
+ if (strlcat(optbuf, subopt, sizeof (optbuf)) >=
+ sizeof (optbuf)) {
+ if (!qflg)
+ warnx(gettext("option string too long"));
+ rc = EX_OPT;
+ }
+ break;
+
+ /*
+ * OPT_RO, OPT_RW, are actually generic too,
+ * but we use the mntflags for these, and
+ * then update the options string later.
+ */
+ case OPT_RO:
+ mntflags |= MS_RDONLY;
+ break;
+ case OPT_RW:
+ mntflags &= ~MS_RDONLY;
+ break;
+
+ /*
+ * NFS-derived options for attribute cache
+ * handling (disable, set min/max timeouts)
+ */
+ case OPT_NOAC:
+ mdatap->flags |= SMBFS_MF_NOAC;
+ break;
+
+ case OPT_ACTIMEO:
+ errno = 0;
+ val = strtol(optarg, &p, 10);
+ if (errno || *p != 0)
+ goto badval;
+ mdatap->acdirmin = mdatap->acregmin = val;
+ mdatap->acdirmax = mdatap->acregmax = val;
+ mdatap->flags |= SMBFS_MF_ACDIRMAX;
+ mdatap->flags |= SMBFS_MF_ACREGMAX;
+ mdatap->flags |= SMBFS_MF_ACDIRMIN;
+ mdatap->flags |= SMBFS_MF_ACREGMIN;
+ break;
+
+ case OPT_ACREGMIN:
+ errno = 0;
+ val = strtol(optarg, &p, 10);
+ if (errno || *p != 0)
+ goto badval;
+ mdatap->acregmin = val;
+ mdatap->flags |= SMBFS_MF_ACREGMIN;
+ break;
+
+ case OPT_ACREGMAX:
+ errno = 0;
+ val = strtol(optarg, &p, 10);
+ if (errno || *p != 0)
+ goto badval;
+ mdatap->acregmax = val;
+ mdatap->flags |= SMBFS_MF_ACREGMAX;
+ break;
+
+ case OPT_ACDIRMIN:
+ errno = 0;
+ val = strtol(optarg, &p, 10);
+ if (errno || *p != 0)
+ goto badval;
+ mdatap->acdirmin = val;
+ mdatap->flags |= SMBFS_MF_ACDIRMIN;
+ break;
+
+ case OPT_ACDIRMAX:
+ errno = 0;
+ val = strtol(optarg, &p, 10);
+ if (errno || *p != 0)
+ goto badval;
+ mdatap->acdirmax = val;
+ mdatap->flags |= SMBFS_MF_ACDIRMAX;
+ break;
+ /*
+ * SMBFS-specific options. Some of these
+ * don't go through the mount system call,
+ * but just set libsmbfs options.
+ */
case OPT_DOMAIN:
- err = smb_ctx_setdomain(ctx, optarg, B_TRUE);
+ if (smb_ctx_setdomain(ctx, optarg, B_TRUE) != 0)
+ rc = EX_OPT;
break;
case OPT_USER:
- err = smb_ctx_setuser(ctx, optarg, B_TRUE);
+ if (smb_ctx_setuser(ctx, optarg, B_TRUE) != 0)
+ rc = EX_OPT;
break;
case OPT_UID:
@@ -438,49 +529,62 @@ setsubopt(smb_ctx_t *ctx, struct smbfs_args *mdatap, int index, char *optarg)
if (pwd == NULL) {
if (!qflg)
warnx(gettext("unknown user '%s'"), optarg);
- err = -1;
+ rc = EX_OPT;
} else {
mdatap->uid = pwd->pw_uid;
}
break;
+
case OPT_GID:
grp = isdigit(optarg[0]) ?
getgrgid(atoi(optarg)) : getgrnam(optarg);
if (grp == NULL) {
if (!qflg)
warnx(gettext("unknown group '%s'"), optarg);
- err = -1;
+ rc = EX_OPT;
} else {
mdatap->gid = grp->gr_gid;
}
break;
+
case OPT_DIRPERMS:
errno = 0;
- l = strtol(optarg, &next, 8);
- if (errno || *next != 0) {
- if (!qflg)
- warnx(gettext(
- "invalid value for directory mode"));
- err = -1;
- } else {
- mdatap->dir_mode = l;
- }
+ val = strtol(optarg, &p, 8);
+ if (errno || *p != 0)
+ goto badval;
+ mdatap->dir_mode = val;
break;
+
case OPT_FILEPERMS:
errno = 0;
- l = strtol(optarg, &next, 8);
- if (errno || *next != 0) {
- if (!qflg)
- warnx(gettext("invalid value for file mode"));
- err = -1;
- } else {
- mdatap->file_mode = l;
- }
+ val = strtol(optarg, &p, 8);
+ if (errno || *p != 0)
+ goto badval;
+ mdatap->file_mode = val;
break;
+
case OPT_NOPROMPT:
noprompt++;
+ break;
+
+ default:
+ if (!qflg)
+ warnx(gettext("unknown option %s"), subopt);
+ rc = EX_OPT;
+ break;
+
+ badval:
+ if (!qflg)
+ warnx(gettext("invalid value for %s"), subopt);
+ rc = EX_OPT;
+ break;
}
- return (err);
+
+ /* Undo changes made to subopt */
+ if (equals)
+ *equals = '=';
+
+ return (rc);
}
static void
@@ -490,5 +594,5 @@ usage(void)
gettext("usage: mount -F smbfs [-Orq] [-o option[,option]]"
" //[workgroup;][user[:password]@]server[/share] path"));
- exit(EX_USAGE);
+ exit(EX_OPT);
}
diff --git a/usr/src/cmd/mdb/common/modules/smbfs/smbfs.c b/usr/src/cmd/mdb/common/modules/smbfs/smbfs.c
index 11aeb9f081..4841a41cd8 100644
--- a/usr/src/cmd/mdb/common/modules/smbfs/smbfs.c
+++ b/usr/src/cmd/mdb/common/modules/smbfs/smbfs.c
@@ -20,13 +20,10 @@
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/mdb_modapi.h>
#include <sys/types.h>
#include <sys/refstr_impl.h>
@@ -176,138 +173,29 @@ smbfs_vfs_help(void)
}
/*
- * Walker for the smbnode hash table.
- */
-
-typedef struct smbnode_walk_data {
- rhashq_t *smbtab; /* (our copy of) the smbtable */
- int tabsize; /* size of table */
- int nextidx; /* next bucket index */
- uintptr_t buckptr; /* target addr of current bucket */
- uintptr_t nodeptr; /* target addr of current smbnode */
- smbnode_t node; /* scratch space for _step */
-} smbnode_walk_data_t;
-
-int
-smbnode_walk_init(mdb_walk_state_t *wsp)
-{
- size_t tabsz_bytes;
- int tabsize;
- uintptr_t smbtab;
- smbnode_walk_data_t *smbw;
-
- if (wsp->walk_addr != NULL) {
- mdb_warn("smbnode only supports global walks\n");
- return (WALK_ERR);
- }
-
- if (mdb_readvar(&tabsize, "smbtablesize") == -1) {
- mdb_warn("failed to read `smbtablesize'\n");
- return (WALK_ERR);
- }
-
- if (tabsize == 0) {
- return (WALK_DONE);
- }
-
- if (mdb_readvar(&smbtab, "smbtable") == -1) {
- mdb_warn("failed to read `smbtable'\n");
- return (WALK_ERR);
- }
-
- smbw = mdb_alloc(sizeof (*smbw), UM_SLEEP | UM_GC);
-
- tabsz_bytes = tabsize * sizeof (rhashq_t);
- smbw->smbtab = mdb_alloc(tabsz_bytes, UM_SLEEP | UM_GC);
- if (mdb_vread(smbw->smbtab, tabsz_bytes, smbtab) != tabsz_bytes) {
- mdb_warn("failed to read in smbtable from %p", smbtab);
- return (WALK_ERR);
- }
- smbw->tabsize = tabsize;
- smbw->nextidx = 1;
- smbw->buckptr = smbtab;
- smbw->nodeptr = (uintptr_t)smbw->smbtab[0].r_hashf;
- wsp->walk_data = smbw;
-
- return (WALK_NEXT);
-}
-
-int
-smbnode_walk_step(mdb_walk_state_t *wsp)
-{
- smbnode_walk_data_t *smbw = wsp->walk_data;
- int status;
-
-next_bucket:
- while (smbw->nodeptr == smbw->buckptr &&
- smbw->nextidx < smbw->tabsize) {
-
- /* Skip an empty bucket */
- rhashq_t *h = &smbw->smbtab[smbw->nextidx];
- smbw->nodeptr = (uintptr_t)h->r_hashf;
- smbw->nextidx++;
- smbw->buckptr += sizeof (rhashq_t);
- }
-
- if (smbw->nodeptr == smbw->buckptr)
- return (WALK_DONE);
-
- if (mdb_vread(&smbw->node, sizeof (smbw->node),
- smbw->nodeptr) != sizeof (smbw->node)) {
- mdb_warn("failed to read smbnode at %p in bucket %p\n",
- smbw->nodeptr, smbw->buckptr);
- /* Proceed with next bucket. */
- smbw->nodeptr = smbw->buckptr;
- goto next_bucket;
- }
-
- status = wsp->walk_callback(smbw->nodeptr,
- &smbw->node, wsp->walk_cbdata);
-
- /* Move to next node in this bucket */
- smbw->nodeptr = (uintptr_t)smbw->node.r_hashf;
-
- return (status);
-}
-
-/*ARGSUSED*/
-void
-smbnode_walk_fini(mdb_walk_state_t *wsp)
-{
- /* UM_GC takes care of it all. */
-}
-
-/*
* Dcmd (and callback function) to print a summary of
- * all smbnodes in the node hash table.
+ * all smbnodes in the node "hash" (cache) AVL tree.
*/
-typedef struct smbnode_cbdata {
+typedef struct smbfs_node_cbdata {
int flags;
int printed_header;
- uintptr_t smi; /* optional filtering by VFS */
- /* TODO: only nodes with a given [-h]ash */
- vnode_t vn; /* scratch space for smbnode_cb */
-} smbnode_cbdata_t;
+ vnode_t vn;
+} smbfs_node_cbdata_t;
int
-smbnode_cb(uintptr_t addr, const void *data, void *arg)
+smbfs_node_cb(uintptr_t addr, const void *data, void *arg)
{
const smbnode_t *np = data;
- smbnode_cbdata_t *cbd = arg;
-
- /* Optional filtering by mount point. */
- if (cbd->smi && cbd->smi != (uintptr_t)np->n_mount) {
- return (WALK_NEXT);
- }
+ smbfs_node_cbdata_t *cbd = arg;
if (cbd->printed_header == 0) {
cbd->printed_header = 1;
- mdb_printf("// smbnode vnode rpath\n");
+ mdb_printf("// vnode smbnode rpath\n");
}
- mdb_printf(" %-p", addr); /* smbnode */
mdb_printf(" %-p", (uintptr_t)np->r_vnode);
+ mdb_printf(" %-p", addr); /* smbnode */
print_str((uintptr_t)np->n_rpath);
mdb_printf("\n");
@@ -320,9 +208,8 @@ smbnode_cb(uintptr_t addr, const void *data, void *arg)
(uintptr_t)np->r_vnode);
} else {
/* Interesting parts of vnode_t */
- mdb_printf("v_type: %d v_path:",
- cbd->vn.v_type);
- print_str((uintptr_t)cbd->vn.v_path);
+ mdb_printf("v_type=%d v_count=%d",
+ cbd->vn.v_type, cbd->vn.v_count);
mdb_printf("\n");
}
mdb_dec_indent(2);
@@ -332,55 +219,54 @@ smbnode_cb(uintptr_t addr, const void *data, void *arg)
}
int
-smbnode_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
+smbfs_node_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
- smbnode_cbdata_t *cbd;
- smbnode_t *np;
+ smbfs_node_cbdata_t *cbd;
cbd = mdb_zalloc(sizeof (*cbd), UM_SLEEP | UM_GC);
if (mdb_getopts(argc, argv,
'v', MDB_OPT_SETBITS, OPT_VERBOSE, &cbd->flags,
- 'm', MDB_OPT_UINTPTR, &cbd->smi, NULL) != argc) {
+ NULL) != argc) {
return (DCMD_USAGE);
}
if (!(flags & DCMD_ADDRSPEC)) {
- if (mdb_walk("smbnode", smbnode_cb, cbd)
- == -1) {
- mdb_warn("cannot walk smbnodes");
- return (DCMD_ERR);
- }
- return (DCMD_OK);
+ mdb_warn("expect an smbmntinfo_t addr");
+ return (DCMD_USAGE);
}
+ addr += OFFSETOF(smbmntinfo_t, smi_hash_avl);
- np = mdb_alloc(sizeof (*np), UM_SLEEP | UM_GC);
- SMBFS_OBJ_FETCH(addr, smbnode_t, np, DCMD_ERR);
- smbnode_cb(addr, np, cbd);
+ if (mdb_pwalk("genunix`avl", smbfs_node_cb, cbd, addr) == -1) {
+ mdb_warn("cannot walk smbfs nodes");
+ return (DCMD_ERR);
+ }
return (DCMD_OK);
}
void
-smbnode_help(void)
+smbfs_node_help(void)
{
mdb_printf("Options:\n"
- " -m mntinfo only show smbnodes belonging to mntinfo\n"
" -v be verbose when displaying smbnodes\n");
}
static const mdb_dcmd_t dcmds[] = {
- { "smbfs_vfs", "?[-v]",
+ {
+ "smbfs_vfs", "?[-v]",
"show smbfs-mounted vfs structs",
- smbfs_vfs_dcmd, smbfs_vfs_help },
- { "smbnode", "?[-v] [-m mntinfo]",
- "show smbnodes", smbnode_dcmd, smbnode_help },
+ smbfs_vfs_dcmd, smbfs_vfs_help
+ },
+ {
+ "smbfs_node", "?[-v]",
+ "given an smbmntinfo_t, list smbnodes",
+ smbfs_node_dcmd, smbfs_node_help
+ },
{NULL}
};
static const mdb_walker_t walkers[] = {
- { "smbnode", "walk smbnode hash table",
- smbnode_walk_init, smbnode_walk_step, smbnode_walk_fini },
{NULL}
};
diff --git a/usr/src/lib/libsmbfs/smb/acl_conv.c b/usr/src/common/smbclnt/smbfs_ntacl.c
index d19b323dfe..79d307f6ca 100644
--- a/usr/src/lib/libsmbfs/smb/acl_conv.c
+++ b/usr/src/common/smbclnt/smbfs_ntacl.c
@@ -25,43 +25,39 @@
*/
/*
- * ACL support for smbfs
- *
- * May want to move some of this to usr/src/common
- * and compile with the smbfs kmod too, once we
- * implement VOP_GETSECATTR, VOP_SETSECATTR.
+ * ACL conversion support for smbfs
+ * (To/from NT/ZFS-style ACLs.)
*/
#include <sys/types.h>
#include <sys/errno.h>
+#include <sys/acl.h>
+#include <sys/byteorder.h>
+
+#ifdef _KERNEL
+
#include <sys/cred.h>
#include <sys/cmn_err.h>
#include <sys/kmem.h>
#include <sys/sunddi.h>
-#include <sys/acl.h>
#include <sys/vnode.h>
#include <sys/vfs.h>
-#include <sys/byteorder.h>
-#include <errno.h>
+#include <sys/kidmap.h>
+
+#else /* _KERNEL */
+
#include <stdio.h>
-#include <string.h>
+#include <stdlib.h>
#include <strings.h>
-#include <unistd.h>
-#include <umem.h>
#include <idmap.h>
-#include <sys/fs/smbfs_ioctl.h>
+#endif /* _KERNEL */
#include <netsmb/mchain.h>
#include <netsmb/smb.h>
-
-#include <netsmb/smb_lib.h>
-#include <netsmb/smbfs_acl.h>
-
-#include "acl_nt.h"
-#include "private.h"
+#include "smbfs_ntacl.h"
#ifdef _KERNEL
#define MALLOC(size) kmem_alloc(size, KM_SLEEP)
@@ -80,7 +76,6 @@ FREESZ(void *p, size_t sz)
#endif /* lint */
#endif /* _KERNEL */
-
#define ERRCHK(expr) if ((error = expr) != 0) goto errout
/*
@@ -99,7 +94,7 @@ ifree_sid(i_ntsid_t *sid)
}
static int
-mb_get_sid(mbdata_t *mbp, i_ntsid_t **sidp)
+md_get_sid(mdchain_t *mdp, i_ntsid_t **sidp)
{
i_ntsid_t *sid = NULL;
uint8_t revision, subauthcount;
@@ -107,9 +102,9 @@ mb_get_sid(mbdata_t *mbp, i_ntsid_t **sidp)
size_t sidsz;
int error, i;
- if ((error = mb_get_uint8(mbp, &revision)) != 0)
+ if ((error = md_get_uint8(mdp, &revision)) != 0)
return (error);
- if ((error = mb_get_uint8(mbp, &subauthcount)) != 0)
+ if ((error = md_get_uint8(mdp, &subauthcount)) != 0)
return (error);
sidsz = I_SID_SIZE(subauthcount);
@@ -120,11 +115,11 @@ mb_get_sid(mbdata_t *mbp, i_ntsid_t **sidp)
bzero(sid, sidsz);
sid->sid_revision = revision;
sid->sid_subauthcount = subauthcount;
- ERRCHK(mb_get_mem(mbp, (char *)sid->sid_authority, 6));
+ ERRCHK(md_get_mem(mdp, sid->sid_authority, 6, MB_MSYSTEM));
subauthp = &sid->sid_subauthvec[0];
for (i = 0; i < subauthcount; i++) {
- ERRCHK(mb_get_uint32le(mbp, subauthp));
+ ERRCHK(md_get_uint32le(mdp, subauthp));
subauthp++;
}
@@ -138,7 +133,7 @@ errout:
}
static int
-mb_put_sid(mbdata_t *mbp, i_ntsid_t *sid)
+mb_put_sid(mbchain_t *mbp, i_ntsid_t *sid)
{
uint32_t *subauthp;
int error, i;
@@ -148,7 +143,7 @@ mb_put_sid(mbdata_t *mbp, i_ntsid_t *sid)
ERRCHK(mb_put_uint8(mbp, sid->sid_revision));
ERRCHK(mb_put_uint8(mbp, sid->sid_subauthcount));
- ERRCHK(mb_put_mem(mbp, (char *)sid->sid_authority, 6));
+ ERRCHK(mb_put_mem(mbp, sid->sid_authority, 6, MB_MSYSTEM));
subauthp = &sid->sid_subauthvec[0];
for (i = 0; i < sid->sid_subauthcount; i++) {
@@ -179,9 +174,9 @@ ifree_ace(i_ntace_t *ace)
}
static int
-mb_get_ace(mbdata_t *mbp, i_ntace_t **acep)
+md_get_ace(mdchain_t *mdp, i_ntace_t **acep)
{
- mbdata_t tmp_mb;
+ mdchain_t tmp_md;
i_ntace_t *ace = NULL;
uint16_t ace_len;
int error;
@@ -196,22 +191,22 @@ mb_get_ace(mbdata_t *mbp, i_ntace_t **acep)
* XXX: This only decodes types 0-7
*
* There may also be padding after it, so
- * decode the using a copy of the mbdata,
+ * decode the using a copy of the mdchain,
* and then consume the specified length.
*/
- tmp_mb = *mbp;
+ tmp_md = *mdp;
/* Fixed-size header */
- ERRCHK(mb_get_uint8(&tmp_mb, &ace->ace_type));
- ERRCHK(mb_get_uint8(&tmp_mb, &ace->ace_flags));
- ERRCHK(mb_get_uint16le(&tmp_mb, &ace_len));
+ ERRCHK(md_get_uint8(&tmp_md, &ace->ace_type));
+ ERRCHK(md_get_uint8(&tmp_md, &ace->ace_flags));
+ ERRCHK(md_get_uint16le(&tmp_md, &ace_len));
/* Variable-size body */
- ERRCHK(mb_get_uint32le(&tmp_mb, &ace->ace_rights));
- ERRCHK(mb_get_sid(&tmp_mb, &ace->ace_sid));
+ ERRCHK(md_get_uint32le(&tmp_md, &ace->ace_rights));
+ ERRCHK(md_get_sid(&tmp_md, &ace->ace_sid));
/* Now actually consume ace_len */
- ERRCHK(mb_get_mem(mbp, NULL, ace_len));
+ ERRCHK(md_get_mem(mdp, NULL, ace_len, MB_MSYSTEM));
/* Success! */
*acep = ace;
@@ -223,7 +218,7 @@ errout:
}
static int
-mb_put_ace(mbdata_t *mbp, i_ntace_t *ace)
+mb_put_ace(mbchain_t *mbp, i_ntace_t *ace)
{
int cnt0, error;
uint16_t ace_len, *ace_len_p;
@@ -235,7 +230,11 @@ mb_put_ace(mbdata_t *mbp, i_ntace_t *ace)
ERRCHK(mb_put_uint8(mbp, ace->ace_type));
ERRCHK(mb_put_uint8(mbp, ace->ace_flags));
- ERRCHK(mb_fit(mbp, 2, (char **)&ace_len_p));
+ ace_len_p = mb_reserve(mbp, sizeof (*ace_len_p));
+ if (ace_len_p == NULL) {
+ error = ENOMEM;
+ goto errout;
+ }
ERRCHK(mb_put_uint32le(mbp, ace->ace_rights));
ERRCHK(mb_put_sid(mbp, ace->ace_sid));
@@ -278,7 +277,7 @@ ifree_acl(i_ntacl_t *acl)
}
static int
-mb_get_acl(mbdata_t *mbp, i_ntacl_t **aclp)
+md_get_acl(mdchain_t *mdp, i_ntacl_t **aclp)
{
i_ntacl_t *acl = NULL;
i_ntace_t **acep;
@@ -287,15 +286,15 @@ mb_get_acl(mbdata_t *mbp, i_ntacl_t **aclp)
size_t aclsz;
int i, error;
- if ((error = mb_get_uint8(mbp, &revision)) != 0)
+ if ((error = md_get_uint8(mdp, &revision)) != 0)
return (error);
- if ((error = mb_get_uint8(mbp, NULL)) != 0)
+ if ((error = md_get_uint8(mdp, NULL)) != 0)
return (error);
- if ((error = mb_get_uint16le(mbp, &acl_len)) != 0)
+ if ((error = md_get_uint16le(mdp, &acl_len)) != 0)
return (error);
- if ((error = mb_get_uint16le(mbp, &acecount)) != 0)
+ if ((error = md_get_uint16le(mdp, &acecount)) != 0)
return (error);
- if ((error = mb_get_uint16(mbp, NULL)) != 0)
+ if ((error = md_get_uint16le(mdp, NULL)) != 0)
return (error);
aclsz = I_ACL_SIZE(acecount);
@@ -307,7 +306,7 @@ mb_get_acl(mbdata_t *mbp, i_ntacl_t **aclp)
acep = &acl->acl_acevec[0];
for (i = 0; i < acl->acl_acecount; i++) {
- ERRCHK(mb_get_ace(mbp, acep));
+ ERRCHK(md_get_ace(mdp, acep));
acep++;
}
/*
@@ -325,7 +324,7 @@ errout:
}
static int
-mb_put_acl(mbdata_t *mbp, i_ntacl_t *acl)
+mb_put_acl(mbchain_t *mbp, i_ntacl_t *acl)
{
i_ntace_t **acep;
uint16_t acl_len, *acl_len_p;
@@ -335,7 +334,11 @@ mb_put_acl(mbdata_t *mbp, i_ntacl_t *acl)
ERRCHK(mb_put_uint8(mbp, acl->acl_revision));
ERRCHK(mb_put_uint8(mbp, 0)); /* pad1 */
- ERRCHK(mb_fit(mbp, 2, (char **)&acl_len_p));
+ acl_len_p = mb_reserve(mbp, sizeof (*acl_len_p));
+ if (acl_len_p == NULL) {
+ error = ENOMEM;
+ goto errout;
+ }
ERRCHK(mb_put_uint16le(mbp, acl->acl_acecount));
ERRCHK(mb_put_uint16le(mbp, 0)); /* pad2 */
@@ -380,14 +383,14 @@ smbfs_acl_free_sd(i_ntsd_t *sd)
* (like "absolute" form per. NT docs)
* Returns allocated data in sdp
*
- * Note: does NOT consume all the mbp data, so the
+ * Note: does NOT consume all the mdp data, so the
* caller has to take care of that if necessary.
*/
int
-mb_get_ntsd(mbdata_t *mbp, i_ntsd_t **sdp)
+md_get_ntsd(mdchain_t *mdp, i_ntsd_t **sdp)
{
i_ntsd_t *sd = NULL;
- mbdata_t top_mb, tmp_mb;
+ mdchain_t top_md, tmp_md;
uint32_t owneroff, groupoff, sacloff, dacloff;
int error;
@@ -397,44 +400,44 @@ mb_get_ntsd(mbdata_t *mbp, i_ntsd_t **sdp)
/*
* Offsets below are relative to this point,
- * so save the mbp state for use below.
+ * so save the mdp state for use below.
*/
- top_mb = *mbp;
+ top_md = *mdp;
- ERRCHK(mb_get_uint8(mbp, &sd->sd_revision));
- ERRCHK(mb_get_uint8(mbp, NULL));
- ERRCHK(mb_get_uint16le(mbp, &sd->sd_flags));
- ERRCHK(mb_get_uint32le(mbp, &owneroff));
- ERRCHK(mb_get_uint32le(mbp, &groupoff));
- ERRCHK(mb_get_uint32le(mbp, &sacloff));
- ERRCHK(mb_get_uint32le(mbp, &dacloff));
+ ERRCHK(md_get_uint8(mdp, &sd->sd_revision));
+ ERRCHK(md_get_uint8(mdp, &sd->sd_rmctl));
+ ERRCHK(md_get_uint16le(mdp, &sd->sd_flags));
+ ERRCHK(md_get_uint32le(mdp, &owneroff));
+ ERRCHK(md_get_uint32le(mdp, &groupoff));
+ ERRCHK(md_get_uint32le(mdp, &sacloff));
+ ERRCHK(md_get_uint32le(mdp, &dacloff));
/*
* For each section make a temporary copy of the
- * top_mb state, advance to the given offset, and
- * pass that to the lower mb_get_xxx functions.
+ * top_md state, advance to the given offset, and
+ * pass that to the lower md_get_xxx functions.
* These could be marshalled in any order, but
* are normally found in the order shown here.
*/
if (sacloff) {
- tmp_mb = top_mb;
- mb_get_mem(&tmp_mb, NULL, sacloff);
- ERRCHK(mb_get_acl(&tmp_mb, &sd->sd_sacl));
+ tmp_md = top_md;
+ md_get_mem(&tmp_md, NULL, sacloff, MB_MSYSTEM);
+ ERRCHK(md_get_acl(&tmp_md, &sd->sd_sacl));
}
if (dacloff) {
- tmp_mb = top_mb;
- mb_get_mem(&tmp_mb, NULL, dacloff);
- ERRCHK(mb_get_acl(&tmp_mb, &sd->sd_dacl));
+ tmp_md = top_md;
+ md_get_mem(&tmp_md, NULL, dacloff, MB_MSYSTEM);
+ ERRCHK(md_get_acl(&tmp_md, &sd->sd_dacl));
}
if (owneroff) {
- tmp_mb = top_mb;
- mb_get_mem(&tmp_mb, NULL, owneroff);
- ERRCHK(mb_get_sid(&tmp_mb, &sd->sd_owner));
+ tmp_md = top_md;
+ md_get_mem(&tmp_md, NULL, owneroff, MB_MSYSTEM);
+ ERRCHK(md_get_sid(&tmp_md, &sd->sd_owner));
}
if (groupoff) {
- tmp_mb = top_mb;
- mb_get_mem(&tmp_mb, NULL, groupoff);
- ERRCHK(mb_get_sid(&tmp_mb, &sd->sd_group));
+ tmp_md = top_md;
+ md_get_mem(&tmp_md, NULL, groupoff, MB_MSYSTEM);
+ ERRCHK(md_get_sid(&tmp_md, &sd->sd_group));
}
/* Success! */
@@ -452,7 +455,7 @@ errout:
* Returns allocated mbchain in mbp.
*/
int
-mb_put_ntsd(mbdata_t *mbp, i_ntsd_t *sd)
+mb_put_ntsd(mbchain_t *mbp, i_ntsd_t *sd)
{
uint32_t *owneroffp, *groupoffp, *sacloffp, *dacloffp;
uint32_t owneroff, groupoff, sacloff, dacloff;
@@ -462,12 +465,18 @@ mb_put_ntsd(mbdata_t *mbp, i_ntsd_t *sd)
owneroff = groupoff = sacloff = dacloff = 0;
ERRCHK(mb_put_uint8(mbp, sd->sd_revision));
- ERRCHK(mb_put_uint8(mbp, 0)); /* pad1 */
+ ERRCHK(mb_put_uint8(mbp, sd->sd_rmctl));
ERRCHK(mb_put_uint16le(mbp, sd->sd_flags));
- ERRCHK(mb_fit(mbp, 4, (char **)&owneroffp));
- ERRCHK(mb_fit(mbp, 4, (char **)&groupoffp));
- ERRCHK(mb_fit(mbp, 4, (char **)&sacloffp));
- ERRCHK(mb_fit(mbp, 4, (char **)&dacloffp));
+
+ owneroffp = mb_reserve(mbp, sizeof (*owneroffp));
+ groupoffp = mb_reserve(mbp, sizeof (*groupoffp));
+ sacloffp = mb_reserve(mbp, sizeof (*sacloffp));
+ dacloffp = mb_reserve(mbp, sizeof (*dacloffp));
+ if (owneroffp == NULL || groupoffp == NULL ||
+ sacloffp == NULL || dacloffp == NULL) {
+ error = ENOMEM;
+ goto errout;
+ }
/*
* These could be marshalled in any order, but
@@ -535,7 +544,7 @@ smbfs_sid2str(i_ntsid_t *sid,
for (i = 0; i < 6; i++)
auth = (auth << 8) | sid->sid_authority[i];
- n = snprintf(s, osz, "-%llu", auth);
+ n = snprintf(s, osz, "-%llu", (u_longlong_t)auth);
if (n > osz)
return (-1);
s += n; osz -= n;
@@ -556,19 +565,29 @@ smbfs_sid2str(i_ntsid_t *sid,
if (ridp)
*ridp = *ip;
+ /* LINTED E_PTRDIFF_OVERFLOW */
return (s - obuf);
}
/*
* Our interface to the idmap service.
+ *
+ * The idmap API is _almost_ the same between
+ * kernel and user-level. But not quite...
+ * Hope this improves readability below.
*/
-
#ifdef _KERNEL
-#define I_GetPidBySid kidmap_batch_getpidbysid
+
+#define I_GetPidBySid(GH, SPP, RID, PIDP, ISUP, SP) \
+ kidmap_batch_getpidbysid(GH, SPP, RID, PIDP, ISUP, SP)
#define I_GetMappings kidmap_get_mappings
+
#else /* _KERNEL */
-#define I_GetPidBySid idmap_get_pidbysid
+
+#define I_GetPidBySid(GH, SPP, RID, PIDP, ISUP, SP) \
+ idmap_get_pidbysid(GH, SPP, RID, 0, PIDP, ISUP, SP)
#define I_GetMappings idmap_get_mappings
+
#endif /* _KERNEL */
struct mapinfo {
@@ -615,7 +634,7 @@ mkrq_idmap_sid2ux(
return (0);
}
- idms = I_GetPidBySid(idmap_gh, sid_prefix, rid, 0,
+ idms = I_GetPidBySid(idmap_gh, sid_prefix, rid,
&mip->mi_uid, &mip->mi_isuser, &mip->mi_status);
if (idms != IDMAP_SUCCESS)
return (EINVAL);
@@ -824,9 +843,6 @@ smbfs_acl_sd2zfs(
idms = I_GetMappings(idmap_gh);
if (idms != IDMAP_SUCCESS) {
-#ifdef DEBUG
- printf("idmap_get_mappings: rc=%d\n", idms);
-#endif
/* creative error choice */
error = EIDRM;
goto errout;
diff --git a/usr/src/lib/libsmbfs/smb/acl_nt.h b/usr/src/common/smbclnt/smbfs_ntacl.h
index 844a7e6543..cf6788f491 100644
--- a/usr/src/lib/libsmbfs/smb/acl_nt.h
+++ b/usr/src/common/smbclnt/smbfs_ntacl.h
@@ -24,15 +24,15 @@
* Use is subject to license terms.
*/
-#ifndef _ACL_NT_H
-#define _ACL_NT_H
+#ifndef _SMBFS_NTACL_H
+#define _SMBFS_NTACL_H
/*
* Internal functions for dealing with
* NT Security data structures.
*/
-#include <netsmb/smbfs_acl.h>
+#include <netsmb/mchain.h>
/*
* Internal form of an NT SID
@@ -68,46 +68,60 @@ typedef struct i_ntacl {
/*
* Internal form of an NT Security Descriptor (SD)
*/
-struct i_ntsd {
+typedef struct i_ntsd {
uint8_t sd_revision; /* 0x01 observed between W2K */
+ uint8_t sd_rmctl; /* resource mgr control (MBZ) */
uint16_t sd_flags;
i_ntsid_t *sd_owner;
i_ntsid_t *sd_group;
i_ntacl_t *sd_sacl;
i_ntacl_t *sd_dacl;
-};
-
-struct mbdata;
+} i_ntsd_t;
/*
* Import a raw SD (mb chain) into "internal" form.
* (like "absolute" form per. NT docs)
* Returns allocated data in sdp
*/
-int mb_get_ntsd(struct mbdata *mbp, i_ntsd_t **sdp);
+int md_get_ntsd(mdchain_t *mbp, i_ntsd_t **sdp);
/*
* Export an "internal" SD into an raw SD (mb chain).
* (a.k.a "self-relative" form per. NT docs)
* Returns allocated mbchain in mbp.
*/
-int mb_put_ntsd(struct mbdata *mbp, i_ntsd_t *sd);
-
+int mb_put_ntsd(mbchain_t *mbp, i_ntsd_t *sd);
/*
- * Get an SD via ioctl on FD (with "selector" bits),
- * stroing the raw Windows SD in the mb chain mbp.
+ * Convert an internal SD to a ZFS-style ACL.
+ * Get uid/gid too if pointers != NULL.
*/
-int smbfs_acl_iocget(int fd, uint32_t selector, struct mbdata *mbp);
+#ifdef _KERNEL
+int smbfs_acl_sd2zfs(i_ntsd_t *, vsecattr_t *, uid_t *, gid_t *);
+#else /* _KERNEL */
+int smbfs_acl_sd2zfs(i_ntsd_t *, acl_t *, uid_t *, gid_t *);
+#endif /* _KERNEL */
/*
- * Set an SD via ioctl on FD (with "selector" bits),
- * with a raw Windows SD from the chain mbp.
+ * Convert an internal SD to a ZFS-style ACL.
+ * Include owner/group too if uid/gid != -1.
*/
-int smbfs_acl_iocset(int fd, uint32_t selector, struct mbdata *mbp);
+#ifdef _KERNEL
+int smbfs_acl_zfs2sd(vsecattr_t *, uid_t, gid_t, i_ntsd_t **);
+#else /* _KERNEL */
+int smbfs_acl_zfs2sd(acl_t *, uid_t, gid_t, i_ntsd_t **);
+#endif /* _KERNEL */
+/*
+ * Free an i_ntsd_t, as returned by md_get_ntsd()
+ * or smbfs_acl_zfs2sd().
+ */
+void smbfs_acl_free_sd(struct i_ntsd *);
+/*
+ * Convert an NT SID to string format.
+ */
int smbfs_sid2str(i_ntsid_t *sid,
char *obuf, size_t olen, uint32_t *ridp);
-#endif /* _ACL_NT_H */
+#endif /* _SMBFS_NTACL_H */
diff --git a/usr/src/lib/libsmbfs/Makefile.com b/usr/src/lib/libsmbfs/Makefile.com
index 656ba731b3..f7a6c06790 100644
--- a/usr/src/lib/libsmbfs/Makefile.com
+++ b/usr/src/lib/libsmbfs/Makefile.com
@@ -33,9 +33,8 @@ VERS= .1
# leaving out: kiconv.o
-OBJECTS=\
+OBJ_LIB=\
acl_api.o \
- acl_conv.o \
acl_print.o \
charsets.o \
cfopt.o \
@@ -75,13 +74,19 @@ OBJECTS=\
ui-sun.o \
utf_str.o
+OBJ_CMN= smbfs_ntacl.o
+
+OBJECTS= $(OBJ_LIB) $(OBJ_CMN)
+
include $(SRC)/lib/Makefile.lib
LIBS = $(DYNLIB) $(LINTLIB)
SRCDIR= ../smb
+CMNDIR= $(SRC)/common/smbclnt
-SRCS= $(OBJECTS:%.o=../smb/%.c)
+SRCS= $(OBJ_LIB:%.o=$(SRCDIR)/%.c) \
+ $(OBJ_CMN:%.o=$(CMNDIR)/%.c)
$(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC)
@@ -93,7 +98,9 @@ LDLIBS += -lsocket -lnsl -lc -lmd -lpkcs11 -lkrb5 -lsec -lidmap
CFLAGS += $(CCVERBOSE)
CPPFLAGS += -D__EXTENSIONS__ -D_REENTRANT -DMIA \
- -I$(SRCDIR) -I.. -I$(SRC)/uts/common
+ -I$(SRCDIR) -I.. \
+ -I$(SRC)/uts/common \
+ -I$(SRC)/common/smbclnt
# Debugging
${NOT_RELEASE_BUILD} CPPFLAGS += -DDEBUG
@@ -104,15 +111,22 @@ ${NOT_RELEASE_BUILD} CPPFLAGS += -DDEBUG
#CTFCONVERT_O=
#CTFMERGE_LIB=
-# disable some of the less important lint
-LINTCHECKFLAGS += -erroff=E_FUNC_RET_ALWAYS_IGNOR2
-LINTCHECKFLAGS += -erroff=E_FUNC_RET_MAYBE_IGNORED2
-LINTCHECKFLAGS += -DDEBUG
+# Filter out the less important lint.
+# See lgrep.awk
+LGREP = nawk -f $(SRCDIR)/lgrep.awk
+LTAIL += 2>&1 | $(LGREP)
all: $(LIBS)
-lint: lintcheck
+lint: lintcheck_t
include ../../Makefile.targ
+lintcheck_t: $$(SRCS)
+ $(LINT.c) $(LINTCHECKFLAGS) $(SRCS) $(LDLIBS) $(LTAIL)
+
+objs/%.o pics/%.o: $(CMNDIR)/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
+
.KEEP_STATE:
diff --git a/usr/src/lib/libsmbfs/netsmb/smbfs_acl.h b/usr/src/lib/libsmbfs/netsmb/smbfs_acl.h
index d1da5bda22..b8cf6a8036 100644
--- a/usr/src/lib/libsmbfs/netsmb/smbfs_acl.h
+++ b/usr/src/lib/libsmbfs/netsmb/smbfs_acl.h
@@ -61,37 +61,26 @@ int smbfs_acl_set(int fd, acl_t *, uid_t, gid_t);
/*
* Slightly lower-level functions, allowing access to
* the raw Windows Security Descriptor (SD)
+ *
+ * The struct i_ntsid is opaque in this I/F.
+ * Real decl. in: common/smbclnt/smbfs_ntacl.h
*/
-typedef struct i_ntsd i_ntsd_t;
+struct i_ntsd;
/*
* Get an "internal form" SD from the FD (opened in smbfs).
* Allocates a hierarchy in isdp. Caller must free it via
* smbfs_acl_free_isd()
*/
-int smbfs_acl_getsd(int fd, uint32_t, i_ntsd_t **);
+int smbfs_acl_getsd(int fd, uint32_t, struct i_ntsd **);
/*
* Set an "internal form" SD onto the FD (opened in smbfs).
*/
-int smbfs_acl_setsd(int fd, uint32_t, i_ntsd_t *);
-
-/*
- * Convert an internal SD to a ZFS-style ACL.
- * Get uid/gid too if pointers != NULL.
- */
-int smbfs_acl_sd2zfs(i_ntsd_t *, acl_t *, uid_t *, gid_t *);
-
-/*
- * Convert an internal SD to a ZFS-style ACL.
- * Include owner/group too if uid/gid != -1.
- */
-int smbfs_acl_zfs2sd(acl_t *, uid_t, gid_t, i_ntsd_t **);
-
-void smbfs_acl_free_sd(i_ntsd_t *);
+int smbfs_acl_setsd(int fd, uint32_t, struct i_ntsd *);
struct __FILE;
-void smbfs_acl_print_sd(struct __FILE *, i_ntsd_t *);
+void smbfs_acl_print_sd(struct __FILE *, struct i_ntsd *);
#ifdef __cplusplus
}
diff --git a/usr/src/lib/libsmbfs/smb/acl_api.c b/usr/src/lib/libsmbfs/smb/acl_api.c
index 3e9d703c99..b5b6123063 100644
--- a/usr/src/lib/libsmbfs/smb/acl_api.c
+++ b/usr/src/lib/libsmbfs/smb/acl_api.c
@@ -53,7 +53,7 @@
#include <netsmb/smb_lib.h>
#include <netsmb/smbfs_acl.h>
-#include "acl_nt.h"
+#include "smbfs_ntacl.h"
#include "private.h"
/* Sanity check SD sizes */
@@ -78,7 +78,7 @@ smbfs_acl_iocget(int fd, uint32_t selector, mbdata_t *mbp)
struct mbuf *m;
int error;
- error = mb_init(mbp, MAX_RAW_SD_SIZE);
+ error = mb_init_sz(mbp, MAX_RAW_SD_SIZE);
if (error)
return (error);
@@ -157,7 +157,7 @@ smbfs_acl_getsd(int fd, uint32_t selector, i_ntsd_t **sdp)
* (like "absolute" form per. NT docs)
* Returns allocated data in sdp
*/
- error = mb_get_ntsd(mbp, sdp);
+ error = md_get_ntsd(mbp, sdp);
}
mb_done(mbp);
@@ -174,7 +174,9 @@ smbfs_acl_setsd(int fd, uint32_t selector, i_ntsd_t *sd)
int error;
mbp = &mb_store;
- mb_init(mbp, M_MINSIZE);
+ error = mb_init_sz(mbp, MAX_RAW_SD_SIZE);
+ if (error)
+ return (error);
/*
* Export the "internal" SD into an mb chain.
diff --git a/usr/src/lib/libsmbfs/smb/acl_print.c b/usr/src/lib/libsmbfs/smb/acl_print.c
index 259258a9f1..6d399e32aa 100644
--- a/usr/src/lib/libsmbfs/smb/acl_print.c
+++ b/usr/src/lib/libsmbfs/smb/acl_print.c
@@ -53,7 +53,7 @@
#include <netsmb/smb_lib.h>
#include <netsmb/smbfs_acl.h>
-#include "acl_nt.h"
+#include "smbfs_ntacl.h"
static void
fprint_sid(FILE *fp, i_ntsid_t *sid)
diff --git a/usr/src/lib/libsmbfs/smb/ctx.c b/usr/src/lib/libsmbfs/smb/ctx.c
index 04057ac334..40a62a3853 100644
--- a/usr/src/lib/libsmbfs/smb/ctx.c
+++ b/usr/src/lib/libsmbfs/smb/ctx.c
@@ -253,22 +253,30 @@ smb_ctx_init(struct smb_ctx *ctx)
ctx->ct_authflags = SMB_AT_DEFAULT;
ctx->ct_minauth = SMB_AT_DEFAULT;
- nb_ctx_setscope(ctx->ct_nb, "");
+ error = nb_ctx_setscope(ctx->ct_nb, "");
+ if (error)
+ return (error);
/*
* if the user name is not specified some other way,
* use the current user name (built-in default)
*/
if (getpwuid_r(getuid(), &pw, pwbuf, sizeof (pwbuf)) != NULL) {
- smb_ctx_setuser(ctx, pw.pw_name, 0);
+ error = smb_ctx_setuser(ctx, pw.pw_name, 0);
+ if (error)
+ return (error);
ctx->ct_home = strdup(pw.pw_name);
+ if (ctx->ct_home == NULL)
+ return (ENOMEM);
}
/*
* Set a built-in default domain (workgroup).
* Using the Windows/NT default for now.
*/
- smb_ctx_setdomain(ctx, "WORKGROUP", 0);
+ error = smb_ctx_setdomain(ctx, "WORKGROUP", 0);
+ if (error)
+ return (error);
return (error);
}
@@ -571,7 +579,7 @@ smb_ctx_parseunc(struct smb_ctx *ctx, const char *unc,
*/
if (strchr(tmp, '%'))
(void) unpercent(tmp);
- smb_ctx_setfullserver(ctx, tmp);
+ error = smb_ctx_setfullserver(ctx, tmp);
if (error)
goto out;
@@ -771,7 +779,7 @@ smb_ctx_setpassword(struct smb_ctx *ctx, const char *passwd, int from_cmd)
memset(ctx->ct_password, 0, sizeof (ctx->ct_password));
if (strncmp(passwd, "$$1", 3) == 0)
- smb_simpledecrypt(ctx->ct_password, passwd);
+ (void) smb_simpledecrypt(ctx->ct_password, passwd);
else
strlcpy(ctx->ct_password, passwd,
sizeof (ctx->ct_password));
@@ -1387,14 +1395,15 @@ smb_ctx_readrcsection(struct smb_ctx *ctx, const char *sname, int level)
if (p) {
/*
* "signing" was set in this section; override
- * the current signing settings.
+ * the current signing settings. Note:
+ * setsigning flags are: enable, require
*/
if (strcmp(p, "disabled") == 0) {
- smb_ctx_setsigning(ctx, FALSE, FALSE);
+ (void) smb_ctx_setsigning(ctx, FALSE, FALSE);
} else if (strcmp(p, "enabled") == 0) {
- smb_ctx_setsigning(ctx, TRUE, FALSE);
+ (void) smb_ctx_setsigning(ctx, TRUE, FALSE);
} else if (strcmp(p, "required") == 0) {
- smb_ctx_setsigning(ctx, TRUE, TRUE);
+ (void) smb_ctx_setsigning(ctx, TRUE, TRUE);
} else {
/*
* Unknown "signing" value.
diff --git a/usr/src/lib/libsmbfs/smb/file.c b/usr/src/lib/libsmbfs/smb/file.c
index 74630fdd91..3c8184e8a1 100644
--- a/usr/src/lib/libsmbfs/smb/file.c
+++ b/usr/src/lib/libsmbfs/smb/file.c
@@ -114,7 +114,7 @@ smb_fh_ntcreate(
mb_put_uint16le(mbp, 0xff); /* secondary command */
mb_put_uint16le(mbp, 0); /* offset to next command (none) */
mb_put_uint8(mbp, 0); /* MBZ (pad?) */
- mb_fit(mbp, 2, &pathsizep); /* path size - fill in below */
+ (void) mb_fit(mbp, 2, &pathsizep); /* path size - fill in below */
mb_put_uint32le(mbp, flags); /* create flags (oplock) */
mb_put_uint32le(mbp, 0); /* FID - basis for path if not root */
mb_put_uint32le(mbp, req_acc);
@@ -138,7 +138,7 @@ smb_fh_ntcreate(
mb_put_uint8(mbp, 0);
}
pathstart = mbp->mb_count;
- mb_put_dstring(mbp, path, uc);
+ mb_put_string(mbp, path, uc);
smb_rq_bend(rqp);
/* Now go back and fill in pathsizep */
@@ -155,30 +155,30 @@ smb_fh_ntcreate(
* spec says 26 for word count, but 34 words are defined
* and observed from win2000
*/
- error = mb_get_uint8(mbp, &wc);
+ error = md_get_uint8(mbp, &wc);
if (error || wc < 26) {
smb_error(dgettext(TEXT_DOMAIN,
"%s: open failed, bad word count"), 0, path);
error = EBADRPC;
goto out;
}
- mb_get_uint8(mbp, NULL); /* secondary cmd */
- mb_get_uint8(mbp, NULL); /* mbz */
- mb_get_uint16le(mbp, NULL); /* andxoffset */
- mb_get_uint8(mbp, NULL); /* oplock lvl granted */
- mb_get_uint16le(mbp, &fh); /* FID */
- mb_get_uint32le(mbp, action_taken);
+ md_get_uint8(mbp, NULL); /* secondary cmd */
+ md_get_uint8(mbp, NULL); /* mbz */
+ md_get_uint16le(mbp, NULL); /* andxoffset */
+ md_get_uint8(mbp, NULL); /* oplock lvl granted */
+ md_get_uint16le(mbp, &fh); /* FID */
+ md_get_uint32le(mbp, action_taken);
#if 0 /* skip decoding the rest */
- mb_get_uint64le(mbp, NULL); /* creation time */
- mb_get_uint64le(mbp, NULL); /* access time */
- mb_get_uint64le(mbp, NULL); /* write time */
- mb_get_uint64le(mbp, NULL); /* change time */
- mb_get_uint32le(mbp, NULL); /* attributes */
- mb_get_uint64le(mbp, NULL); /* allocation size */
- mb_get_uint64le(mbp, NULL); /* EOF */
- mb_get_uint16le(mbp, NULL); /* file type */
- mb_get_uint16le(mbp, NULL); /* device state */
- mb_get_uint8(mbp, NULL); /* directory (boolean) */
+ md_get_uint64le(mbp, NULL); /* creation time */
+ md_get_uint64le(mbp, NULL); /* access time */
+ md_get_uint64le(mbp, NULL); /* write time */
+ md_get_uint64le(mbp, NULL); /* change time */
+ md_get_uint32le(mbp, NULL); /* attributes */
+ md_get_uint64le(mbp, NULL); /* allocation size */
+ md_get_uint64le(mbp, NULL); /* EOF */
+ md_get_uint16le(mbp, NULL); /* file type */
+ md_get_uint16le(mbp, NULL); /* device state */
+ md_get_uint8(mbp, NULL); /* directory (boolean) */
#endif
/* success! */
diff --git a/usr/src/lib/libsmbfs/smb/iod_cl.c b/usr/src/lib/libsmbfs/smb/iod_cl.c
index 074b2ad848..7449d68ed5 100644
--- a/usr/src/lib/libsmbfs/smb/iod_cl.c
+++ b/usr/src/lib/libsmbfs/smb/iod_cl.c
@@ -151,7 +151,7 @@ smb_iod_start(smb_ctx_t *ctx)
char *argv[2];
argv[0] = "smbiod";
argv[1] = NULL;
- execv(smbiod_path, argv);
+ (void) execv(smbiod_path, argv);
_exit(1);
}
@@ -160,7 +160,7 @@ smb_iod_start(smb_ctx_t *ctx)
*/
tmo = iod_start_timeout;
while (--tmo >= 0) {
- sleep(1);
+ (void) sleep(1);
err = smb_iod_open_door(&fd);
if (err == 0)
goto OK;
diff --git a/usr/src/lib/libsmbfs/smb/keychain.c b/usr/src/lib/libsmbfs/smb/keychain.c
index da19fd4d0b..c5cf319c21 100644
--- a/usr/src/lib/libsmbfs/smb/keychain.c
+++ b/usr/src/lib/libsmbfs/smb/keychain.c
@@ -290,8 +290,11 @@ smbfs_default_dom_usr(const char *home, const char *server,
if (err)
return (err);
- if (server)
- smb_ctx_setfullserver(ctx, server);
+ if (server) {
+ err = smb_ctx_setfullserver(ctx, server);
+ if (err != 0)
+ goto out;
+ }
if (home && *home) {
if (ctx->ct_home)
diff --git a/usr/src/lib/libsmbfs/smb/krb5ssp.c b/usr/src/lib/libsmbfs/smb/krb5ssp.c
index fbbd08398b..d473c07c79 100644
--- a/usr/src/lib/libsmbfs/smb/krb5ssp.c
+++ b/usr/src/lib/libsmbfs/smb/krb5ssp.c
@@ -236,9 +236,9 @@ krb5ssp_put_request(struct ssp_ctx *sp, struct mbdata *out_mb)
if ((err = krb5ssp_tkt2gtok(tkt, tktlen, &gtok, &gtoklen)) != 0)
goto out;
- if ((err = mb_init(out_mb, gtoklen)) != 0)
+ if ((err = mb_init_sz(out_mb, gtoklen)) != 0)
goto out;
- if ((err = mb_put_mem(out_mb, gtok, gtoklen)) != 0)
+ if ((err = mb_put_mem(out_mb, gtok, gtoklen, MB_MSYSTEM)) != 0)
goto out;
if (ctx->ct_vcflags & SMBV_WILL_SIGN)
diff --git a/usr/src/lib/libsmbfs/smb/lgrep.awk b/usr/src/lib/libsmbfs/smb/lgrep.awk
new file mode 100644
index 0000000000..8f36708df8
--- /dev/null
+++ b/usr/src/lib/libsmbfs/smb/lgrep.awk
@@ -0,0 +1,54 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+# This is a "lint tail" that removes all the
+# uninteresting lines from our lint output.
+# It's nawk because sed doesn't do (a|b).
+# Also comments are easier here.
+
+# The mb_put/md_get functions are intentionally used both
+# with and without return value checks. Not a concern.
+/: mb_put_.* .E_FUNC_RET_[A-Z]*_IGNOR/ { next; }
+/: md_get_.* .E_FUNC_RET_[A-Z]*_IGNOR/ { next; }
+
+# The rc_get* functions clear the out arg even on failure,
+# so most callers don't need to check the return value.
+/: rc_get[a-z]* .E_FUNC_RET_[A-Z]*_IGNOR/ { next; }
+
+# These have uninteresting return values, usually ignored.
+/: (n|sm)b_ctx_readrcsection .E_FUNC_RET_[A-Z]*_IGNOR/ { next; }
+/: nls_str_(lower|upper) .E_FUNC_RET_[A-Z]*_IGNOR/ { next; }
+/: rc_(close|freesect) .E_FUNC_RET_[A-Z]*_IGNOR/ { next; }
+
+# Other functions for which we often ignore return values.
+/: [a-z]*close .E_FUNC_RET_[A-Z]*_IGNOR/ { next; }
+/: [a-z]*flush .E_FUNC_RET_[A-Z]*_IGNOR/ { next; }
+/: [a-z]*printf .E_FUNC_RET_[A-Z]*_IGNOR/ { next; }
+/: mem(cpy|move|set) .E_FUNC_RET_[A-Z]*_IGNOR/ { next; }
+/: mutex_.* .E_FUNC_RET_[A-Z]*_IGNOR/ { next; }
+/: str[ln]?(cat|cpy) .E_FUNC_RET_[A-Z]*_IGNOR/ { next; }
+
+{ print; }
diff --git a/usr/src/lib/libsmbfs/smb/mbuf.c b/usr/src/lib/libsmbfs/smb/mbuf.c
index 9380ec12e9..86710f3f94 100644
--- a/usr/src/lib/libsmbfs/smb/mbuf.c
+++ b/usr/src/lib/libsmbfs/smb/mbuf.c
@@ -53,8 +53,20 @@
#include "private.h"
#include "charsets.h"
-static int
-m_get(size_t len, struct mbuf **mpp)
+/*
+ * Note: Leaving a little space (8 bytes) between the
+ * mbuf header and the start of the data so we can
+ * prepend a NetBIOS header in that space.
+ */
+#define M_ALIGNFACTOR (sizeof (long))
+#define M_ALIGN(len) (((len) + M_ALIGNFACTOR - 1) & ~(M_ALIGNFACTOR - 1))
+#define M_BASESIZE (sizeof (struct mbuf) + 8)
+#define M_MINSIZE (1024 - M_BASESIZE)
+#define M_TOP(m) ((char *)(m) + M_BASESIZE)
+#define M_TRAILINGSPACE(m) ((m)->m_maxlen - (m)->m_len)
+
+int
+m_get(int len, struct mbuf **mpp)
{
struct mbuf *m;
@@ -132,37 +144,42 @@ m_lineup(struct mbuf *m0, struct mbuf **mpp)
}
int
-mb_init(struct mbdata *mbp, size_t size)
+mb_init(struct mbdata *mbp)
+{
+ return (mb_init_sz(mbp, M_MINSIZE));
+}
+
+int
+mb_init_sz(struct mbdata *mbp, int size)
{
struct mbuf *m;
int error;
if ((error = m_get(size, &m)) != 0)
return (error);
- return (mb_initm(mbp, m));
+ mb_initm(mbp, m);
+ return (0);
}
-int
+void
mb_initm(struct mbdata *mbp, struct mbuf *m)
{
bzero(mbp, sizeof (*mbp));
mbp->mb_top = mbp->mb_cur = m;
mbp->mb_pos = mtod(m, char *);
- return (0);
}
-int
+void
mb_done(struct mbdata *mbp)
{
if (mbp->mb_top) {
m_freem(mbp->mb_top);
mbp->mb_top = NULL;
}
- return (0);
}
int
-m_getm(struct mbuf *top, size_t len, struct mbuf **mpp)
+m_getm(struct mbuf *top, int len, struct mbuf **mpp)
{
struct mbuf *m, *mp;
int error, ts;
@@ -190,13 +207,24 @@ out:
* Routines to put data in a buffer
*/
+void *
+mb_reserve(mbchain_t *mbp, int size)
+{
+ char *p;
+
+ if (mb_fit(mbp, size, &p) != 0)
+ return (NULL);
+
+ return (p);
+}
+
/*
* Check if object of size 'size' fit to the current position and
* allocate new mbuf if not. Advance pointers and increase length of mbuf(s).
* Return pointer to the object placeholder or NULL if any error occured.
*/
int
-mb_fit(struct mbdata *mbp, size_t size, char **pp)
+mb_fit(mbchain_t *mbp, int size, char **pp)
{
struct mbuf *m, *mn;
int error;
@@ -217,56 +245,57 @@ mb_fit(struct mbdata *mbp, size_t size, char **pp)
}
int
-mb_put_uint8(struct mbdata *mbp, uint8_t x)
+mb_put_uint8(mbchain_t *mbp, uint8_t x)
{
uint8_t y = x;
- return (mb_put_mem(mbp, &y, sizeof (y)));
+ return (mb_put_mem(mbp, &y, sizeof (y), MB_MINLINE));
}
int
-mb_put_uint16be(struct mbdata *mbp, uint16_t x)
+mb_put_uint16be(mbchain_t *mbp, uint16_t x)
{
uint16_t y = htobes(x);
- return (mb_put_mem(mbp, &y, sizeof (y)));
+ return (mb_put_mem(mbp, &y, sizeof (y), MB_MINLINE));
}
int
-mb_put_uint16le(struct mbdata *mbp, uint16_t x)
+mb_put_uint16le(mbchain_t *mbp, uint16_t x)
{
uint16_t y = htoles(x);
- return (mb_put_mem(mbp, &y, sizeof (y)));
+ return (mb_put_mem(mbp, &y, sizeof (y), MB_MINLINE));
}
int
-mb_put_uint32be(struct mbdata *mbp, uint32_t x)
+mb_put_uint32be(mbchain_t *mbp, uint32_t x)
{
uint32_t y = htobel(x);
- return (mb_put_mem(mbp, &y, sizeof (y)));
+ return (mb_put_mem(mbp, &y, sizeof (y), MB_MINLINE));
}
int
-mb_put_uint32le(struct mbdata *mbp, uint32_t x)
+mb_put_uint32le(mbchain_t *mbp, uint32_t x)
{
uint32_t y = htolel(x);
- return (mb_put_mem(mbp, &y, sizeof (y)));
+ return (mb_put_mem(mbp, &y, sizeof (y), MB_MINLINE));
}
int
-mb_put_uint64be(struct mbdata *mbp, uint64_t x)
+mb_put_uint64be(mbchain_t *mbp, uint64_t x)
{
uint64_t y = htobeq(x);
- return (mb_put_mem(mbp, &y, sizeof (y)));
+ return (mb_put_mem(mbp, &y, sizeof (y), MB_MINLINE));
}
int
-mb_put_uint64le(struct mbdata *mbp, uint64_t x)
+mb_put_uint64le(mbchain_t *mbp, uint64_t x)
{
uint64_t y = htoleq(x);
- return (mb_put_mem(mbp, &y, sizeof (y)));
+ return (mb_put_mem(mbp, &y, sizeof (y), MB_MINLINE));
}
+/* ARGSUSED */
int
-mb_put_mem(struct mbdata *mbp, const void *vmem, size_t size)
+mb_put_mem(mbchain_t *mbp, const void *vmem, int size, int type)
{
struct mbuf *m;
const char *src;
@@ -311,14 +340,14 @@ mb_put_mem(struct mbdata *mbp, const void *vmem, size_t size)
* This always consumes the passed mbuf.
*/
int
-mb_put_mbuf(struct mbdata *mbp, struct mbuf *m)
+mb_put_mbuf(mbchain_t *mbp, struct mbuf *m)
{
struct mbuf *cm = mbp->mb_cur;
int ts = M_TRAILINGSPACE(cm);
if (m->m_next == NULL && m->m_len <= ts) {
/* just copy */
- mb_put_mem(mbp, m->m_data, m->m_len);
+ mb_put_mem(mbp, m->m_data, m->m_len, MB_MSYSTEM);
m_freem(m);
return (0);
}
@@ -340,7 +369,7 @@ mb_put_mbuf(struct mbdata *mbp, struct mbuf *m)
* null terminated, and aligned if necessary.
*/
int
-mb_put_dstring(struct mbdata *mbp, const char *s, int uc)
+mb_put_string(mbchain_t *mbp, const char *s, int uc)
{
int err;
@@ -361,7 +390,7 @@ mb_put_dstring(struct mbdata *mbp, const char *s, int uc)
* Put an ASCII string (really OEM), given a UTF-8 string.
*/
int
-mb_put_astring(struct mbdata *mbp, const char *s)
+mb_put_astring(mbchain_t *mbp, const char *s)
{
char *abuf;
int err, len;
@@ -370,7 +399,7 @@ mb_put_astring(struct mbdata *mbp, const char *s)
if (abuf == NULL)
return (ENOMEM);
len = strlen(abuf) + 1;
- err = mb_put_mem(mbp, abuf, len);
+ err = mb_put_mem(mbp, abuf, len, MB_MSYSTEM);
free(abuf);
return (err);
}
@@ -379,7 +408,7 @@ mb_put_astring(struct mbdata *mbp, const char *s)
* Put UCS-2LE, given a UTF-8 string.
*/
int
-mb_put_ustring(struct mbdata *mbp, const char *s)
+mb_put_ustring(mbchain_t *mbp, const char *s)
{
uint16_t *ubuf;
int err, len;
@@ -387,8 +416,8 @@ mb_put_ustring(struct mbdata *mbp, const char *s)
ubuf = convert_utf8_to_leunicode(s);
if (ubuf == NULL)
return (ENOMEM);
- len = unicode_strlen(ubuf) + 1;
- err = mb_put_mem(mbp, ubuf, (len << 1));
+ len = 2 * (unicode_strlen(ubuf) + 1);
+ err = mb_put_mem(mbp, ubuf, len, MB_MSYSTEM);
free(ubuf);
return (err);
}
@@ -399,24 +428,18 @@ mb_put_ustring(struct mbdata *mbp, const char *s)
#define mb_left(m, p) (mtod(m, char *) + (m)->m_len - (p))
int
-mb_get_uint8(struct mbdata *mbp, uint8_t *x)
-{
- return (mb_get_mem(mbp, x, 1));
-}
-
-int
-mb_get_uint16(struct mbdata *mbp, uint16_t *x)
+md_get_uint8(mdchain_t *mbp, uint8_t *x)
{
- return (mb_get_mem(mbp, x, 2));
+ return (md_get_mem(mbp, x, 1, MB_MINLINE));
}
int
-mb_get_uint16le(struct mbdata *mbp, uint16_t *x)
+md_get_uint16le(mdchain_t *mbp, uint16_t *x)
{
uint16_t v;
int err;
- if ((err = mb_get_mem(mbp, &v, 2)) != 0)
+ if ((err = md_get_mem(mbp, &v, sizeof (v), MB_MINLINE)) != 0)
return (err);
if (x != NULL)
*x = letohs(v);
@@ -424,11 +447,11 @@ mb_get_uint16le(struct mbdata *mbp, uint16_t *x)
}
int
-mb_get_uint16be(struct mbdata *mbp, uint16_t *x) {
+md_get_uint16be(mdchain_t *mbp, uint16_t *x) {
uint16_t v;
int err;
- if ((err = mb_get_mem(mbp, &v, 2)) != 0)
+ if ((err = md_get_mem(mbp, &v, sizeof (v), MB_MINLINE)) != 0)
return (err);
if (x != NULL)
*x = betohs(v);
@@ -436,18 +459,12 @@ mb_get_uint16be(struct mbdata *mbp, uint16_t *x) {
}
int
-mb_get_uint32(struct mbdata *mbp, uint32_t *x)
-{
- return (mb_get_mem(mbp, x, 4));
-}
-
-int
-mb_get_uint32be(struct mbdata *mbp, uint32_t *x)
+md_get_uint32be(mdchain_t *mbp, uint32_t *x)
{
uint32_t v;
int err;
- if ((err = mb_get_mem(mbp, &v, 4)) != 0)
+ if ((err = md_get_mem(mbp, &v, sizeof (v), MB_MINLINE)) != 0)
return (err);
if (x != NULL)
*x = betohl(v);
@@ -455,12 +472,12 @@ mb_get_uint32be(struct mbdata *mbp, uint32_t *x)
}
int
-mb_get_uint32le(struct mbdata *mbp, uint32_t *x)
+md_get_uint32le(mdchain_t *mbp, uint32_t *x)
{
uint32_t v;
int err;
- if ((err = mb_get_mem(mbp, &v, 4)) != 0)
+ if ((err = md_get_mem(mbp, &v, sizeof (v), MB_MINLINE)) != 0)
return (err);
if (x != NULL)
*x = letohl(v);
@@ -468,18 +485,12 @@ mb_get_uint32le(struct mbdata *mbp, uint32_t *x)
}
int
-mb_get_uint64(struct mbdata *mbp, uint64_t *x)
-{
- return (mb_get_mem(mbp, x, 8));
-}
-
-int
-mb_get_uint64be(struct mbdata *mbp, uint64_t *x)
+md_get_uint64be(mdchain_t *mbp, uint64_t *x)
{
uint64_t v;
int err;
- if ((err = mb_get_mem(mbp, &v, 8)) != 0)
+ if ((err = md_get_mem(mbp, &v, sizeof (v), MB_MINLINE)) != 0)
return (err);
if (x != NULL)
*x = betohq(v);
@@ -487,20 +498,21 @@ mb_get_uint64be(struct mbdata *mbp, uint64_t *x)
}
int
-mb_get_uint64le(struct mbdata *mbp, uint64_t *x)
+md_get_uint64le(mdchain_t *mbp, uint64_t *x)
{
uint64_t v;
int err;
- if ((err = mb_get_mem(mbp, &v, 8)) != 0)
+ if ((err = md_get_mem(mbp, &v, sizeof (v), MB_MINLINE)) != 0)
return (err);
if (x != NULL)
*x = letohq(v);
return (0);
}
+/* ARGSUSED */
int
-mb_get_mem(struct mbdata *mbp, void *vmem, size_t size)
+md_get_mem(mdchain_t *mbp, void *vmem, int size, int type)
{
struct mbuf *m = mbp->mb_cur;
char *dst = vmem;
@@ -539,7 +551,7 @@ mb_get_mem(struct mbdata *mbp, void *vmem, size_t size)
* Nothing fancy here - just copy.
*/
int
-mb_get_mbuf(struct mbdata *mbp, int size, struct mbuf **ret)
+md_get_mbuf(mdchain_t *mbp, int size, mbuf_t **ret)
{
mbuf_t *m;
int err;
@@ -548,7 +560,7 @@ mb_get_mbuf(struct mbdata *mbp, int size, struct mbuf **ret)
if (err)
return (err);
- err = mb_get_mem(mbp, m->m_data, size);
+ err = md_get_mem(mbp, m->m_data, size, MB_MSYSTEM);
if (err) {
m_freem(m);
return (err);
@@ -564,26 +576,27 @@ mb_get_mbuf(struct mbdata *mbp, int size, struct mbuf **ret)
* either Unicode or OEM chars.
*/
int
-mb_get_string(struct mbdata *mbp, char **str_pp, int uc)
+md_get_string(mdchain_t *mbp, char **str_pp, int uc)
{
int err;
if (uc)
- err = mb_get_ustring(mbp, str_pp);
+ err = md_get_ustring(mbp, str_pp);
else
- err = mb_get_astring(mbp, str_pp);
+ err = md_get_astring(mbp, str_pp);
return (err);
}
/*
* Get an ASCII (really OEM) string from the mbuf chain
* and convert it to UTF-8
- * Similar to mb_get_ustring below.
+ *
+ * Similar to md_get_ustring below.
*/
int
-mb_get_astring(struct mbdata *real_mbp, char **str_pp)
+md_get_astring(mdchain_t *real_mbp, char **str_pp)
{
- struct mbdata tmp_mb, *mbp;
+ mdchain_t tmp_mb, *mbp;
char *tstr, *ostr;
int err, i, slen;
uint8_t ch;
@@ -598,7 +611,7 @@ mb_get_astring(struct mbdata *real_mbp, char **str_pp)
mbp = &tmp_mb;
slen = 0;
for (;;) {
- err = mb_get_uint8(mbp, &ch);
+ err = md_get_uint8(mbp, &ch);
if (err)
break;
if (ch == 0)
@@ -615,11 +628,11 @@ mb_get_astring(struct mbdata *real_mbp, char **str_pp)
return (ENOMEM);
mbp = real_mbp;
for (i = 0; i < slen; i++) {
- mb_get_uint8(mbp, &ch);
+ md_get_uint8(mbp, &ch);
tstr[i] = ch;
}
tstr[i] = 0;
- mb_get_uint8(mbp, NULL);
+ md_get_uint8(mbp, NULL);
/*
* Convert OEM to UTF-8
@@ -637,12 +650,12 @@ mb_get_astring(struct mbdata *real_mbp, char **str_pp)
* Get a UCS-2LE string from the mbuf chain, and
* convert it to UTF-8.
*
- * Similar to mb_get_astring below.
+ * Similar to md_get_astring above.
*/
int
-mb_get_ustring(struct mbdata *real_mbp, char **str_pp)
+md_get_ustring(mdchain_t *real_mbp, char **str_pp)
{
- struct mbdata tmp_mb, *mbp;
+ mdchain_t tmp_mb, *mbp;
uint16_t *tstr;
char *ostr;
int err, i, slen;
@@ -652,7 +665,7 @@ mb_get_ustring(struct mbdata *real_mbp, char **str_pp)
* First, align(2) on the real_mbp
*/
if (((uintptr_t)real_mbp->mb_pos) & 1)
- mb_get_uint8(real_mbp, NULL);
+ md_get_uint8(real_mbp, NULL);
/*
* Next, figure out the string length.
@@ -664,7 +677,7 @@ mb_get_ustring(struct mbdata *real_mbp, char **str_pp)
mbp = &tmp_mb;
slen = 0;
for (;;) {
- err = mb_get_uint16le(mbp, &ch);
+ err = md_get_uint16le(mbp, &ch);
if (err)
break;
if (ch == 0)
@@ -682,11 +695,11 @@ mb_get_ustring(struct mbdata *real_mbp, char **str_pp)
return (ENOMEM);
mbp = real_mbp;
for (i = 0; i < slen; i++) {
- mb_get_uint16le(mbp, &ch);
+ md_get_uint16le(mbp, &ch);
tstr[i] = ch;
}
tstr[i] = 0;
- mb_get_uint16le(mbp, NULL);
+ md_get_uint16le(mbp, NULL);
/*
* Convert UCS-2 (native!) to UTF-8
diff --git a/usr/src/lib/libsmbfs/smb/nb_name.c b/usr/src/lib/libsmbfs/smb/nb_name.c
index 604d9142cd..812900aca9 100644
--- a/usr/src/lib/libsmbfs/smb/nb_name.c
+++ b/usr/src/lib/libsmbfs/smb/nb_name.c
@@ -206,7 +206,7 @@ nb_name_encode(struct mbdata *mbp, struct nb_name *nn)
return (0);
}
- mb_fit(mbp, 1, &plen);
+ (void) mb_fit(mbp, 1, &plen);
*plen = 0; /* will update below */
lblen = 0;
for (p = nn->nn_scope; ; p++) {
@@ -218,7 +218,7 @@ nb_name_encode(struct mbdata *mbp, struct nb_name *nn)
}
if (*p == '.') {
*plen = lblen;
- mb_fit(mbp, 1, &plen);
+ (void) mb_fit(mbp, 1, &plen);
*plen = 0;
lblen = 0;
} else {
diff --git a/usr/src/lib/libsmbfs/smb/nb_ssn.c b/usr/src/lib/libsmbfs/smb/nb_ssn.c
index bd53ce6fce..44d5a48120 100644
--- a/usr/src/lib/libsmbfs/smb/nb_ssn.c
+++ b/usr/src/lib/libsmbfs/smb/nb_ssn.c
@@ -178,7 +178,7 @@ nb_ssn_recv(struct smb_ctx *ctx, struct mbdata *mb,
/*
* Get a message buffer, read the payload
*/
- if ((err = mb_init(mb, *mlen)) != 0)
+ if ((err = mb_init_sz(mb, *mlen)) != 0)
return (err);
buf = mb->mb_top->m_data;
len = *mlen;
@@ -274,7 +274,7 @@ nb_ssn_request(struct smb_ctx *ctx, char *srvname)
bzero(&req, sizeof (req));
bzero(&res, sizeof (res));
- if ((err = mb_init(&req, M_MINSIZE)) != 0)
+ if ((err = mb_init(&req)) != 0)
goto errout;
ucwks = utf8_str_toupper(ctx->ct_locname);
diff --git a/usr/src/lib/libsmbfs/smb/nbns_rq.c b/usr/src/lib/libsmbfs/smb/nbns_rq.c
index d0e85209e7..7dc46f3983 100644
--- a/usr/src/lib/libsmbfs/smb/nbns_rq.c
+++ b/usr/src/lib/libsmbfs/smb/nbns_rq.c
@@ -373,7 +373,7 @@ nbns_rq_create(int opcode, struct nb_ctx *ctx, struct nbns_rq **rqpp)
if (rqp == NULL)
return (ENOMEM);
bzero(rqp, sizeof (*rqp));
- error = mb_init(&rqp->nr_rq, NBDG_MAXSIZE);
+ error = mb_init_sz(&rqp->nr_rq, NBDG_MAXSIZE);
if (error) {
free(rqp);
return (error);
@@ -416,15 +416,15 @@ nbns_rq_getrr(struct nbns_rq *rqp, struct nbns_rr *rrp)
if (len < 1)
return (NBERROR(NBERR_INVALIDRESPONSE));
rrp->rr_name = cp;
- error = mb_get_mem(mbp, NULL, len);
+ error = md_get_mem(mbp, NULL, len, MB_MSYSTEM);
if (error)
return (error);
- mb_get_uint16be(mbp, &rrp->rr_type);
- mb_get_uint16be(mbp, &rrp->rr_class);
- mb_get_uint32be(mbp, &rrp->rr_ttl);
- mb_get_uint16be(mbp, &rrp->rr_rdlength);
+ md_get_uint16be(mbp, &rrp->rr_type);
+ md_get_uint16be(mbp, &rrp->rr_class);
+ md_get_uint32be(mbp, &rrp->rr_ttl);
+ md_get_uint16be(mbp, &rrp->rr_rdlength);
rrp->rr_data = (uchar_t *)mbp->mb_pos;
- error = mb_get_mem(mbp, NULL, rrp->rr_rdlength);
+ error = md_get_mem(mbp, NULL, rrp->rr_rdlength, MB_MSYSTEM);
return (error);
}
@@ -436,11 +436,7 @@ nbns_rq_prepare(struct nbns_rq *rqp)
uint16_t ofr; /* opcode, flags, rcode */
int error;
- /*
- * Replacing with one argument.
- * error = mb_init(&rqp->nr_rp, NBDG_MAXSIZE);
- */
- error = mb_init(&rqp->nr_rp, NBDG_MAXSIZE);
+ error = mb_init_sz(&rqp->nr_rp, NBDG_MAXSIZE);
if (error)
return (error);
@@ -455,15 +451,19 @@ nbns_rq_prepare(struct nbns_rq *rqp)
mb_put_uint16be(mbp, rqp->nr_qdcount);
mb_put_uint16be(mbp, rqp->nr_ancount);
mb_put_uint16be(mbp, rqp->nr_nscount);
- mb_put_uint16be(mbp, rqp->nr_arcount);
+ error = mb_put_uint16be(mbp, rqp->nr_arcount);
if (rqp->nr_qdcount) {
if (rqp->nr_qdcount > 1)
return (EINVAL);
- nb_name_encode(mbp, rqp->nr_qdname);
+ (void) nb_name_encode(mbp, rqp->nr_qdname);
mb_put_uint16be(mbp, rqp->nr_qdtype);
- mb_put_uint16be(mbp, rqp->nr_qdclass);
+ error = mb_put_uint16be(mbp, rqp->nr_qdclass);
}
- m_lineup(mbp->mb_top, &mbp->mb_top);
+ if (error)
+ return (error);
+ error = m_lineup(mbp->mb_top, &mbp->mb_top);
+ if (error)
+ return (error);
if (ctx->nb_timo == 0)
ctx->nb_timo = 1; /* by default 1 second */
return (0);
@@ -652,7 +652,7 @@ do_recv:
mbp = &rqp->nr_rp;
if (mbp->mb_count < 12)
return (NBERROR(NBERR_INVALIDRESPONSE));
- mb_get_uint16be(mbp, &rpid);
+ md_get_uint16be(mbp, &rpid);
if (rpid != rqp->nr_trnid)
return (NBERROR(NBERR_INVALIDRESPONSE));
break;
@@ -660,14 +660,14 @@ do_recv:
if (tries == maxretry)
return (NBERROR(NBERR_HOSTNOTFOUND));
- mb_get_uint16be(mbp, &ofr);
+ md_get_uint16be(mbp, &ofr);
rqp->nr_rpnmflags = (ofr >> 4) & 0x7F;
rqp->nr_rprcode = ofr & 0xf;
if (rqp->nr_rprcode)
return (NBERROR(rqp->nr_rprcode));
- mb_get_uint16be(mbp, &rpid); /* QDCOUNT */
- mb_get_uint16be(mbp, &rqp->nr_rpancount);
- mb_get_uint16be(mbp, &rqp->nr_rpnscount);
- mb_get_uint16be(mbp, &rqp->nr_rparcount);
+ md_get_uint16be(mbp, &rpid); /* QDCOUNT */
+ md_get_uint16be(mbp, &rqp->nr_rpancount);
+ md_get_uint16be(mbp, &rqp->nr_rpnscount);
+ md_get_uint16be(mbp, &rqp->nr_rparcount);
return (0);
}
diff --git a/usr/src/lib/libsmbfs/smb/negprot.c b/usr/src/lib/libsmbfs/smb/negprot.c
index 6c1649f1bb..cd6e2866df 100644
--- a/usr/src/lib/libsmbfs/smb/negprot.c
+++ b/usr/src/lib/libsmbfs/smb/negprot.c
@@ -104,7 +104,7 @@ smb_negprot(struct smb_ctx *ctx, struct mbdata *oblob)
struct mbdata *mbp;
struct smb_dialect *dp;
int err, len;
- uint8_t wc, stime[8], eklen;
+ uint8_t wc, eklen;
uint16_t dindex, bc;
int will_sign = 0;
@@ -188,8 +188,8 @@ smb_negprot(struct smb_ctx *ctx, struct mbdata *oblob)
* section 2.2.3
*/
mbp = &rqp->rq_rp;
- (void) mb_get_uint8(mbp, &wc);
- err = mb_get_uint16le(mbp, &dindex);
+ (void) md_get_uint8(mbp, &wc);
+ err = md_get_uint16le(mbp, &dindex);
if (err || dindex > SMB_DIALECT_MAX) {
DPRINT("err %d dindex %d", err, (int)dindex);
goto errout;
@@ -206,17 +206,17 @@ smb_negprot(struct smb_ctx *ctx, struct mbdata *oblob)
DPRINT("bad wc %d", (int)wc);
goto errout;
}
- mb_get_uint8(mbp, &sv->sv_sm); /* SecurityMode */
- mb_get_uint16le(mbp, &sv->sv_maxmux); /* MaxMpxCount */
- mb_get_uint16le(mbp, &sv->sv_maxvcs); /* MaxCountVCs */
- mb_get_uint32le(mbp, &sv->sv_maxtx); /* MaxBufferSize */
- mb_get_uint32le(mbp, &sv->sv_maxraw); /* MaxRawSize */
- mb_get_uint32le(mbp, &sv->sv_skey); /* SessionKey */
- mb_get_uint32le(mbp, &sv->sv_caps); /* Capabilities */
- mb_get_mem(mbp, (char *)stime, 8); /* SystemTime(s) */
- mb_get_uint16le(mbp, (uint16_t *)&sv->sv_tz);
- mb_get_uint8(mbp, &eklen); /* EncryptionKeyLength */
- err = mb_get_uint16le(mbp, &bc); /* ByteCount */
+ md_get_uint8(mbp, &sv->sv_sm); /* SecurityMode */
+ md_get_uint16le(mbp, &sv->sv_maxmux); /* MaxMpxCount */
+ md_get_uint16le(mbp, &sv->sv_maxvcs); /* MaxCountVCs */
+ md_get_uint32le(mbp, &sv->sv_maxtx); /* MaxBufferSize */
+ md_get_uint32le(mbp, &sv->sv_maxraw); /* MaxRawSize */
+ md_get_uint32le(mbp, &sv->sv_skey); /* SessionKey */
+ md_get_uint32le(mbp, &sv->sv_caps); /* Capabilities */
+ md_get_mem(mbp, NULL, 8, MB_MSYSTEM); /* SystemTime(s) */
+ md_get_uint16le(mbp, (uint16_t *)&sv->sv_tz);
+ md_get_uint8(mbp, &eklen); /* EncryptionKeyLength */
+ err = md_get_uint16le(mbp, &bc); /* ByteCount */
if (err)
goto errout;
@@ -325,7 +325,7 @@ smb_negprot(struct smb_ctx *ctx, struct mbdata *oblob)
/*
* Skip the server GUID.
*/
- err = mb_get_mem(mbp, NULL, SMB_GUIDLEN);
+ err = md_get_mem(mbp, NULL, SMB_GUIDLEN, MB_MSYSTEM);
if (err)
goto errout;
/*
@@ -339,7 +339,7 @@ smb_negprot(struct smb_ctx *ctx, struct mbdata *oblob)
/*
* Get the (optional) SPNEGO "hint".
*/
- err = mb_get_mbuf(mbp, len, &m);
+ err = md_get_mbuf(mbp, len, &m);
if (err)
goto errout;
mb_initm(oblob, m);
@@ -358,7 +358,8 @@ smb_negprot(struct smb_ctx *ctx, struct mbdata *oblob)
err = EBADRPC;
goto errout;
}
- err = mb_get_mem(mbp, (char *)ctx->ct_ntlm_chal, NTLM_CHAL_SZ);
+ err = md_get_mem(mbp, ctx->ct_ntlm_chal,
+ NTLM_CHAL_SZ, MB_MSYSTEM);
/*
* Server domain follows (ignored)
* Note: NOT aligned(2) - unusual!
diff --git a/usr/src/lib/libsmbfs/smb/netshareenum.c b/usr/src/lib/libsmbfs/smb/netshareenum.c
index 2ee1fd7792..bd2c24caec 100644
--- a/usr/src/lib/libsmbfs/smb/netshareenum.c
+++ b/usr/src/lib/libsmbfs/smb/netshareenum.c
@@ -280,9 +280,9 @@ smb_rap_NetShareEnum(struct smb_ctx *ctx, int sLevel, void *pbBuffer,
error = smb_rap_create(0, "WrLeh", "B13BWz", &rap);
if (error)
return (error);
- smb_rap_setNparam(rap, sLevel); /* W - sLevel */
- smb_rap_setPparam(rap, pbBuffer); /* r - pbBuffer */
- smb_rap_setNparam(rap, *cbBuffer); /* L - cbBuffer */
+ (void) smb_rap_setNparam(rap, sLevel); /* W - sLevel */
+ (void) smb_rap_setPparam(rap, pbBuffer); /* r - pbBuffer */
+ (void) smb_rap_setNparam(rap, *cbBuffer); /* L - cbBuffer */
error = smb_rap_request(rap, ctx);
if (error == 0) {
*pcEntriesRead = rap->r_entries;
diff --git a/usr/src/lib/libsmbfs/smb/ntlm.c b/usr/src/lib/libsmbfs/smb/ntlm.c
index 8119e62b65..ffd9ff3d41 100644
--- a/usr/src/lib/libsmbfs/smb/ntlm.c
+++ b/usr/src/lib/libsmbfs/smb/ntlm.c
@@ -187,11 +187,11 @@ ntlm_put_v1_responses(struct smb_ctx *ctx,
int err;
/* Get mbuf chain for the LM response. */
- if ((err = mb_init(lm_mbp, NTLM_V1_RESP_SZ)) != 0)
+ if ((err = mb_init_sz(lm_mbp, NTLM_V1_RESP_SZ)) != 0)
return (err);
/* Get mbuf chain for the NT response. */
- if ((err = mb_init(nt_mbp, NTLM_V1_RESP_SZ)) != 0)
+ if ((err = mb_init_sz(nt_mbp, NTLM_V1_RESP_SZ)) != 0)
return (err);
/*
@@ -199,7 +199,9 @@ ntlm_put_v1_responses(struct smb_ctx *ctx,
* from the challenge and the ASCII
* password (if authflags allow).
*/
- mb_fit(lm_mbp, NTLM_V1_RESP_SZ, (char **)&lmresp);
+ err = mb_fit(lm_mbp, NTLM_V1_RESP_SZ, (char **)&lmresp);
+ if (err)
+ return (err);
bzero(lmresp, NTLM_V1_RESP_SZ);
if (ctx->ct_authflags & SMB_AT_LM1) {
/* They asked to send the LM hash too. */
@@ -213,7 +215,9 @@ ntlm_put_v1_responses(struct smb_ctx *ctx,
* Compute the NTLM response, derived from
* the challenge and the NT hash.
*/
- mb_fit(nt_mbp, NTLM_V1_RESP_SZ, (char **)&ntresp);
+ err = mb_fit(nt_mbp, NTLM_V1_RESP_SZ, (char **)&ntresp);
+ if (err)
+ return (err);
bzero(ntresp, NTLM_V1_RESP_SZ);
err = ntlm_v1_response(ntresp, ctx->ct_nthash,
ctx->ct_ntlm_chal, NTLM_CHAL_SZ);
@@ -408,9 +412,9 @@ ntlm_put_v2_responses(struct smb_ctx *ctx, struct mbdata *ti_mbp,
uchar_t v2hash[NTLM_HASH_SZ];
struct mbuf *tim = ti_mbp->mb_top;
- if ((err = mb_init(lm_mbp, M_MINSIZE)) != 0)
+ if ((err = mb_init(lm_mbp)) != 0)
return (err);
- if ((err = mb_init(nt_mbp, M_MINSIZE)) != 0)
+ if ((err = mb_init(nt_mbp)) != 0)
return (err);
/*
@@ -443,13 +447,13 @@ ntlm_put_v2_responses(struct smb_ctx *ctx, struct mbdata *ti_mbp,
* 2: Client nonce
*/
lmresp = (uchar_t *)lm_mbp->mb_pos;
- mb_put_mem(lm_mbp, NULL, NTLM_HASH_SZ);
+ mb_put_mem(lm_mbp, NULL, NTLM_HASH_SZ, MB_MSYSTEM);
err = ntlm_v2_resp_hash(lmresp,
v2hash, ctx->ct_ntlm_chal,
ctx->ct_clnonce, NTLM_CHAL_SZ);
if (err)
goto out;
- mb_put_mem(lm_mbp, ctx->ct_clnonce, NTLM_CHAL_SZ);
+ mb_put_mem(lm_mbp, ctx->ct_clnonce, NTLM_CHAL_SZ, MB_MSYSTEM);
/*
* Compute the NTLMv2 response, derived
@@ -461,13 +465,13 @@ ntlm_put_v2_responses(struct smb_ctx *ctx, struct mbdata *ti_mbp,
* 2: "target info." blob
*/
ntresp = (uchar_t *)nt_mbp->mb_pos;
- mb_put_mem(nt_mbp, NULL, NTLM_HASH_SZ);
+ mb_put_mem(nt_mbp, NULL, NTLM_HASH_SZ, MB_MSYSTEM);
err = ntlm_v2_resp_hash(ntresp,
v2hash, ctx->ct_ntlm_chal,
(uchar_t *)tim->m_data, tim->m_len);
if (err)
goto out;
- mb_put_mem(nt_mbp, tim->m_data, tim->m_len);
+ mb_put_mem(nt_mbp, tim->m_data, tim->m_len, MB_MSYSTEM);
/*
* Compute the session key
@@ -506,7 +510,7 @@ smb_put_blob_name(struct mbdata *mbp, char *name, int type)
mb_put_uint16le(mbp, type);
mb_put_uint16le(mbp, nlen);
- mb_put_mem(mbp, (char *)ucs, nlen);
+ mb_put_mem(mbp, (char *)ucs, nlen, MB_MSYSTEM);
if (ucs)
free(ucs);
@@ -528,7 +532,7 @@ ntlm_build_target_info(struct smb_ctx *ctx, struct mbuf *names,
int err;
/* Get mbuf chain for the "target info". */
- if ((err = mb_init(mbp, M_MINSIZE)) != 0)
+ if ((err = mb_init(mbp)) != 0)
return (err);
/*
@@ -556,7 +560,7 @@ ntlm_build_target_info(struct smb_ctx *ctx, struct mbuf *names,
mb_put_uint32le(mbp, 0x101); /* Blob signature */
mb_put_uint32le(mbp, 0); /* reserved */
mb_put_uint64le(mbp, nt_time); /* NT time stamp */
- mb_put_mem(mbp, ctx->ct_clnonce, NTLM_CHAL_SZ);
+ mb_put_mem(mbp, ctx->ct_clnonce, NTLM_CHAL_SZ, MB_MSYSTEM);
mb_put_uint32le(mbp, 0); /* unknown */
/*
@@ -564,7 +568,7 @@ ntlm_build_target_info(struct smb_ctx *ctx, struct mbuf *names,
* NTLMSSP Type 2 message or composed here.
*/
if (names) {
- err = mb_put_mem(mbp, names->m_data, names->m_len);
+ err = mb_put_mem(mbp, names->m_data, names->m_len, MB_MSYSTEM);
} else {
/* Get upper-case names. */
ucdom = utf8_str_toupper(ctx->ct_domain);
diff --git a/usr/src/lib/libsmbfs/smb/ntlmssp.c b/usr/src/lib/libsmbfs/smb/ntlmssp.c
index 3428fbca36..535777b187 100644
--- a/usr/src/lib/libsmbfs/smb/ntlmssp.c
+++ b/usr/src/lib/libsmbfs/smb/ntlmssp.c
@@ -87,13 +87,13 @@ static const char ntlmssp_id[ID_SZ] = "NTLMSSP";
* Get a "security buffer" (header part)
*/
static int
-mb_get_sb_hdr(struct mbdata *mbp, struct sec_buf *sb)
+md_get_sb_hdr(struct mbdata *mbp, struct sec_buf *sb)
{
int err;
- (void) mb_get_uint16le(mbp, &sb->sb_length);
- (void) mb_get_uint16le(mbp, &sb->sb_maxlen);
- err = mb_get_uint32le(mbp, &sb->sb_offset);
+ (void) md_get_uint16le(mbp, &sb->sb_length);
+ (void) md_get_uint16le(mbp, &sb->sb_maxlen);
+ err = md_get_uint32le(mbp, &sb->sb_offset);
return (err);
}
@@ -103,7 +103,7 @@ mb_get_sb_hdr(struct mbdata *mbp, struct sec_buf *sb)
* the data is delivered as an mbuf.
*/
static int
-mb_get_sb_data(struct mbdata *mbp, struct sec_buf *sb, struct mbuf **mp)
+md_get_sb_data(struct mbdata *mbp, struct sec_buf *sb, struct mbuf **mp)
{
struct mbdata tmp_mb;
int err;
@@ -115,12 +115,12 @@ mb_get_sb_data(struct mbdata *mbp, struct sec_buf *sb, struct mbuf **mp)
mb_initm(&tmp_mb, mbp->mb_top);
/* Skip data up to the offset. */
- err = mb_get_mem(&tmp_mb, NULL, sb->sb_offset);
+ err = md_get_mem(&tmp_mb, NULL, sb->sb_offset, MB_MSYSTEM);
if (err)
return (err);
/* Get the data (as an mbuf). */
- err = mb_get_mbuf(&tmp_mb, sb->sb_maxlen, mp);
+ err = md_get_mbuf(&tmp_mb, sb->sb_maxlen, mp);
return (err);
}
@@ -174,10 +174,10 @@ mb_put_sb_string(struct mbdata *mbp, struct sec_buf *sb,
* then chop off the null terminator
* before appending to caller's mbp.
*/
- err = mb_init(&tmp_mb, M_MINSIZE);
+ err = mb_init(&tmp_mb);
if (err)
return (err);
- err = mb_put_dstring(&tmp_mb, s, unicode);
+ err = mb_put_string(&tmp_mb, s, unicode);
if (err)
return (err);
@@ -218,7 +218,7 @@ ntlmssp_put_type1(struct ssp_ctx *sp, struct mbdata *out_mb)
char *ucdom = NULL;
char *ucwks = NULL;
- if ((err = mb_init(&mb2, M_MINSIZE)) != 0)
+ if ((err = mb_init(&mb2)) != 0)
return (err);
mb2.mb_count = sizeof (hdr);
@@ -269,7 +269,7 @@ ntlmssp_put_type1(struct ssp_ctx *sp, struct mbdata *out_mb)
* Marshal the header (in LE order)
* then concatenate the 2nd part.
*/
- (void) mb_put_mem(out_mb, &hdr.h_id, ID_SZ);
+ (void) mb_put_mem(out_mb, &hdr.h_id, ID_SZ, MB_MSYSTEM);
(void) mb_put_uint32le(out_mb, hdr.h_type);
(void) mb_put_uint32le(out_mb, hdr.h_flags);
(void) mb_put_sb_hdr(out_mb, &hdr.h_cldom);
@@ -322,15 +322,15 @@ ntlmssp_get_type2(struct ssp_ctx *sp, struct mbdata *in_mb)
/* Parse the fixed size header stuff. */
bzero(&hdr, sizeof (hdr));
- (void) mb_get_mem(in_mb, &hdr.h_id, ID_SZ);
- (void) mb_get_uint32le(in_mb, &hdr.h_type);
+ (void) md_get_mem(in_mb, &hdr.h_id, ID_SZ, MB_MSYSTEM);
+ (void) md_get_uint32le(in_mb, &hdr.h_type);
if (hdr.h_type != 2) {
err = EPROTO;
goto out;
}
- (void) mb_get_sb_hdr(in_mb, &hdr.h_target_name);
- (void) mb_get_uint32le(in_mb, &hdr.h_flags);
- (void) mb_get_mem(in_mb, &hdr.h_challenge, NTLM_CHAL_SZ);
+ (void) md_get_sb_hdr(in_mb, &hdr.h_target_name);
+ (void) md_get_uint32le(in_mb, &hdr.h_flags);
+ (void) md_get_mem(in_mb, &hdr.h_challenge, NTLM_CHAL_SZ, MB_MSYSTEM);
/*
* Save flags, challenge for later.
@@ -344,9 +344,9 @@ ntlmssp_get_type2(struct ssp_ctx *sp, struct mbdata *in_mb)
*/
if ((m_totlen(top_mb.mb_top) > sizeof (hdr)) &&
(hdr.h_target_name.sb_offset >= sizeof (hdr))) {
- (void) mb_get_uint32le(in_mb, &hdr.h_context[0]);
- (void) mb_get_uint32le(in_mb, &hdr.h_context[1]);
- (void) mb_get_sb_hdr(in_mb, &hdr.h_target_info);
+ (void) md_get_uint32le(in_mb, &hdr.h_context[0]);
+ (void) md_get_uint32le(in_mb, &hdr.h_context[1]);
+ (void) md_get_sb_hdr(in_mb, &hdr.h_target_info);
}
/*
@@ -354,18 +354,18 @@ ntlmssp_get_type2(struct ssp_ctx *sp, struct mbdata *in_mb)
* the data from the offset/length indicated in the
* security buffer header; then parse the string.
*/
- err = mb_get_sb_data(&top_mb, &hdr.h_target_name, &m);
+ err = md_get_sb_data(&top_mb, &hdr.h_target_name, &m);
if (err)
goto out;
mb_initm(&tmp_mb, m);
- err = mb_get_string(&tmp_mb, &ssp_st->ss_target_name, uc);
+ err = md_get_string(&tmp_mb, &ssp_st->ss_target_name, uc);
mb_done(&tmp_mb);
/*
* Get the target info blob, if present.
*/
if (hdr.h_target_info.sb_offset >= sizeof (hdr)) {
- err = mb_get_sb_data(&top_mb, &hdr.h_target_info,
+ err = md_get_sb_data(&top_mb, &hdr.h_target_info,
&ssp_st->ss_target_info);
}
@@ -422,7 +422,7 @@ ntlmssp_put_type3(struct ssp_ctx *sp, struct mbdata *out_mb)
goto out;
}
- if ((err = mb_init(&mb2, M_MINSIZE)) != 0)
+ if ((err = mb_init(&mb2)) != 0)
goto out;
mb2.mb_count = sizeof (hdr);
uc = ssp_st->ss_flags & NTLMSSP_NEGOTIATE_UNICODE;
@@ -475,7 +475,7 @@ ntlmssp_put_type3(struct ssp_ctx *sp, struct mbdata *out_mb)
* Marshal the header (in LE order)
* then concatenate the 2nd part.
*/
- (void) mb_put_mem(out_mb, &hdr.h_id, ID_SZ);
+ (void) mb_put_mem(out_mb, &hdr.h_id, ID_SZ, MB_MSYSTEM);
(void) mb_put_uint32le(out_mb, hdr.h_type);
(void) mb_put_sb_hdr(out_mb, &hdr.h_lm_resp);
@@ -555,7 +555,7 @@ ntlmssp_next_token(struct ssp_ctx *sp, struct mbdata *in_mb,
}
/* Will build an ouptut token. */
- err = mb_init(out_mb, M_MINSIZE);
+ err = mb_init(out_mb);
if (err)
goto out;
diff --git a/usr/src/lib/libsmbfs/smb/print.c b/usr/src/lib/libsmbfs/smb/print.c
index 263cafaa93..268c330a0b 100644
--- a/usr/src/lib/libsmbfs/smb/print.c
+++ b/usr/src/lib/libsmbfs/smb/print.c
@@ -75,19 +75,19 @@ smb_printer_open(struct smb_ctx *ctx, int setuplen, int mode,
smb_rq_wend(rqp);
smb_rq_bstart(rqp);
mb_put_uint8(mbp, SMB_DT_ASCII);
- mb_put_dstring(mbp, ident, uc);
+ mb_put_string(mbp, ident, uc);
smb_rq_bend(rqp);
error = smb_rq_simple(rqp);
if (error)
goto out;
mbp = smb_rq_getreply(rqp);
- error = mb_get_uint8(mbp, &wc);
+ error = md_get_uint8(mbp, &wc);
if (error || wc < 1) {
error = EBADRPC;
goto out;
}
- mb_get_uint16(mbp, &fh);
+ md_get_uint16le(mbp, &fh);
*fhp = fh;
error = 0;
diff --git a/usr/src/lib/libsmbfs/smb/private.h b/usr/src/lib/libsmbfs/smb/private.h
index b95ec1f7f4..e6124f2e57 100644
--- a/usr/src/lib/libsmbfs/smb/private.h
+++ b/usr/src/lib/libsmbfs/smb/private.h
@@ -47,6 +47,7 @@
#include <sys/byteorder.h>
#include <sys/ccompile.h>
+#include <netsmb/mchain.h>
#include <netsmb/netbios.h>
extern void dprint(const char *, const char *, ...)
@@ -71,39 +72,6 @@ extern void dprint(const char *, const char *, ...)
#define SMBV_EXT_SEC 0x0080 /* conn to use extended security */
#define SMBV_WILL_SIGN 0x0100 /* negotiated signing */
-
-/*
- * BSD-style mbuf simulation
- */
-struct mbuf {
- int m_len;
- int m_maxlen;
- char *m_data;
- struct mbuf *m_next;
-};
-typedef struct mbuf mbuf_t;
-
-struct mbdata {
- struct mbuf *mb_top;
- struct mbuf *mb_cur;
- char *mb_pos;
- int mb_count;
-};
-typedef struct mbdata mbdata_t;
-
-/*
- * Note: Leaving a little space (8 bytes) between the
- * mbuf header and the start of the data so we can
- * prepend a NetBIOS header in that space.
- */
-#define M_ALIGNFACTOR (sizeof (long))
-#define M_ALIGN(len) (((len) + M_ALIGNFACTOR - 1) & ~(M_ALIGNFACTOR - 1))
-#define M_BASESIZE (sizeof (struct mbuf) + 8)
-#define M_MINSIZE (1024 - M_BASESIZE)
-#define M_TOP(m) ((char *)(m) + M_BASESIZE)
-#define M_TRAILINGSPACE(m) ((m)->m_maxlen - (m)->m_len)
-#define mtod(m, t) ((t)(m)->m_data)
-
/*
* request handling structures
*/
@@ -140,52 +108,26 @@ void smb_rq_wend(struct smb_rq *);
int smb_rq_simple(struct smb_rq *);
int smb_rq_dmem(struct mbdata *, const char *, size_t);
int smb_rq_internal(struct smb_ctx *, struct smb_rq *);
-int smb_rq_sign(struct smb_rq *);
+void smb_rq_sign(struct smb_rq *);
int smb_rq_verify(struct smb_rq *);
-
/*
- * Message compose/parse
+ * This library extends the mchain.h function set a little.
*/
-
-void m_freem(struct mbuf *);
-int m_getm(struct mbuf *, size_t, struct mbuf **);
+int m_getm(struct mbuf *, int, struct mbuf **);
int m_lineup(struct mbuf *, struct mbuf **);
size_t m_totlen(struct mbuf *);
-int mb_init(struct mbdata *, size_t);
-int mb_initm(struct mbdata *, struct mbuf *);
-int mb_done(struct mbdata *);
-int mb_fit(struct mbdata *mbp, size_t size, char **pp);
-int mb_put_uint8(struct mbdata *, uint8_t);
-int mb_put_uint16be(struct mbdata *, uint16_t);
-int mb_put_uint16le(struct mbdata *, uint16_t);
-int mb_put_uint32be(struct mbdata *, uint32_t);
-int mb_put_uint32le(struct mbdata *, uint32_t);
-int mb_put_uint64be(struct mbdata *, uint64_t);
-int mb_put_uint64le(struct mbdata *, uint64_t);
-int mb_put_mem(struct mbdata *, const void *, size_t);
-int mb_put_mbuf(struct mbdata *, struct mbuf *);
+int mb_init_sz(struct mbdata *, int);
+int mb_fit(struct mbdata *mbp, int size, char **pp);
+
+int mb_put_string(struct mbdata *mbp, const char *s, int);
int mb_put_astring(struct mbdata *mbp, const char *s);
-int mb_put_dstring(struct mbdata *mbp, const char *s, int);
int mb_put_ustring(struct mbdata *mbp, const char *s);
-int mb_get_uint8(struct mbdata *, uint8_t *);
-int mb_get_uint16(struct mbdata *, uint16_t *);
-int mb_get_uint16le(struct mbdata *, uint16_t *);
-int mb_get_uint16be(struct mbdata *, uint16_t *);
-int mb_get_uint32(struct mbdata *, uint32_t *);
-int mb_get_uint32be(struct mbdata *, uint32_t *);
-int mb_get_uint32le(struct mbdata *, uint32_t *);
-int mb_get_uint64(struct mbdata *, uint64_t *);
-int mb_get_uint64be(struct mbdata *, uint64_t *);
-int mb_get_uint64le(struct mbdata *, uint64_t *);
-int mb_get_mem(struct mbdata *, void *, size_t);
-int mb_get_mbuf(struct mbdata *, int, struct mbuf **);
-int mb_get_string(struct mbdata *, char **, int);
-int mb_get_astring(struct mbdata *, char **);
-int mb_get_ustring(struct mbdata *, char **);
-
+int md_get_string(struct mbdata *, char **, int);
+int md_get_astring(struct mbdata *, char **);
+int md_get_ustring(struct mbdata *, char **);
/*
* Network stuff (NetBIOS and otherwise)
diff --git a/usr/src/lib/libsmbfs/smb/rap.c b/usr/src/lib/libsmbfs/smb/rap.c
index 8260e2639c..98f35af5ff 100644
--- a/usr/src/lib/libsmbfs/smb/rap.c
+++ b/usr/src/lib/libsmbfs/smb/rap.c
@@ -222,9 +222,11 @@ smb_rap_create(int fn, const char *param, const char *data,
len += plen;
}
rap->r_pbuf = rap->r_npbuf = malloc(len);
- smb_rap_rqparam(rap, 'W', 1, fn);
- smb_rap_rqparam_z(rap, rap->r_sparam);
- smb_rap_rqparam_z(rap, rap->r_sdata);
+ if (rap->r_pbuf == NULL)
+ return (ENOMEM);
+ (void) smb_rap_rqparam(rap, 'W', 1, fn);
+ (void) smb_rap_rqparam_z(rap, rap->r_sparam);
+ (void) smb_rap_rqparam_z(rap, rap->r_sdata);
*rapp = rap;
return (0);
}
diff --git a/usr/src/lib/libsmbfs/smb/rq.c b/usr/src/lib/libsmbfs/smb/rq.c
index 7b21708428..6045237393 100644
--- a/usr/src/lib/libsmbfs/smb/rq.c
+++ b/usr/src/lib/libsmbfs/smb/rq.c
@@ -51,6 +51,8 @@
#include <netsmb/smb_lib.h>
#include "private.h"
+#define MIN_REPLY_SIZE 4096
+
static uint32_t smb_map_doserr(uint8_t, uint16_t);
/*
@@ -85,11 +87,11 @@ smb_rq_init(struct smb_ctx *ctx, uchar_t cmd, struct smb_rq **rqpp)
* Setup the request buffer.
* Do the reply buffer later.
*/
- if (mb_init(&rqp->rq_rq, M_MINSIZE))
+ if (mb_init(&rqp->rq_rq))
goto errout;
/* Space for the SMB header. (filled in later) */
- mb_put_mem(&rqp->rq_rq, NULL, SMB_HDRLEN);
+ mb_put_mem(&rqp->rq_rq, NULL, SMB_HDRLEN, MB_MSYSTEM);
/*
* Copy the ctx flags here, so the caller can
@@ -130,7 +132,7 @@ smb_rq_wstart(struct smb_rq *rqp)
{
struct mbdata *mbp = &rqp->rq_rq;
- mb_fit(mbp, 1, &rqp->rq_wcntp);
+ (void) mb_fit(mbp, 1, &rqp->rq_wcntp);
rqp->rq_wcbase = mbp->mb_count;
}
@@ -176,7 +178,7 @@ smb_rq_bstart(struct smb_rq *rqp)
{
struct mbdata *mbp = &rqp->rq_rq;
- mb_fit(mbp, 2, &rqp->rq_bcntp);
+ (void) mb_fit(mbp, 2, &rqp->rq_bcntp);
rqp->rq_bcbase = mbp->mb_count;
}
@@ -209,19 +211,16 @@ smb_rq_bend(struct smb_rq *rqp)
rqp->rq_bcntp[1] = (bcnt >> 8);
}
-/*
- * Removed: smb_rq_dmem
- * which was mostly like: mb_put_mem
- */
-
int
smb_rq_simple(struct smb_rq *rqp)
{
struct smbioc_rq krq;
struct mbdata *mbp;
+ mbuf_t *m;
char *data;
uint32_t len;
size_t rpbufsz;
+ int error;
bzero(&krq, sizeof (krq));
krq.ioc_cmd = rqp->rq_cmd;
@@ -231,7 +230,10 @@ smb_rq_simple(struct smb_rq *rqp)
* and fill in the ioctl request.
*/
mbp = smb_rq_getrequest(rqp);
- m_lineup(mbp->mb_top, &mbp->mb_top);
+ error = m_lineup(mbp->mb_top, &mbp->mb_top);
+ if (error)
+ return (error);
+
data = mtod(mbp->mb_top, char *);
len = m_totlen(mbp->mb_top);
@@ -246,20 +248,19 @@ smb_rq_simple(struct smb_rq *rqp)
krq.ioc_tbuf = data + SMB_HDRLEN;
/*
- * Setup a buffer to hold the reply.
- *
- * Default size is M_MINSIZE, but the
- * caller may increase rq_rpbufsz
- * before calling this.
+ * Setup a buffer to hold the reply,
+ * at least MIN_REPLY_SIZE, or larger
+ * if the caller increased rq_rpbufsz.
*/
mbp = smb_rq_getreply(rqp);
rpbufsz = rqp->rq_rpbufsz;
- if (rpbufsz < M_MINSIZE)
- rpbufsz = M_MINSIZE;
- if (mb_init(mbp, rpbufsz))
- return (ENOMEM);
+ if (rpbufsz < MIN_REPLY_SIZE)
+ rpbufsz = MIN_REPLY_SIZE;
+ if ((error = m_get(rpbufsz, &m)) != 0)
+ return (error);
+ mb_initm(mbp, m);
krq.ioc_rbufsz = rpbufsz;
- krq.ioc_rbuf = mtod(mbp->mb_top, char *);
+ krq.ioc_rbuf = mtod(m, char *);
/*
* Call the driver
@@ -271,7 +272,7 @@ smb_rq_simple(struct smb_rq *rqp)
* Initialize returned mbdata.
* SMB header already parsed.
*/
- mbp->mb_top->m_len = krq.ioc_rbufsz;
+ m->m_len = krq.ioc_rbufsz;
return (0);
}
@@ -360,14 +361,13 @@ smb_rq_internal(struct smb_ctx *ctx, struct smb_rq *rqp)
/*
* rewind done; fill it in
*/
- mb_put_mem(mbp, (char *)SMB_SIGNATURE, SMB_SIGLEN);
+ mb_put_mem(mbp, ffsmb, SMB_SIGLEN, MB_MSYSTEM);
mb_put_uint8(mbp, rqp->rq_cmd);
- mb_put_mem(mbp, NULL, 4); /* status */
+ mb_put_uint32le(mbp, 0); /* status */
mb_put_uint8(mbp, rqp->rq_hflags);
mb_put_uint16le(mbp, rqp->rq_hflags2);
- mb_put_uint16le(mbp, 0); /* pid_hi */
- mb_put_mem(mbp, NULL, 8); /* signature */
- mb_put_uint16le(mbp, 0); /* reserved */
+ /* pid_hi(2), signature(8), reserved(2) */
+ mb_put_mem(mbp, NULL, 12, MB_MZERO);
mb_put_uint16le(mbp, rqp->rq_tid);
mb_put_uint16le(mbp, 0); /* pid_lo */
mb_put_uint16le(mbp, rqp->rq_uid);
@@ -416,22 +416,21 @@ smb_rq_internal(struct smb_ctx *ctx, struct smb_rq *rqp)
/*
* Decode the SMB header.
*/
- mb_get_mem(mbp, (char *)sigbuf, 4);
+ md_get_mem(mbp, (char *)sigbuf, 4, MB_MSYSTEM);
if (0 != bcmp(sigbuf, ffsmb, 4)) {
DPRINT("not SMB");
return (EBADRPC);
}
- mb_get_uint8(mbp, &ctmp); /* SMB cmd */
- mb_get_uint32le(mbp, &rqp->rq_status);
- mb_get_uint8(mbp, &rqp->rq_hflags);
- mb_get_uint16le(mbp, &rqp->rq_hflags2);
- mb_get_uint16le(mbp, NULL); /* pid_hi */
- mb_get_mem(mbp, NULL, 8); /* signature */
- mb_get_uint16le(mbp, NULL); /* reserved */
- mb_get_uint16le(mbp, &rqp->rq_tid);
- mb_get_uint16le(mbp, NULL); /* pid_lo */
- mb_get_uint16le(mbp, &rqp->rq_uid);
- mb_get_uint16le(mbp, &rqp->rq_mid);
+ md_get_uint8(mbp, &ctmp); /* SMB cmd */
+ md_get_uint32le(mbp, &rqp->rq_status);
+ md_get_uint8(mbp, &rqp->rq_hflags);
+ md_get_uint16le(mbp, &rqp->rq_hflags2);
+ /* pid_hi(2), signature(8), reserved(2) */
+ md_get_mem(mbp, NULL, 12, MB_MSYSTEM);
+ md_get_uint16le(mbp, &rqp->rq_tid);
+ md_get_uint16le(mbp, NULL); /* pid_lo */
+ md_get_uint16le(mbp, &rqp->rq_uid);
+ md_get_uint16le(mbp, &rqp->rq_mid);
/*
* Figure out the status return.
diff --git a/usr/src/lib/libsmbfs/smb/signing.c b/usr/src/lib/libsmbfs/smb/signing.c
index ef9a32e2e0..0e9c826bbd 100644
--- a/usr/src/lib/libsmbfs/smb/signing.c
+++ b/usr/src/lib/libsmbfs/smb/signing.c
@@ -142,7 +142,7 @@ smb_compute_MAC(struct smb_ctx *ctx, mbuf_t *m,
/*
* Sign a request with HMAC-MD5.
*/
-int
+void
smb_rq_sign(struct smb_rq *rqp)
{
struct smb_ctx *ctx = rqp->rq_ctx;
@@ -155,7 +155,7 @@ smb_rq_sign(struct smb_rq *rqp)
* but just in case...
*/
if (m->m_len < SMB_HDRLEN)
- return (EIO);
+ return;
sigloc = (uchar_t *)m->m_data + SMBSIGOFF;
if (ctx->ct_mackey == NULL) {
@@ -165,7 +165,7 @@ smb_rq_sign(struct smb_rq *rqp)
* This happens with SPNEGO, NTLMSSP, ...
*/
bcopy("BSRSPLY", sigloc, 8);
- return (0);
+ return;
}
/*
@@ -178,9 +178,7 @@ smb_rq_sign(struct smb_rq *rqp)
if (err) {
DPRINT("compute MAC, err %d", err);
bzero(sigloc, SMBSIGLEN);
- return (ENOTSUP);
}
- return (0);
}
/*
@@ -247,10 +245,10 @@ smb_rq_verify(struct smb_rq *rqp)
* of the sequence # has gotten a bit out of sync.
*/
for (fudge = 1; fudge <= nsmb_signing_fudge; fudge++) {
- smb_compute_MAC(ctx, m, rseqno + fudge, sigbuf);
+ (void) smb_compute_MAC(ctx, m, rseqno + fudge, sigbuf);
if (bcmp(sigbuf, sigloc, SMBSIGLEN) == 0)
break;
- smb_compute_MAC(ctx, m, rseqno - fudge, sigbuf);
+ (void) smb_compute_MAC(ctx, m, rseqno - fudge, sigbuf);
if (bcmp(sigbuf, sigloc, SMBSIGLEN) == 0) {
fudge = -fudge;
break;
diff --git a/usr/src/lib/libsmbfs/smb/ssnsetup.c b/usr/src/lib/libsmbfs/smb/ssnsetup.c
index e4b5ec4f20..712a71f34c 100644
--- a/usr/src/lib/libsmbfs/smb/ssnsetup.c
+++ b/usr/src/lib/libsmbfs/smb/ssnsetup.c
@@ -405,11 +405,11 @@ smb__ssnsetup(struct smb_ctx *ctx,
mb_put_mbuf(mbp, mbc2->mb_top); /* NT password */
mbc2->mb_top = NULL; /* consumed */
}
- mb_put_dstring(mbp, ctx->ct_user, uc);
- mb_put_dstring(mbp, ctx->ct_domain, uc);
+ mb_put_string(mbp, ctx->ct_user, uc);
+ mb_put_string(mbp, ctx->ct_domain, uc);
}
- mb_put_dstring(mbp, NativeOS, uc);
- mb_put_dstring(mbp, LanMan, uc);
+ mb_put_string(mbp, NativeOS, uc);
+ mb_put_string(mbp, LanMan, uc);
smb_rq_bend(rqp);
err = smb_rq_internal(ctx, rqp);
@@ -436,7 +436,7 @@ smb__ssnsetup(struct smb_ctx *ctx,
is->is_smbuid = rqp->rq_uid;
mbp = &rqp->rq_rp;
- err = mb_get_uint8(mbp, &wc);
+ err = md_get_uint8(mbp, &wc);
if (err)
goto out;
@@ -444,18 +444,18 @@ smb__ssnsetup(struct smb_ctx *ctx,
if (caps & SMB_CAP_EXT_SECURITY) {
if (wc != 4)
goto out;
- mb_get_uint16le(mbp, NULL); /* secondary cmd */
- mb_get_uint16le(mbp, NULL); /* andxoffset */
- mb_get_uint16le(mbp, actionp); /* action */
- mb_get_uint16le(mbp, &sblen); /* sec. blob len */
- mb_get_uint16le(mbp, &bc); /* byte count */
+ md_get_uint16le(mbp, NULL); /* secondary cmd */
+ md_get_uint16le(mbp, NULL); /* andxoffset */
+ md_get_uint16le(mbp, actionp); /* action */
+ md_get_uint16le(mbp, &sblen); /* sec. blob len */
+ md_get_uint16le(mbp, &bc); /* byte count */
/*
* Get the security blob, after
* sanity-checking the length.
*/
if (sblen == 0 || bc < sblen)
goto out;
- err = mb_get_mbuf(mbp, sblen, &m);
+ err = md_get_mbuf(mbp, sblen, &m);
if (err)
goto out;
mb_initm(mbc2, m);
@@ -463,10 +463,10 @@ smb__ssnsetup(struct smb_ctx *ctx,
} else {
if (wc != 3)
goto out;
- mb_get_uint16le(mbp, NULL); /* secondary cmd */
- mb_get_uint16le(mbp, NULL); /* andxoffset */
- mb_get_uint16le(mbp, actionp); /* action */
- err = mb_get_uint16le(mbp, &bc); /* byte count */
+ md_get_uint16le(mbp, NULL); /* secondary cmd */
+ md_get_uint16le(mbp, NULL); /* andxoffset */
+ md_get_uint16le(mbp, actionp); /* action */
+ err = md_get_uint16le(mbp, &bc); /* byte count */
if (err)
goto out;
}
@@ -485,9 +485,9 @@ smb__ssnsetup(struct smb_ctx *ctx,
goto out;
/* Ignore any parsing errors for these strings. */
- err = mb_get_string(mbp, &ctx->ct_srv_OS, uc);
+ err = md_get_string(mbp, &ctx->ct_srv_OS, uc);
DPRINT("server OS: %s", err ? "?" : ctx->ct_srv_OS);
- err = mb_get_string(mbp, &ctx->ct_srv_LM, uc);
+ err = md_get_string(mbp, &ctx->ct_srv_LM, uc);
DPRINT("server LM: %s", err ? "?" : ctx->ct_srv_LM);
/*
* There's sometimes a server domain folloing
diff --git a/usr/src/lib/libsmbfs/smb/ssp.c b/usr/src/lib/libsmbfs/smb/ssp.c
index f8433ba8e5..d0b0d86d4f 100644
--- a/usr/src/lib/libsmbfs/smb/ssp.c
+++ b/usr/src/lib/libsmbfs/smb/ssp.c
@@ -277,7 +277,7 @@ ssp_ctx_next_token(struct smb_ctx *ctx,
err = EBADRPC;
goto out;
}
- err = mb_init(&body_in, (size_t)toklen);
+ err = mb_init_sz(&body_in, (size_t)toklen);
if (err)
goto out;
m = body_in.mb_top;
@@ -354,7 +354,7 @@ ssp_ctx_next_token(struct smb_ctx *ctx,
err = EBADRPC;
goto out;
}
- err = mb_init(caller_out, (size_t)toklen);
+ err = mb_init_sz(caller_out, (size_t)toklen);
if (err)
goto out;
m = caller_out->mb_top;
diff --git a/usr/src/pkgdefs/SUNWsmbfsu/prototype_com b/usr/src/pkgdefs/SUNWsmbfsu/prototype_com
index e1a79c3742..bf892511dc 100644
--- a/usr/src/pkgdefs/SUNWsmbfsu/prototype_com
+++ b/usr/src/pkgdefs/SUNWsmbfsu/prototype_com
@@ -58,7 +58,6 @@ d none usr/lib/fs 755 root sys
d none usr/lib/fs/smbfs 755 root sys
f none usr/lib/fs/smbfs/mount 555 root bin
f none usr/lib/fs/smbfs/umount 555 root bin
-d none usr/lib/fs/smb 755 root sys
f none usr/lib/fs/smbfs/libshare_smbfs.so.1 755 root bin
f none usr/lib/libsmbfs.so.1 755 root bin
d none usr/lib/mdb 755 root sys
diff --git a/usr/src/uts/common/Makefile.files b/usr/src/uts/common/Makefile.files
index 1feed57654..8681c65e96 100644
--- a/usr/src/uts/common/Makefile.files
+++ b/usr/src/uts/common/Makefile.files
@@ -1262,15 +1262,17 @@ UFS_OBJS += ufs_alloc.o ufs_bmap.o ufs_dir.o ufs_xattr.o \
lufs_log.o lufs_map.o lufs_top.o lufs_debug.o
VSCAN_OBJS += vscan_drv.o vscan_svc.o vscan_door.o
-NSMB_OBJS += smb_conn.o smb_dev.o smb_iod.o smb_rq.o \
- smb_sign.o smb_smb.o smb_tran.o smb_trantcp.o \
- smb_usr.o smb_subrs.o subr_mchain.o smb_pass.o
+NSMB_OBJS += smb_conn.o smb_dev.o smb_iod.o smb_pass.o \
+ smb_rq.o smb_sign.o smb_smb.o smb_subrs.o \
+ smb_time.o smb_tran.o smb_trantcp.o smb_usr.o \
+ subr_mchain.o
+SMBFS_COMMON_OBJS += smbfs_ntacl.o
SMBFS_OBJS += smbfs_vfsops.o smbfs_vnops.o smbfs_node.o \
smbfs_acl.o smbfs_client.o smbfs_smb.o \
smbfs_subr.o smbfs_subr2.o \
- smbfs_rwlock.o smbfs_xattr.o
-
+ smbfs_rwlock.o smbfs_xattr.o \
+ $(SMBFS_COMMON_OBJS)
#
# LVM modules
diff --git a/usr/src/uts/common/Makefile.rules b/usr/src/uts/common/Makefile.rules
index d87dd585e2..e1a301b569 100644
--- a/usr/src/uts/common/Makefile.rules
+++ b/usr/src/uts/common/Makefile.rules
@@ -284,6 +284,10 @@ $(OBJS_DIR)/%.o: $(UTSBASE)/common/fs/sharefs/%.c
$(COMPILE.c) -o $@ $<
$(CTFCONVERT_O)
+$(OBJS_DIR)/%.o: $(COMMONBASE)/smbclnt/%.c
+ $(COMPILE.c) -o $@ $<
+ $(CTFCONVERT_O)
+
$(OBJS_DIR)/%.o: $(UTSBASE)/common/fs/smbclnt/netsmb/%.c
$(COMPILE.c) -o $@ $<
$(CTFCONVERT_O)
@@ -1707,6 +1711,9 @@ $(LINTS_DIR)/%.ln: $(UTSBASE)/common/fs/proc/%.c
$(LINTS_DIR)/%.ln: $(UTSBASE)/common/fs/sharefs/%.c
@($(LHEAD) $(LINT.c) $< $(LTAIL))
+$(LINTS_DIR)/%.ln: $(COMMONBASE)/smbclnt/%.c
+ @($(LHEAD) $(LINT.c) $< $(LTAIL))
+
$(LINTS_DIR)/%.ln: $(UTSBASE)/common/fs/smbclnt/netsmb/%.c
@($(LHEAD) $(LINT.c) $< $(LTAIL))
diff --git a/usr/src/uts/common/fs/smbclnt/netsmb/smb_conn.c b/usr/src/uts/common/fs/smbclnt/netsmb/smb_conn.c
index f1dcd57ea3..d1e7efd60a 100644
--- a/usr/src/uts/common/fs/smbclnt/netsmb/smb_conn.c
+++ b/usr/src/uts/common/fs/smbclnt/netsmb/smb_conn.c
@@ -58,12 +58,7 @@
#include <sys/atomic.h>
#include <sys/u8_textprep.h>
-#ifdef APPLE
-#include <sys/smb_apple.h>
-#include <sys/smb_iconv.h>
-#else
#include <netsmb/smb_osdep.h>
-#endif
#include <netsmb/smb.h>
#include <netsmb/smb_conn.h>
@@ -620,7 +615,7 @@ smb_share_gone(struct smb_connobj *cp)
smb_credinit(&scred, NULL);
smb_iod_shutdown_share(ssp);
- smb_smb_treedisconnect(ssp, &scred);
+ (void) smb_smb_treedisconnect(ssp, &scred);
smb_credrele(&scred);
}
diff --git a/usr/src/uts/common/fs/smbclnt/netsmb/smb_conn.h b/usr/src/uts/common/fs/smbclnt/netsmb/smb_conn.h
index df85a77d11..83138776e4 100644
--- a/usr/src/uts/common/fs/smbclnt/netsmb/smb_conn.h
+++ b/usr/src/uts/common/fs/smbclnt/netsmb/smb_conn.h
@@ -81,13 +81,7 @@ typedef struct smb_cred {
#define SMBS_RECONNECTING 0x0002
#define SMBS_CONNECTED 0x0004
#define SMBS_TCON_WAIT 0x0008
-#define SMBS_1980 0x0010
-/*
- * ^ This partition can't handle dates before 1980. It's probably a FAT
- * partition but could be some other ancient FS type
- */
-#define SMBS_RESUMEKEYS 0x0020 /* must use resume keys */
-#define SMBS_LONGNAMES 0x0040 /* share can use long names */
+#define SMBS_FST_FAT 0x0010 /* share FS Type is FAT */
/*
* Note: the common "obj" level uses this GONE flag by
* the name SMBO_GONE. Keep this alias as a reminder.
@@ -274,7 +268,7 @@ typedef struct smb_fscb {
void (*fscb_up)(smb_share_t *);
} smb_fscb_t;
/* Install the above vector, or pass NULL to clear it. */
-int smb_fscb_set(smb_fscb_t *);
+void smb_fscb_set(smb_fscb_t *);
/*
* The driver per open instance object.
@@ -331,11 +325,11 @@ int smb_usr_iod_ioctl(smb_dev_t *sdp, int cmd, intptr_t arg, int flags);
int smb_iod_create(smb_vc_t *vcp);
int smb_iod_destroy(smb_vc_t *vcp);
int smb_iod_connect(smb_vc_t *vcp);
-int smb_iod_disconnect(smb_vc_t *vcp);
+void smb_iod_disconnect(smb_vc_t *vcp);
int smb_iod_addrq(struct smb_rq *rqp);
int smb_iod_multirq(struct smb_rq *rqp);
int smb_iod_waitrq(struct smb_rq *rqp);
-int smb_iod_removerq(struct smb_rq *rqp);
+void smb_iod_removerq(struct smb_rq *rqp);
void smb_iod_shutdown_share(smb_share_t *ssp);
void smb_iod_sendall(smb_vc_t *);
diff --git a/usr/src/uts/common/fs/smbclnt/netsmb/smb_dev.c b/usr/src/uts/common/fs/smbclnt/netsmb/smb_dev.c
index 8ec7daef1c..61b4088927 100644
--- a/usr/src/uts/common/fs/smbclnt/netsmb/smb_dev.c
+++ b/usr/src/uts/common/fs/smbclnt/netsmb/smb_dev.c
@@ -66,12 +66,7 @@
#include <sys/types.h>
#include <sys/zone.h>
-#ifdef APPLE
-#include <sys/smb_apple.h>
-#else
#include <netsmb/smb_osdep.h>
-#endif
-
#include <netsmb/mchain.h> /* for "htoles()" */
#include <netsmb/smb.h>
@@ -182,7 +177,7 @@ _init(void)
{
int error;
- ddi_soft_state_init(&statep, sizeof (smb_dev_t), 1);
+ (void) ddi_soft_state_init(&statep, sizeof (smb_dev_t), 1);
/* Can initialize some mutexes also. */
mutex_init(&dev_lck, NULL, MUTEX_DRIVER, NULL);
@@ -198,6 +193,9 @@ _init(void)
/* Initialize password Key chain DB. */
smb_pkey_init();
+ /* Time conversion stuff. */
+ smb_time_init();
+
/* Initialize crypto mechanisms. */
smb_crypto_mech_init();
@@ -247,6 +245,9 @@ _fini(void)
(void) zone_key_delete(nsmb_zone_key);
+ /* Time conversion stuff. */
+ smb_time_fini();
+
/* Destroy password Key chain DB. */
smb_pkey_fini();
@@ -384,7 +385,7 @@ nsmb_ioctl(dev_t dev, int cmd, intptr_t arg, int flags, /* model.h */
err = 0;
switch (cmd) {
case SMBIOC_GETVERS:
- ddi_copyout(&nsmb_version, (void *)arg,
+ (void) ddi_copyout(&nsmb_version, (void *)arg,
sizeof (nsmb_version), flags);
break;
diff --git a/usr/src/uts/common/fs/smbclnt/netsmb/smb_iod.c b/usr/src/uts/common/fs/smbclnt/netsmb/smb_iod.c
index f6bba8380a..e7cac1aa75 100644
--- a/usr/src/uts/common/fs/smbclnt/netsmb/smb_iod.c
+++ b/usr/src/uts/common/fs/smbclnt/netsmb/smb_iod.c
@@ -64,11 +64,7 @@
#include <sys/zone.h>
#include <sys/sdt.h>
-#ifdef APPLE
-#include <sys/smb_apple.h>
-#else
#include <netsmb/smb_osdep.h>
-#endif
#include <netsmb/smb.h>
#include <netsmb/smb_conn.h>
@@ -85,11 +81,10 @@ int smb_iod_send_echo(smb_vc_t *);
* can't unload until all the mounts are gone.
*/
static smb_fscb_t *fscb;
-int
+void
smb_fscb_set(smb_fscb_t *cb)
{
fscb = cb;
- return (0);
}
static void
@@ -161,7 +156,7 @@ smb_iod_invrq(struct smb_vc *vcp)
*
* Forcibly kill the connection and IOD.
*/
-int
+void
smb_iod_disconnect(struct smb_vc *vcp)
{
@@ -194,8 +189,6 @@ smb_iod_disconnect(struct smb_vc *vcp)
vcp->iod_thr != curthread) {
tsignal(vcp->iod_thr, SIGKILL);
}
-
- return (0);
}
/*
@@ -700,7 +693,7 @@ smb_iod_multirq(struct smb_rq *rqp)
}
-int
+void
smb_iod_removerq(struct smb_rq *rqp)
{
struct smb_vc *vcp = rqp->sr_vc;
@@ -716,8 +709,6 @@ smb_iod_removerq(struct smb_rq *rqp)
#endif
TAILQ_REMOVE(&vcp->iod_rqlist, rqp, sr_link);
rw_exit(&vcp->iod_rqlock);
-
- return (0);
}
@@ -789,7 +780,6 @@ smb_iod_waitrq(struct smb_rq *rqp)
tmo1 = SEC_TO_TICK(smb_timo_notice);
else
tmo1 = 0;
-
tmo2 = ddi_get_lbolt() + SEC_TO_TICK(rqp->sr_timo);
/*
@@ -914,14 +904,13 @@ void
smb_iod_sendall(smb_vc_t *vcp)
{
struct smb_rq *rqp;
- int error, save_newrq, muxcnt;
+ int error, muxcnt;
/*
* Clear "newrq" to make sure threads adding
* new requests will run this function again.
*/
rw_enter(&vcp->iod_rqlock, RW_WRITER);
- save_newrq = vcp->iod_newrq;
vcp->iod_newrq = 0;
/*
@@ -931,9 +920,6 @@ smb_iod_sendall(smb_vc_t *vcp)
*/
rw_downgrade(&vcp->iod_rqlock);
- /* Expect to find about this many requests. */
- SMBIODEBUG("top, save_newrq=%d\n", save_newrq);
-
/*
* Serialize to prevent multiple senders.
* Note lock order: iod_rqlock, vc_sendlock
diff --git a/usr/src/uts/common/fs/smbclnt/netsmb/smb_pass.c b/usr/src/uts/common/fs/smbclnt/netsmb/smb_pass.c
index 4079482538..c26d80e48c 100644
--- a/usr/src/uts/common/fs/smbclnt/netsmb/smb_pass.c
+++ b/usr/src/uts/common/fs/smbclnt/netsmb/smb_pass.c
@@ -166,7 +166,7 @@ smb_pkey_init()
void
smb_pkey_fini()
{
- smb_pkey_deluid((uid_t)-1, kcred);
+ (void) smb_pkey_deluid((uid_t)-1, kcred);
avl_destroy(&smb_ptd);
mutex_destroy(&smb_ptd_lock);
}
@@ -187,15 +187,14 @@ smb_pkey_idle()
return ((n) ? EBUSY : 0);
}
-int
-smb_node_delete(smb_passid_t *tmp)
+static void
+smb_pkey_delete(smb_passid_t *tmp)
{
ASSERT(MUTEX_HELD(&smb_ptd_lock));
avl_remove(&smb_ptd, tmp);
strfree(tmp->srvdom);
strfree(tmp->username);
kmem_free(tmp, sizeof (*tmp));
- return (0);
}
@@ -225,7 +224,7 @@ smb_pkey_del(smbioc_pk_t *pk, cred_t *cr)
mutex_enter(&smb_ptd_lock);
if ((cpid = (smb_passid_t *)avl_find(&smb_ptd,
tmp, &where)) != NULL) {
- smb_node_delete(cpid);
+ smb_pkey_delete(cpid);
}
mutex_exit(&smb_ptd_lock);
@@ -259,7 +258,7 @@ smb_pkey_deluid(uid_t ioc_uid, cred_t *cr)
/*
* Delete the node.
*/
- smb_node_delete(tmp);
+ smb_pkey_delete(tmp);
}
}
mutex_exit(&smb_ptd_lock);
@@ -306,7 +305,7 @@ smb_pkey_add(smbioc_pk_t *pk, cred_t *cr)
/* If it already exists, delete it. */
ret = smb_pkey_check(pk, cr);
if (ret == 0) {
- smb_pkey_del(pk, cr);
+ (void) smb_pkey_del(pk, cr);
}
mutex_enter(&smb_ptd_lock);
diff --git a/usr/src/uts/common/fs/smbclnt/netsmb/smb_rq.c b/usr/src/uts/common/fs/smbclnt/netsmb/smb_rq.c
index 0985d58ff4..0ce241b0ce 100644
--- a/usr/src/uts/common/fs/smbclnt/netsmb/smb_rq.c
+++ b/usr/src/uts/common/fs/smbclnt/netsmb/smb_rq.c
@@ -39,6 +39,7 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/time.h>
#include <sys/kmem.h>
#include <sys/proc.h>
#include <sys/lock.h>
@@ -261,17 +262,14 @@ smb_rq_simple_timed(struct smb_rq *rqp, int timeout)
break;
SMBRQ_LOCK(rqp);
if (rqp->sr_share) {
- cv_reltimedwait(&rqp->sr_cond, &(rqp)->sr_lock,
- (hz * SMB_RCNDELAY), TR_CLOCK_TICK);
+ (void) cv_reltimedwait(&rqp->sr_cond, &(rqp)->sr_lock,
+ SEC_TO_TICK(SMB_RCNDELAY), TR_CLOCK_TICK);
} else {
- delay(ddi_get_lbolt() + (hz * SMB_RCNDELAY));
+ delay(SEC_TO_TICK(SMB_RCNDELAY));
}
SMBRQ_UNLOCK(rqp);
rqp->sr_rexmit--;
-#ifdef XXX
- timeout *= 2;
-#endif
}
return (error);
}
@@ -469,8 +467,10 @@ smb_rq_reply(struct smb_rq *rqp)
u_int8_t tb;
int error, rperror = 0;
- if (rqp->sr_timo == SMBNOREPLYWAIT)
- return (smb_iod_removerq(rqp));
+ if (rqp->sr_timo == SMBNOREPLYWAIT) {
+ smb_iod_removerq(rqp);
+ return (0);
+ }
error = smb_iod_waitrq(rqp);
if (error)
@@ -534,10 +534,6 @@ smb_rq_reply(struct smb_rq *rqp)
error = md_get_uint16le(mdp, &rqp->sr_rpuid);
error = md_get_uint16le(mdp, &rqp->sr_rpmid);
- SMBSDEBUG("M:%04x, P:%04x, U:%04x, T:%04x, E: %d:%d\n",
- rqp->sr_rpmid, rqp->sr_rppid, rqp->sr_rpuid, rqp->sr_rptid,
- rqp->sr_errclass, rqp->sr_serror);
-
return ((error) ? error : rperror);
}
@@ -969,7 +965,7 @@ smb_t2_request_int(struct smb_t2rq *t2p)
m = t2p->t2_tdata.mb_top;
if (m) {
md_initm(&mbdata, m); /* do not free it! */
- totdcount = m_fixhdr(m);
+ totdcount = m_fixhdr(m);
if (totdcount > 0xffff)
return (EINVAL);
} else
@@ -1045,12 +1041,14 @@ smb_t2_request_int(struct smb_t2rq *t2p)
smb_rq_bstart(rqp);
if (t2p->t_name) {
/* Put the string and terminating null. */
- smb_put_dmem(mbp, vcp, t2p->t_name, nmlen + 1,
+ error = smb_put_dmem(mbp, vcp, t2p->t_name, nmlen + 1,
SMB_CS_NONE, NULL);
} else {
/* nmsize accounts for padding, char size. */
- mb_put_mem(mbp, NULL, nmsize, MB_MZERO);
+ error = mb_put_mem(mbp, NULL, nmsize, MB_MZERO);
}
+ if (error)
+ goto freerq;
len = mb_fixhdr(mbp);
if (txpcount) {
mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO);
@@ -1153,12 +1151,10 @@ smb_t2_request_int(struct smb_t2rq *t2p)
goto bad;
mdp = &t2p->t2_rdata;
if (mdp->md_top) {
- m_fixhdr(mdp->md_top);
md_initm(mdp, mdp->md_top);
}
mdp = &t2p->t2_rparam;
if (mdp->md_top) {
- m_fixhdr(mdp->md_top);
md_initm(mdp, mdp->md_top);
}
bad:
@@ -1366,12 +1362,10 @@ smb_nt_request_int(struct smb_ntrq *ntp)
goto bad;
mdp = &ntp->nt_rdata;
if (mdp->md_top) {
- m_fixhdr(mdp->md_top);
md_initm(mdp, mdp->md_top);
}
mdp = &ntp->nt_rparam;
if (mdp->md_top) {
- m_fixhdr(mdp->md_top);
md_initm(mdp, mdp->md_top);
}
bad:
@@ -1409,10 +1403,10 @@ smb_t2_request(struct smb_t2rq *t2p)
break;
mutex_enter(&(t2p)->t2_lock);
if (t2p->t2_share) {
- cv_reltimedwait(&t2p->t2_cond, &(t2p)->t2_lock,
- (hz * SMB_RCNDELAY), TR_CLOCK_TICK);
+ (void) cv_reltimedwait(&t2p->t2_cond, &(t2p)->t2_lock,
+ SEC_TO_TICK(SMB_RCNDELAY), TR_CLOCK_TICK);
} else {
- delay(ddi_get_lbolt() + (hz * SMB_RCNDELAY));
+ delay(SEC_TO_TICK(SMB_RCNDELAY));
}
mutex_exit(&(t2p)->t2_lock);
}
@@ -1442,11 +1436,11 @@ smb_nt_request(struct smb_ntrq *ntp)
break;
mutex_enter(&(ntp)->nt_lock);
if (ntp->nt_share) {
- cv_reltimedwait(&ntp->nt_cond, &(ntp)->nt_lock,
- (hz * SMB_RCNDELAY), TR_CLOCK_TICK);
+ (void) cv_reltimedwait(&ntp->nt_cond, &(ntp)->nt_lock,
+ SEC_TO_TICK(SMB_RCNDELAY), TR_CLOCK_TICK);
} else {
- delay(ddi_get_lbolt() + (hz * SMB_RCNDELAY));
+ delay(SEC_TO_TICK(SMB_RCNDELAY));
}
mutex_exit(&(ntp)->nt_lock);
}
diff --git a/usr/src/uts/common/fs/smbclnt/netsmb/smb_sign.c b/usr/src/uts/common/fs/smbclnt/netsmb/smb_sign.c
index 91c450bb23..140d390670 100644
--- a/usr/src/uts/common/fs/smbclnt/netsmb/smb_sign.c
+++ b/usr/src/uts/common/fs/smbclnt/netsmb/smb_sign.c
@@ -189,7 +189,7 @@ smb_compute_MAC(struct smb_vc *vcp, mblk_t *mp,
/*
* Sign a request with HMAC-MD5.
*/
-int
+void
smb_rq_sign(struct smb_rq *rqp)
{
struct smb_vc *vcp = rqp->sr_vc;
@@ -203,7 +203,7 @@ smb_rq_sign(struct smb_rq *rqp)
*/
if (MBLKL(mp) < SMB_HDRLEN) {
if (!pullupmsg(mp, SMB_HDRLEN))
- return (0);
+ return;
}
sigloc = mp->b_rptr + SMBSIGOFF;
@@ -214,7 +214,7 @@ smb_rq_sign(struct smb_rq *rqp)
* This happens with SPNEGO, NTLMSSP, ...
*/
bcopy("BSRSPLY", sigloc, 8);
- return (0);
+ return;
}
/*
@@ -225,9 +225,7 @@ smb_rq_sign(struct smb_rq *rqp)
if (status != CRYPTO_SUCCESS) {
SMBSDEBUG("Crypto error %d", status);
bzero(sigloc, SMBSIGLEN);
- return (ENOTSUP);
}
- return (0);
}
/*
@@ -240,8 +238,7 @@ smb_rq_verify(struct smb_rq *rqp)
mblk_t *mp = rqp->sr_rp.md_top;
uint8_t sigbuf[SMBSIGLEN];
uint8_t *sigloc;
- int status;
- int fudge;
+ int fudge, rsn, status;
/*
* Note vc_mackey and vc_mackeylen gets filled in by
@@ -266,9 +263,11 @@ smb_rq_verify(struct smb_rq *rqp)
}
sigloc = mp->b_rptr + SMBSIGOFF;
- SMBSDEBUG("sr_rseqno = 0x%x\n", rqp->sr_rseqno);
-
- status = smb_compute_MAC(vcp, mp, rqp->sr_rseqno, sigbuf);
+ /*
+ * Compute the expected signature in sigbuf.
+ */
+ rsn = rqp->sr_rseqno;
+ status = smb_compute_MAC(vcp, mp, rsn, sigbuf);
if (status != CRYPTO_SUCCESS) {
SMBSDEBUG("Crypto error %d", status);
/*
@@ -293,10 +292,10 @@ smb_rq_verify(struct smb_rq *rqp)
* of the sequence # has gotten a bit out of sync.
*/
for (fudge = 1; fudge <= nsmb_signing_fudge; fudge++) {
- smb_compute_MAC(vcp, mp, rqp->sr_rseqno + fudge, sigbuf);
+ (void) smb_compute_MAC(vcp, mp, rsn + fudge, sigbuf);
if (bcmp(sigbuf, sigloc, SMBSIGLEN) == 0)
break;
- smb_compute_MAC(vcp, mp, rqp->sr_rseqno - fudge, sigbuf);
+ (void) smb_compute_MAC(vcp, mp, rsn - fudge, sigbuf);
if (bcmp(sigbuf, sigloc, SMBSIGLEN) == 0) {
fudge = -fudge;
break;
@@ -304,7 +303,7 @@ smb_rq_verify(struct smb_rq *rqp)
}
if (fudge <= nsmb_signing_fudge) {
SMBSDEBUG("sr_rseqno=%d, but %d would have worked\n",
- rqp->sr_rseqno, rqp->sr_rseqno + fudge);
+ rsn, rsn + fudge);
}
#endif
return (EBADRPC);
diff --git a/usr/src/uts/common/fs/smbclnt/netsmb/smb_smb.c b/usr/src/uts/common/fs/smbclnt/netsmb/smb_smb.c
index fce18f74ff..5fa43ece4b 100644
--- a/usr/src/uts/common/fs/smbclnt/netsmb/smb_smb.c
+++ b/usr/src/uts/common/fs/smbclnt/netsmb/smb_smb.c
@@ -51,12 +51,7 @@
#include <sys/note.h>
#include <sys/cmn_err.h>
-#ifdef APPLE
-#include <sys/smb_apple.h>
-#include <sys/utfconv.h>
-#else
#include <netsmb/smb_osdep.h>
-#endif
#include <netsmb/smb.h>
#include <netsmb/smb_conn.h>
@@ -84,95 +79,16 @@ int smb_timo_read = 45;
int smb_timo_write = 60; /* was SMBWRTTIMO */
int smb_timo_append = 90;
-/*
- * Debug/test feature to disable NTMLv2.
- * Set this to zero to skip NTLMv2
- */
-int nsmb_enable_ntlmv2 = 1;
-
-static int smb_smb_read(struct smb_share *ssp, u_int16_t fid,
+static int smb_smb_read(struct smb_share *ssp, uint16_t fid,
uint32_t *lenp, uio_t *uiop, smb_cred_t *scred, int timo);
-static int smb_smb_write(struct smb_share *ssp, u_int16_t fid,
+static int smb_smb_write(struct smb_share *ssp, uint16_t fid,
uint32_t *lenp, uio_t *uiop, smb_cred_t *scred, int timo);
-static int smb_smb_readx(struct smb_share *ssp, u_int16_t fid,
+static int smb_smb_readx(struct smb_share *ssp, uint16_t fid,
uint32_t *lenp, uio_t *uiop, smb_cred_t *scred, int timo);
-static int smb_smb_writex(struct smb_share *ssp, u_int16_t fid,
+static int smb_smb_writex(struct smb_share *ssp, uint16_t fid,
uint32_t *lenp, uio_t *uiop, smb_cred_t *scred, int timo);
-struct smb_dialect {
- int d_id;
- const char *d_name;
-};
-
-
-/*
- * Number of seconds between 1970 and 1601 year
- */
-const u_int64_t DIFF1970TO1601 = 11644473600ULL;
-
-void
-smb_time_local2server(struct timespec *tsp, int tzoff, long *seconds)
-{
- /*
- * XXX - what if we connected to the server when it was in
- * daylight savings/summer time and we've subsequently switched
- * to standard time, or vice versa, so that the time zone
- * offset we got from the server is now wrong?
- */
- *seconds = tsp->tv_sec - tzoff * 60;
- /* - tz.tz_minuteswest * 60 - (wall_cmos_clock ? adjkerntz : 0) */
-}
-
-void
-smb_time_server2local(ulong_t seconds, int tzoff, struct timespec *tsp)
-{
- /*
- * XXX - what if we connected to the server when it was in
- * daylight savings/summer time and we've subsequently switched
- * to standard time, or vice versa, so that the time zone
- * offset we got from the server is now wrong?
- */
- tsp->tv_sec = seconds + tzoff * 60;
- /* + tz.tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0); */
- tsp->tv_nsec = 0;
-}
-
-/*
- * Time from server comes as UTC, so no need to use tz
- */
-/*ARGSUSED*/
-void
-smb_time_NT2local(u_int64_t nsec, int tzoff, struct timespec *tsp)
-{
- smb_time_server2local(nsec / 10000000 - DIFF1970TO1601, 0, tsp);
-}
-
-/*ARGSUSED*/
-void
-smb_time_local2NT(struct timespec *tsp, int tzoff, u_int64_t *nsec)
-{
- long seconds;
-
- smb_time_local2server(tsp, 0, &seconds);
- *nsec = (((u_int64_t)(seconds) & ~1) + DIFF1970TO1601) *
- (u_int64_t)10000000;
-}
-
-#if defined(NOICONVSUPPORT) || defined(lint)
-extern int iconv_open(const char *to, const char *from, void **handle);
-extern int iconv_close(void *handle);
-#endif
-
-/*
- * Moved to user space helper:
- * smb_smb_negotiate()
- * smb_smb_ssnsetup()
- * smb_smb_ssnclose()
- * smb_share_typename()
- */
-
-
int
smb_smb_treeconnect(struct smb_share *ssp, struct smb_cred *scred)
{
@@ -208,7 +124,7 @@ smb_smb_treeconnect(struct smb_share *ssp, struct smb_cred *scred)
*/
unc_len = 4 + strlen(vcp->vc_srvname) + strlen(ssp->ss_name);
unc_name = kmem_alloc(unc_len, KM_SLEEP);
- snprintf(unc_name, unc_len, "\\\\%s\\%s",
+ (void) snprintf(unc_name, unc_len, "\\\\%s\\%s",
vcp->vc_srvname, ssp->ss_name);
/*
@@ -274,14 +190,17 @@ smb_smb_treeconnect(struct smb_share *ssp, struct smb_cred *scred)
error = EBADRPC;
goto out;
}
- md_get_uint16le(mdp, NULL); /* AndX cmd */
- md_get_uint16le(mdp, NULL); /* AndX off */
- md_get_uint16le(mdp, &options); /* option bits (DFS, search) */
- md_get_uint16le(mdp, &bcnt); /* byte count */
+ md_get_uint16le(mdp, NULL); /* AndX cmd */
+ md_get_uint16le(mdp, NULL); /* AndX off */
+ md_get_uint16le(mdp, &options); /* option bits (DFS, search) */
+ error = md_get_uint16le(mdp, &bcnt); /* byte count */
+ if (error)
+ goto out;
/*
* Get the returned share type string,
- * i.e. "IPC" or whatever.
+ * i.e. "IPC" or whatever. Don't care
+ * if we get an error reading the type.
*/
tlen = sizeof (ssp->ss_type_ret);
bzero(ssp->ss_type_ret, tlen--);
@@ -476,53 +395,61 @@ smb_smb_readx(struct smb_share *ssp, uint16_t fid, uint32_t *lenp,
smb_rq_wend(rqp);
smb_rq_bstart(rqp);
smb_rq_bend(rqp);
- do {
- if (timo == 0)
- timo = smb_timo_read;
- error = smb_rq_simple_timed(rqp, timo);
- if (error)
- break;
- smb_rq_getreply(rqp, &mdp);
- md_get_uint8(mdp, &wc);
- if (wc != 12) {
- error = EBADRPC;
- break;
- }
- md_get_uint8(mdp, NULL);
- md_get_uint8(mdp, NULL);
- md_get_uint16le(mdp, NULL);
- md_get_uint16le(mdp, NULL);
- md_get_uint16le(mdp, NULL); /* data compaction mode */
- md_get_uint16le(mdp, NULL);
- md_get_uint16le(mdp, &lenlo); /* data len ret. */
- md_get_uint16le(mdp, &doff); /* data offset */
- md_get_uint16le(mdp, &lenhi);
- rlen = (lenhi << 16) | lenlo;
- md_get_mem(mdp, NULL, 4 * 2, MB_MSYSTEM);
- md_get_uint16le(mdp, NULL); /* ByteCount */
- /*
- * Does the data offset indicate padding?
- * Add up the gets above, we have:
- */
- off = SMB_HDRLEN + 3 + (12 * 2); /* =59 */
- if (doff > off) /* pad byte(s)? */
- md_get_mem(mdp, NULL, doff - off, MB_MSYSTEM);
- if (rlen == 0) {
- *lenp = rlen;
- break;
- }
- /* paranoid */
- if (rlen > *lenp) {
- SMBSDEBUG("bad server! rlen %d, len %d\n",
- rlen, *lenp);
- rlen = *lenp;
- }
- error = md_get_uio(mdp, uiop, rlen);
- if (error)
- break;
+
+ if (timo == 0)
+ timo = smb_timo_read;
+ error = smb_rq_simple_timed(rqp, timo);
+ if (error)
+ goto out;
+
+ smb_rq_getreply(rqp, &mdp);
+ error = md_get_uint8(mdp, &wc);
+ if (error)
+ goto out;
+ if (wc != 12) {
+ error = EBADRPC;
+ goto out;
+ }
+ md_get_uint8(mdp, NULL);
+ md_get_uint8(mdp, NULL);
+ md_get_uint16le(mdp, NULL);
+ md_get_uint16le(mdp, NULL);
+ md_get_uint16le(mdp, NULL); /* data compaction mode */
+ md_get_uint16le(mdp, NULL);
+ md_get_uint16le(mdp, &lenlo); /* data len ret. */
+ md_get_uint16le(mdp, &doff); /* data offset */
+ md_get_uint16le(mdp, &lenhi);
+ rlen = (lenhi << 16) | lenlo;
+ md_get_mem(mdp, NULL, 4 * 2, MB_MSYSTEM);
+ error = md_get_uint16le(mdp, NULL); /* ByteCount */
+ if (error)
+ goto out;
+ /*
+ * Does the data offset indicate padding?
+ * The current offset is a constant, found
+ * by counting the md_get_ calls above.
+ */
+ off = SMB_HDRLEN + 3 + (12 * 2); /* =59 */
+ if (doff > off) /* pad byte(s)? */
+ md_get_mem(mdp, NULL, doff - off, MB_MSYSTEM);
+ if (rlen == 0) {
*lenp = rlen;
- /*LINTED*/
- } while (0);
+ goto out;
+ }
+ /* paranoid */
+ if (rlen > *lenp) {
+ SMBSDEBUG("bad server! rlen %d, len %d\n",
+ rlen, *lenp);
+ rlen = *lenp;
+ }
+ error = md_get_uio(mdp, uiop, rlen);
+ if (error)
+ goto out;
+
+ /* Success */
+ *lenp = rlen;
+
+out:
smb_rq_done(rqp);
return (error);
}
@@ -563,34 +490,39 @@ smb_smb_writex(struct smb_share *ssp, uint16_t fid, uint32_t *lenp,
mb_put_uint32le(mbp, offhi); /* offset (high part) */
smb_rq_wend(rqp);
smb_rq_bstart(rqp);
- do {
- mb_put_uint8(mbp, 0); /* pad byte */
- error = mb_put_uio(mbp, uiop, *lenp);
- if (error)
- break;
- smb_rq_bend(rqp);
- if (timo == 0)
- timo = smb_timo_write;
- error = smb_rq_simple_timed(rqp, timo);
- if (error)
- break;
- smb_rq_getreply(rqp, &mdp);
- md_get_uint8(mdp, &wc);
- if (wc != 6) {
- error = EBADRPC;
- break;
- }
- md_get_uint8(mdp, NULL); /* andx cmd */
- md_get_uint8(mdp, NULL); /* reserved */
- md_get_uint16le(mdp, NULL); /* andx offset */
- md_get_uint16le(mdp, &lenlo); /* data len ret. */
- md_get_uint16le(mdp, NULL); /* remaining */
- md_get_uint16le(mdp, &lenhi);
- rlen = (lenhi << 16) | lenlo;
- *lenp = rlen;
- /*LINTED*/
- } while (0);
+ mb_put_uint8(mbp, 0); /* pad byte */
+ error = mb_put_uio(mbp, uiop, *lenp);
+ if (error)
+ goto out;
+ smb_rq_bend(rqp);
+ if (timo == 0)
+ timo = smb_timo_write;
+ error = smb_rq_simple_timed(rqp, timo);
+ if (error)
+ goto out;
+ smb_rq_getreply(rqp, &mdp);
+ error = md_get_uint8(mdp, &wc);
+ if (error)
+ goto out;
+ if (wc != 6) {
+ error = EBADRPC;
+ goto out;
+ }
+ md_get_uint8(mdp, NULL); /* andx cmd */
+ md_get_uint8(mdp, NULL); /* reserved */
+ md_get_uint16le(mdp, NULL); /* andx offset */
+ md_get_uint16le(mdp, &lenlo); /* data len ret. */
+ md_get_uint16le(mdp, NULL); /* remaining */
+ error = md_get_uint16le(mdp, &lenhi);
+ if (error)
+ goto out;
+
+ /* Success */
+ rlen = (lenhi << 16) | lenlo;
+ *lenp = rlen;
+
+out:
smb_rq_done(rqp);
return (error);
}
@@ -626,44 +558,50 @@ smb_smb_read(struct smb_share *ssp, uint16_t fid, uint32_t *lenp,
smb_rq_wend(rqp);
smb_rq_bstart(rqp);
smb_rq_bend(rqp);
- do {
- if (timo == 0)
- timo = smb_timo_read;
- error = smb_rq_simple_timed(rqp, timo);
- if (error)
- break;
- smb_rq_getreply(rqp, &mdp);
- md_get_uint8(mdp, &wc);
- if (wc != 5) {
- error = EBADRPC;
- break;
- }
- md_get_uint16le(mdp, &rcnt); /* ret. count */
- md_get_mem(mdp, NULL, 4 * 2, MB_MSYSTEM); /* res. */
- md_get_uint16le(mdp, &bc); /* byte count */
- md_get_uint8(mdp, NULL); /* buffer format */
- md_get_uint16le(mdp, &dlen); /* data len */
- if (dlen < rcnt) {
- SMBSDEBUG("oops: dlen=%d rcnt=%d\n",
- (int)dlen, (int)rcnt);
- rcnt = dlen;
- }
- if (rcnt == 0) {
- *lenp = 0;
- break;
- }
- /* paranoid */
- if (rcnt > cnt) {
- SMBSDEBUG("bad server! rcnt %d, cnt %d\n",
- (int)rcnt, (int)cnt);
- rcnt = cnt;
- }
- error = md_get_uio(mdp, uiop, (int)rcnt);
- if (error)
- break;
- *lenp = (int)rcnt;
- /*LINTED*/
- } while (0);
+
+ if (timo == 0)
+ timo = smb_timo_read;
+ error = smb_rq_simple_timed(rqp, timo);
+ if (error)
+ goto out;
+ smb_rq_getreply(rqp, &mdp);
+ error = md_get_uint8(mdp, &wc);
+ if (error)
+ goto out;
+ if (wc != 5) {
+ error = EBADRPC;
+ goto out;
+ }
+ md_get_uint16le(mdp, &rcnt); /* ret. count */
+ md_get_mem(mdp, NULL, 4 * 2, MB_MSYSTEM); /* res. */
+ md_get_uint16le(mdp, &bc); /* byte count */
+ md_get_uint8(mdp, NULL); /* buffer format */
+ error = md_get_uint16le(mdp, &dlen); /* data len */
+ if (error)
+ goto out;
+ if (dlen < rcnt) {
+ SMBSDEBUG("oops: dlen=%d rcnt=%d\n",
+ (int)dlen, (int)rcnt);
+ rcnt = dlen;
+ }
+ if (rcnt == 0) {
+ *lenp = 0;
+ goto out;
+ }
+ /* paranoid */
+ if (rcnt > cnt) {
+ SMBSDEBUG("bad server! rcnt %d, cnt %d\n",
+ (int)rcnt, (int)cnt);
+ rcnt = cnt;
+ }
+ error = md_get_uio(mdp, uiop, (int)rcnt);
+ if (error)
+ goto out;
+
+ /* success */
+ *lenp = (int)rcnt;
+
+out:
smb_rq_done(rqp);
return (error);
}
@@ -700,26 +638,30 @@ smb_smb_write(struct smb_share *ssp, uint16_t fid, uint32_t *lenp,
smb_rq_bstart(rqp);
mb_put_uint8(mbp, SMB_DT_DATA);
mb_put_uint16le(mbp, cnt);
- do {
- error = mb_put_uio(mbp, uiop, *lenp);
- if (error)
- break;
- smb_rq_bend(rqp);
- if (timo == 0)
- timo = smb_timo_write;
- error = smb_rq_simple_timed(rqp, timo);
- if (error)
- break;
- smb_rq_getreply(rqp, &mdp);
- md_get_uint8(mdp, &wc);
- if (wc != 1) {
- error = EBADRPC;
- break;
- }
- md_get_uint16le(mdp, &rcnt);
- *lenp = rcnt;
- /*LINTED*/
- } while (0);
+
+ error = mb_put_uio(mbp, uiop, *lenp);
+ if (error)
+ goto out;
+ smb_rq_bend(rqp);
+ if (timo == 0)
+ timo = smb_timo_write;
+ error = smb_rq_simple_timed(rqp, timo);
+ if (error)
+ goto out;
+ smb_rq_getreply(rqp, &mdp);
+ error = md_get_uint8(mdp, &wc);
+ if (error)
+ goto out;
+ if (wc != 1) {
+ error = EBADRPC;
+ goto out;
+ }
+ error = md_get_uint16le(mdp, &rcnt);
+ if (error)
+ goto out;
+ *lenp = rcnt;
+
+out:
smb_rq_done(rqp);
return (error);
}
diff --git a/usr/src/uts/common/fs/smbclnt/netsmb/smb_subr.h b/usr/src/uts/common/fs/smbclnt/netsmb/smb_subr.h
index 3edf4c4d9d..675fa62b8d 100644
--- a/usr/src/uts/common/fs/smbclnt/netsmb/smb_subr.h
+++ b/usr/src/uts/common/fs/smbclnt/netsmb/smb_subr.h
@@ -122,7 +122,7 @@ struct sockaddr *smb_dup_sockaddr(struct sockaddr *sa);
void smb_free_sockaddr(struct sockaddr *sa);
int smb_toupper(const char *, char *, size_t);
-int smb_rq_sign(struct smb_rq *);
+void smb_rq_sign(struct smb_rq *);
int smb_rq_verify(struct smb_rq *);
int smb_calcv2mackey(struct smb_vc *, const uchar_t *,
const uchar_t *, size_t);
@@ -130,4 +130,16 @@ int smb_calcmackey(struct smb_vc *, const uchar_t *,
const uchar_t *, size_t);
void smb_crypto_mech_init(void);
+void smb_time_init(void);
+void smb_time_fini(void);
+
+void smb_time_local2server(struct timespec *tsp, int tzoff, long *seconds);
+void smb_time_server2local(ulong_t seconds, int tzoff, struct timespec *tsp);
+void smb_time_NT2local(uint64_t nsec, struct timespec *tsp);
+void smb_time_local2NT(struct timespec *tsp, uint64_t *nsec);
+void smb_time_unix2dos(struct timespec *tsp, int tzoff, uint16_t *ddp,
+ uint16_t *dtp, uint8_t *dhp);
+void smb_dos2unixtime(uint_t dd, uint_t dt, uint_t dh, int tzoff,
+ struct timespec *tsp);
+
#endif /* !_NETSMB_SMB_SUBR_H_ */
diff --git a/usr/src/uts/common/fs/smbclnt/netsmb/smb_subrs.c b/usr/src/uts/common/fs/smbclnt/netsmb/smb_subrs.c
index 98963b5583..bfacaaa55d 100644
--- a/usr/src/uts/common/fs/smbclnt/netsmb/smb_subrs.c
+++ b/usr/src/uts/common/fs/smbclnt/netsmb/smb_subrs.c
@@ -134,7 +134,7 @@ smb_errmsg(int cel, const char *func_name, const char *fmt, ...)
* Don't bother to log these, but just
* fire a dtrace probe with the message.
*/
- vsnprintf(buf, sizeof (buf), fmt, adx);
+ (void) vsnprintf(buf, sizeof (buf), fmt, adx);
DTRACE_PROBE2(debugmsg2,
(char *), func_name,
(char *), buf);
@@ -144,7 +144,7 @@ smb_errmsg(int cel, const char *func_name, const char *fmt, ...)
* Add a prefix to the fmt string,
* then let vcmn_err do the args.
*/
- snprintf(buf, sizeof (buf), "?%s: %s", func_name, fmt);
+ (void) snprintf(buf, sizeof (buf), "?%s: %s", func_name, fmt);
DTRACE_PROBE3(debugmsg3,
(char *), func_name,
(char *), buf,
@@ -186,19 +186,22 @@ m_dumpm(mblk_t *m)
#define ECOMM EIO
#endif
#ifndef ENOMEDIUM
-#define ENOMEDIUM EIO
+#define ENOMEDIUM ENXIO
#endif
#ifndef ETIME
#define ETIME ETIMEDOUT
#endif
-static struct {
- unsigned nterr;
- unsigned errno;
+static const struct {
+ unsigned int nterr;
+ unsigned int errno;
} nt2errno[] = {
+ /* Alphabetical order. */
{NT_STATUS_ACCESS_DENIED, EACCES},
{NT_STATUS_ACCESS_VIOLATION, EACCES},
{NT_STATUS_ACCOUNT_DISABLED, EACCES},
+ {NT_STATUS_ACCOUNT_EXPIRED, EACCES},
+ {NT_STATUS_ACCOUNT_LOCKED_OUT, EACCES},
{NT_STATUS_ACCOUNT_RESTRICTION, EACCES},
{NT_STATUS_ADDRESS_ALREADY_EXISTS, EADDRINUSE},
{NT_STATUS_BAD_NETWORK_NAME, ENOENT},
@@ -209,6 +212,7 @@ static struct {
{NT_STATUS_CONNECTION_DISCONNECTED, ECONNABORTED},
{NT_STATUS_CONNECTION_REFUSED, ECONNREFUSED},
{NT_STATUS_CONNECTION_RESET, ENETRESET},
+ {NT_STATUS_DELETE_PENDING, EACCES},
{NT_STATUS_DEVICE_DOES_NOT_EXIST, ENODEV},
{NT_STATUS_DEVICE_PROTOCOL_ERROR, EPROTO},
{NT_STATUS_DIRECTORY_NOT_EMPTY, ENOTEMPTY},
@@ -216,13 +220,16 @@ static struct {
{NT_STATUS_DLL_NOT_FOUND, ELIBACC},
{NT_STATUS_END_OF_FILE, ENODATA},
{NT_STATUS_FILE_IS_A_DIRECTORY, EISDIR},
+ {NT_STATUS_FILE_LOCK_CONFLICT, EAGAIN},
{NT_STATUS_FLOAT_INEXACT_RESULT, ERANGE},
{NT_STATUS_FLOAT_OVERFLOW, ERANGE},
{NT_STATUS_FLOAT_UNDERFLOW, ERANGE},
{NT_STATUS_HOST_UNREACHABLE, EHOSTUNREACH},
{NT_STATUS_ILL_FORMED_PASSWORD, EACCES},
{NT_STATUS_INTEGER_OVERFLOW, ERANGE},
+ {NT_STATUS_INVALID_ACCOUNT_NAME, EACCES},
{NT_STATUS_INVALID_HANDLE, EBADF},
+ {NT_STATUS_INVALID_LEVEL, ENOTSUP},
{NT_STATUS_INVALID_LOGON_HOURS, EACCES},
{NT_STATUS_INVALID_PARAMETER, EINVAL},
{NT_STATUS_INVALID_PIPE_STATE, EPIPE},
@@ -232,6 +239,8 @@ static struct {
{NT_STATUS_IP_ADDRESS_CONFLICT1, ENOTUNIQ},
{NT_STATUS_IP_ADDRESS_CONFLICT2, ENOTUNIQ},
{NT_STATUS_LICENSE_QUOTA_EXCEEDED, EDQUOT},
+ {NT_STATUS_LOCK_NOT_GRANTED, EAGAIN},
+ {NT_STATUS_LOGIN_TIME_RESTRICTION, EACCES},
{NT_STATUS_LOGON_FAILURE, EACCES},
{NT_STATUS_MEDIA_WRITE_PROTECTED, EROFS},
{NT_STATUS_MEMORY_NOT_ALLOCATED, EFAULT},
@@ -241,6 +250,7 @@ static struct {
{NT_STATUS_NETWORK_UNREACHABLE, ENETUNREACH},
{NT_STATUS_NET_WRITE_FAULT, ECOMM},
{NT_STATUS_NONEXISTENT_SECTOR, ESPIPE},
+ {NT_STATUS_NONE_MAPPED, EINVAL},
{NT_STATUS_NOT_A_DIRECTORY, ENOTDIR},
{NT_STATUS_NOT_IMPLEMENTED, ENOSYS},
{NT_STATUS_NOT_MAPPED_VIEW, EINVAL},
@@ -251,11 +261,13 @@ static struct {
{NT_STATUS_NO_SUCH_DEVICE, ENODEV},
{NT_STATUS_NO_SUCH_FILE, ENOENT},
{NT_STATUS_OBJECT_NAME_COLLISION, EEXIST},
- {NT_STATUS_OBJECT_NAME_NOT_FOUND, ENOENT},
{NT_STATUS_OBJECT_NAME_INVALID, EINVAL},
+ {NT_STATUS_OBJECT_NAME_NOT_FOUND, ENOENT},
{NT_STATUS_OBJECT_PATH_INVALID, ENOTDIR},
+ {NT_STATUS_OBJECT_PATH_NOT_FOUND, ENOENT},
{NT_STATUS_PAGEFILE_QUOTA, EDQUOT},
{NT_STATUS_PASSWORD_EXPIRED, EACCES},
+ {NT_STATUS_PASSWORD_MUST_CHANGE, EACCES},
{NT_STATUS_PASSWORD_RESTRICTION, EACCES},
{NT_STATUS_PATH_NOT_COVERED, ENOENT},
{NT_STATUS_PIPE_BROKEN, EPIPE},
@@ -268,6 +280,7 @@ static struct {
{NT_STATUS_PORT_UNREACHABLE, EHOSTUNREACH},
{NT_STATUS_PROTOCOL_UNREACHABLE, ENOPROTOOPT},
{NT_STATUS_QUOTA_EXCEEDED, EDQUOT},
+ {NT_STATUS_RANGE_NOT_LOCKED, EIO},
{NT_STATUS_REGISTRY_QUOTA_LIMIT, EDQUOT},
{NT_STATUS_REMOTE_DISCONNECT, ESHUTDOWN},
{NT_STATUS_REMOTE_NOT_LISTENING, ECONNREFUSED},
@@ -283,10 +296,10 @@ static struct {
{0, 0}
};
-static struct {
- unsigned dclass;
- unsigned derr;
- unsigned nterr;
+static const struct {
+ unsigned short dclass;
+ unsigned short derr;
+ unsigned int nterr;
} nt2doserr[] = {
{ERRDOS, ERRgeneral, NT_STATUS_UNSUCCESSFUL},
{ERRDOS, ERRbadfunc, NT_STATUS_NOT_IMPLEMENTED},
@@ -614,7 +627,7 @@ static struct {
{ERRHRD, ERRgeneral, NT_STATUS_APP_INIT_FAILURE},
{ERRHRD, ERRgeneral, NT_STATUS_PAGEFILE_CREATE_FAILED},
{ERRHRD, ERRgeneral, NT_STATUS_NO_PAGEFILE},
- {ERRDOS, 124, NT_STATUS_INVALID_LEVEL},
+ {ERRDOS, ERRunknownlevel, NT_STATUS_INVALID_LEVEL},
{ERRDOS, 86, NT_STATUS_WRONG_PASSWORD_CORE},
{ERRHRD, ERRgeneral, NT_STATUS_ILLEGAL_FLOAT_CONTEXT},
{ERRDOS, 109, NT_STATUS_PIPE_BROKEN},
@@ -652,7 +665,8 @@ static struct {
{ERRHRD, ERRgeneral, NT_STATUS_DISK_RESET_FAILED},
{ERRHRD, ERRgeneral, NT_STATUS_SHARED_IRQ_BUSY},
{ERRHRD, ERRgeneral, NT_STATUS_FT_ORPHANING},
- {ERRHRD, ERRgeneral, NT_STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT},
+ {ERRHRD, ERRgeneral,
+ NT_STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT},
{ERRHRD, ERRgeneral, NT_STATUS_16F},
{ERRHRD, ERRgeneral, NT_STATUS_170},
{ERRHRD, ERRgeneral, NT_STATUS_171},
@@ -695,7 +709,7 @@ static struct {
{ERRHRD, ERRgeneral, NT_STATUS_REMOTE_SESSION_LIMIT},
{ERRHRD, ERRgeneral, NT_STATUS_EVENTLOG_FILE_CHANGED},
{ERRDOS, ERRnoaccess,
- NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT},
+ NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT},
{ERRDOS, ERRnoaccess,
NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT},
{ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT},
@@ -853,12 +867,13 @@ smb_maperror(int eclass, int eno)
switch (eclass) {
case ERRDOS:
switch (eno) {
+ case ERRunknownlevel:
+ return (ENOTSUP);
case ERRbadfunc:
case ERRbadenv:
case ERRbadformat:
case ERRremcd:
case ERRrmuns:
- case ERRunknownlevel:
return (EINVAL);
case ERRbadfile:
case ERRbadpath:
@@ -910,7 +925,7 @@ smb_maperror(int eclass, int eno)
case ERRnofiles:
return (0); /* eeof ? */
case ERRlock:
- return (EDEADLK);
+ return (EAGAIN);
case ERRfilexists:
return (EEXIST);
case ERRinvalidname: /* samba maps as noent */
@@ -937,9 +952,7 @@ smb_maperror(int eclass, int eno)
case ERRinvnid:
return (ENETRESET);
case ERRinvnetname:
- SMBERROR("NetBIOS name is invalid: %d\n",
- ERRinvnetname);
- return (EAUTH);
+ return (ENXIO);
case ERRbadtype: /* reserved and returned */
return (EIO);
case ERRacctexpired: /* NT: account exists but disabled */
@@ -957,7 +970,7 @@ smb_maperror(int eclass, int eno)
case ERRbadshare:
return (ETXTBSY);
case ERRlock:
- return (EDEADLK);
+ return (EAGAIN);
case ERRdiskfull:
return (EFBIG);
case ERRnotready:
diff --git a/usr/src/uts/common/fs/smbclnt/netsmb/smb_time.c b/usr/src/uts/common/fs/smbclnt/netsmb/smb_time.c
new file mode 100644
index 0000000000..e984ded911
--- /dev/null
+++ b/usr/src/uts/common/fs/smbclnt/netsmb/smb_time.c
@@ -0,0 +1,353 @@
+/*
+ * Copyright (c) 2000-2001, Boris Popov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Boris Popov.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: smbfs_subr.c,v 1.18 2005/02/02 00:22:23 lindak Exp $
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Time conversion functions (to/from DOS, NT times)
+ * From BSD/Darwin smbfs_subr.c
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/time.h>
+#include <sys/vnode.h>
+#include <sys/sunddi.h>
+
+#include <netsmb/smb_osdep.h>
+
+#include <netsmb/smb.h>
+#include <netsmb/smb_conn.h>
+#include <netsmb/smb_subr.h>
+
+/*
+ * Time & date conversion routines taken from msdosfs. Although leap
+ * year calculation is bogus, it's sufficient before 2100 :)
+ */
+/*
+ * This is the format of the contents of the deTime field in the direntry
+ * structure.
+ * We don't use bitfields because we don't know how compilers for
+ * arbitrary machines will lay them out.
+ */
+#define DT_2SECONDS_MASK 0x1F /* seconds divided by 2 */
+#define DT_2SECONDS_SHIFT 0
+#define DT_MINUTES_MASK 0x7E0 /* minutes */
+#define DT_MINUTES_SHIFT 5
+#define DT_HOURS_MASK 0xF800 /* hours */
+#define DT_HOURS_SHIFT 11
+
+/*
+ * This is the format of the contents of the deDate field in the direntry
+ * structure.
+ */
+#define DD_DAY_MASK 0x1F /* day of month */
+#define DD_DAY_SHIFT 0
+#define DD_MONTH_MASK 0x1E0 /* month */
+#define DD_MONTH_SHIFT 5
+#define DD_YEAR_MASK 0xFE00 /* year - 1980 */
+#define DD_YEAR_SHIFT 9
+/*
+ * Total number of days that have passed for each month in a regular year.
+ */
+static ushort_t regyear[] = {
+ 31, 59, 90, 120, 151, 181,
+ 212, 243, 273, 304, 334, 365
+};
+
+/*
+ * Total number of days that have passed for each month in a leap year.
+ */
+static ushort_t leapyear[] = {
+ 31, 60, 91, 121, 152, 182,
+ 213, 244, 274, 305, 335, 366
+};
+
+/*
+ * Variables used to remember parts of the last time conversion. Maybe we
+ * can avoid a full conversion.
+ */
+static ulong_t lasttime;
+static ulong_t lastday;
+static ushort_t lastddate;
+static ushort_t lastdtime;
+
+/* Lock for the lastxxx variables */
+static kmutex_t lastdt_lock;
+
+/*
+ * Number of seconds between 1970 and 1601 year
+ * (134774 days)
+ */
+const uint64_t DIFF1970TO1601 = 11644473600ULL;
+const uint32_t TEN_MIL = 10000000UL;
+
+/*
+ * Convert NT time (tenths of microseconds since 1601)
+ * to Unix seconds+nanoseconds since 1970. Any time
+ * earlier than 1970 is converted to Unix time zero.
+ * Both are GMT-based (no time zone adjustments).
+ */
+void
+smb_time_NT2local(uint64_t nt_time, struct timespec *tsp)
+{
+ uint64_t nt_sec; /* seconds */
+ uint64_t nt_tus; /* tenths of uSec. */
+
+ /* Optimize time zero. */
+ if (nt_time == 0) {
+ tsp->tv_sec = 0;
+ tsp->tv_nsec = 0;
+ return;
+ }
+
+ nt_sec = nt_time / TEN_MIL;
+ nt_tus = nt_time % TEN_MIL;
+
+ if (nt_sec <= DIFF1970TO1601) {
+ tsp->tv_sec = 0;
+ tsp->tv_nsec = 0;
+ return;
+ }
+ tsp->tv_sec = nt_sec - DIFF1970TO1601;
+ tsp->tv_nsec = nt_tus * 100;
+}
+
+/*
+ * Convert Unix time (seconds+nanoseconds since 1970)
+ * to NT time (tenths of microseconds since 1601).
+ * Exception: Convert time zero (really any time in
+ * the first second of 1970) to NT time zero.
+ * Both are GMT-based (no time zone adjustments).
+ */
+void
+smb_time_local2NT(struct timespec *tsp, uint64_t *nt_time)
+{
+ uint64_t nt_sec; /* seconds */
+ uint64_t nt_tus; /* tenths of uSec. */
+
+ if (tsp->tv_sec == 0) {
+ *nt_time = 0;
+ return;
+ }
+
+ nt_sec = tsp->tv_sec + DIFF1970TO1601;
+ nt_tus = tsp->tv_nsec / 100;
+
+ *nt_time = (uint64_t)nt_sec * TEN_MIL + nt_tus;
+}
+
+/*
+ * Time zone conversion stuff, only used in old dialects.
+ * Don't adjust time zero for either conversion.
+ */
+void
+smb_time_local2server(struct timespec *tsp, int tzoff, long *seconds)
+{
+ if (tsp->tv_sec <= (tzoff * 60))
+ *seconds = 0;
+ else
+ *seconds = tsp->tv_sec - (tzoff * 60);
+}
+
+void
+smb_time_server2local(ulong_t seconds, int tzoff, struct timespec *tsp)
+{
+ if (seconds == 0)
+ tsp->tv_sec = 0;
+ else
+ tsp->tv_sec = seconds + tzoff * 60;
+ tsp->tv_nsec = 0;
+}
+
+/*
+ * Time conversions to/from DOS format, for old dialects.
+ */
+
+void
+smb_time_unix2dos(struct timespec *tsp, int tzoff, u_int16_t *ddp,
+ u_int16_t *dtp, u_int8_t *dhp)
+{
+ long t;
+ ulong_t days, year, month, inc;
+ ushort_t *months;
+
+ mutex_enter(&lastdt_lock);
+
+ /*
+ * If the time from the last conversion is the same as now, then
+ * skip the computations and use the saved result.
+ */
+ smb_time_local2server(tsp, tzoff, &t);
+ t &= ~1;
+ if (lasttime != t) {
+ lasttime = t;
+ if (t < 0) {
+ /*
+ * This is before 1970, so it's before 1980,
+ * and can't be represented as a DOS time.
+ * Just represent it as the DOS epoch.
+ */
+ lastdtime = 0;
+ lastddate = (1 << DD_DAY_SHIFT)
+ + (1 << DD_MONTH_SHIFT)
+ + ((1980 - 1980) << DD_YEAR_SHIFT);
+ } else {
+ lastdtime = (((t / 2) % 30) << DT_2SECONDS_SHIFT)
+ + (((t / 60) % 60) << DT_MINUTES_SHIFT)
+ + (((t / 3600) % 24) << DT_HOURS_SHIFT);
+
+ /*
+ * If the number of days since 1970 is the same as
+ * the last time we did the computation then skip
+ * all this leap year and month stuff.
+ */
+ days = t / (24 * 60 * 60);
+ if (days != lastday) {
+ lastday = days;
+ for (year = 1970; ; year++) {
+ /*
+ * XXX - works in 2000, but won't
+ * work in 2100.
+ */
+ inc = year & 0x03 ? 365 : 366;
+ if (days < inc)
+ break;
+ days -= inc;
+ }
+ /*
+ * XXX - works in 2000, but won't work in 2100.
+ */
+ months = year & 0x03 ? regyear : leapyear;
+ for (month = 0; days >= months[month]; month++)
+ ;
+ if (month > 0)
+ days -= months[month - 1];
+ lastddate = ((days + 1) << DD_DAY_SHIFT)
+ + ((month + 1) << DD_MONTH_SHIFT);
+ /*
+ * Remember DOS's idea of time is relative
+ * to 1980, but UN*X's is relative to 1970.
+ * If somehow we get a time before 1980 then
+ * don't give totally crazy results.
+ */
+ if (year > 1980)
+ lastddate += (year - 1980) <<
+ DD_YEAR_SHIFT;
+ }
+ }
+ }
+ if (dhp)
+ *dhp = (tsp->tv_sec & 1) * 100 + tsp->tv_nsec / 10000000;
+
+ *ddp = lastddate;
+ *dtp = lastdtime;
+
+ mutex_exit(&lastdt_lock);
+}
+
+/*
+ * The number of seconds between Jan 1, 1970 and Jan 1, 1980. In that
+ * interval there were 8 regular years and 2 leap years.
+ */
+#define SECONDSTO1980 (((8 * 365) + (2 * 366)) * (24 * 60 * 60))
+
+static ushort_t lastdosdate;
+static ulong_t lastseconds;
+
+void
+smb_dos2unixtime(uint_t dd, uint_t dt, uint_t dh, int tzoff,
+ struct timespec *tsp)
+{
+ ulong_t seconds;
+ ulong_t month;
+ ulong_t year;
+ ulong_t days;
+ ushort_t *months;
+
+ if (dd == 0) {
+ tsp->tv_sec = 0;
+ tsp->tv_nsec = 0;
+ return;
+ }
+ seconds = (((dt & DT_2SECONDS_MASK) >> DT_2SECONDS_SHIFT) << 1)
+ + ((dt & DT_MINUTES_MASK) >> DT_MINUTES_SHIFT) * 60
+ + ((dt & DT_HOURS_MASK) >> DT_HOURS_SHIFT) * 3600
+ + dh / 100;
+
+ /*
+ * If the year, month, and day from the last conversion are the
+ * same then use the saved value.
+ */
+ mutex_enter(&lastdt_lock);
+ if (lastdosdate != dd) {
+ lastdosdate = (ushort_t)dd;
+ days = 0;
+ year = (dd & DD_YEAR_MASK) >> DD_YEAR_SHIFT;
+ days = year * 365;
+ days += year / 4 + 1; /* add in leap days */
+ /*
+ * XXX - works in 2000, but won't work in 2100.
+ */
+ if ((year & 0x03) == 0)
+ days--; /* if year is a leap year */
+ months = year & 0x03 ? regyear : leapyear;
+ month = (dd & DD_MONTH_MASK) >> DD_MONTH_SHIFT;
+ if (month < 1 || month > 12) {
+ month = 1;
+ }
+ if (month > 1)
+ days += months[month - 2];
+ days += ((dd & DD_DAY_MASK) >> DD_DAY_SHIFT) - 1;
+ lastseconds = (days * 24 * 60 * 60) + SECONDSTO1980;
+ }
+ smb_time_server2local(seconds + lastseconds, tzoff, tsp);
+ tsp->tv_nsec = (dh % 100) * 10000000;
+ mutex_exit(&lastdt_lock);
+}
+
+void
+smb_time_init(void)
+{
+ mutex_init(&lastdt_lock, NULL, MUTEX_DEFAULT, NULL);
+}
+
+void
+smb_time_fini(void)
+{
+ mutex_destroy(&lastdt_lock);
+}
diff --git a/usr/src/uts/common/fs/smbclnt/netsmb/smb_tran.c b/usr/src/uts/common/fs/smbclnt/netsmb/smb_tran.c
index 7a646b48c7..79163f4afe 100644
--- a/usr/src/uts/common/fs/smbclnt/netsmb/smb_tran.c
+++ b/usr/src/uts/common/fs/smbclnt/netsmb/smb_tran.c
@@ -32,7 +32,6 @@
* Selected code from smb_conn.c
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Helper functions for smb_trantcp.c
* (and maybe future transports)
@@ -46,14 +45,8 @@
#include <netinet/in.h>
#include <netinet/tcp.h>
-/* Like smb_dev.h, this knows about all our sockaddr formats. */
-#include <netsmb/netbios.h>
-
-#ifdef APPLE
-#include <sys/smb_apple.h>
-#else
#include <netsmb/smb_osdep.h>
-#endif
+#include <netsmb/netbios.h>
#include <netsmb/smb.h>
#include <netsmb/smb_conn.h>
diff --git a/usr/src/uts/common/fs/smbclnt/netsmb/smb_trantcp.c b/usr/src/uts/common/fs/smbclnt/netsmb/smb_trantcp.c
index 1cd73649c4..566bc27e46 100644
--- a/usr/src/uts/common/fs/smbclnt/netsmb/smb_trantcp.c
+++ b/usr/src/uts/common/fs/smbclnt/netsmb/smb_trantcp.c
@@ -62,12 +62,7 @@
#include <netinet/in.h>
#include <netinet/tcp.h>
-#ifdef APPLE
-#include <sys/smb_apple.h>
-#else
#include <netsmb/smb_osdep.h>
-#endif
-
#include <netsmb/mchain.h>
#include <netsmb/netbios.h>
@@ -201,7 +196,7 @@ discon:
* cleanup and state change on any call.
*/
freemsg(tm);
- nb_disconnect(nbp);
+ (void) nb_disconnect(nbp);
return (ENOTCONN);
}
@@ -261,7 +256,7 @@ nb_snddis(TIUSER *tiptr)
/*
* Stuff the NetBIOS header into space already prepended.
*/
-static int
+static void
nb_sethdr(mblk_t *m, uint8_t type, uint32_t len)
{
uint32_t *p;
@@ -272,7 +267,6 @@ nb_sethdr(mblk_t *m, uint8_t type, uint32_t len)
/*LINTED*/
p = (uint32_t *)m->b_rptr;
*p = htonl(len);
- return (0);
}
/*
@@ -517,9 +511,9 @@ smb_nbst_done(struct smb_vc *vcp)
* But it's harmless.
*/
if (nbp->nbp_flags & NBF_CONNECTED)
- nb_disconnect(nbp);
+ (void) nb_disconnect(nbp);
if (nbp->nbp_tiptr)
- t_kclose(nbp->nbp_tiptr, 0);
+ (void) t_kclose(nbp->nbp_tiptr, 0);
if (nbp->nbp_laddr)
smb_free_sockaddr((struct sockaddr *)nbp->nbp_laddr);
if (nbp->nbp_paddr)
@@ -542,7 +536,7 @@ smb_nbst_loan_fp(struct smb_vc *vcp, struct file *fp, cred_t *cr)
* Un-loan the existing one, if any.
*/
if (nbp->nbp_tiptr != NULL) {
- t_kclose(nbp->nbp_tiptr, 0);
+ (void) t_kclose(nbp->nbp_tiptr, 0);
nbp->nbp_tiptr = NULL;
nbp->nbp_flags &= ~NBF_CONNECTED;
nbp->nbp_state = NBST_CLOSED;
@@ -595,6 +589,7 @@ nb_disconnect(struct nbpcb *nbp)
{
TIUSER *tiptr;
int save_flags;
+ int err = 0;
tiptr = nbp->nbp_tiptr;
if (tiptr == NULL)
@@ -610,12 +605,13 @@ nb_disconnect(struct nbpcb *nbp)
mutex_exit(&nbp->nbp_lock);
if (save_flags & NBF_CONNECTED)
- nb_snddis(tiptr);
+ err = nb_snddis(tiptr);
if (nbp->nbp_state != NBST_RETARGET) {
nbp->nbp_state = NBST_CLOSED;
}
- return (0);
+
+ return (err);
}
/*
diff --git a/usr/src/uts/common/fs/smbclnt/netsmb/smb_usr.c b/usr/src/uts/common/fs/smbclnt/netsmb/smb_usr.c
index 19ef7bdc97..c4843e8578 100644
--- a/usr/src/uts/common/fs/smbclnt/netsmb/smb_usr.c
+++ b/usr/src/uts/common/fs/smbclnt/netsmb/smb_usr.c
@@ -194,7 +194,7 @@ smb_usr_simplerq(smb_dev_t *sdp, intptr_t arg, int flags, cred_t *cr)
ioc->ioc_errclass = rqp->sr_errclass;
ioc->ioc_serror = rqp->sr_serror;
ioc->ioc_error = rqp->sr_error;
- ddi_copyout(ioc, (void *)arg, sizeof (*ioc), flags);
+ (void) ddi_copyout(ioc, (void *)arg, sizeof (*ioc), flags);
out:
if (rqp != NULL)
@@ -310,7 +310,7 @@ smb_usr_t2request(smb_dev_t *sdp, intptr_t arg, int flags, cred_t *cr)
ioc->ioc_error = t2p->t2_sr_error;
ioc->ioc_rpflags2 = t2p->t2_sr_rpflags2;
- ddi_copyout(ioc, (void *)arg, sizeof (*ioc), flags);
+ (void) ddi_copyout(ioc, (void *)arg, sizeof (*ioc), flags);
out:
@@ -404,7 +404,7 @@ smb_usr_rw(smb_dev_t *sdp, int cmd, intptr_t arg, int flags, cred_t *cr)
*/
ioc->ioc_cnt -= auio.uio_resid;
- ddi_copyout(ioc, (void *)arg, sizeof (*ioc), flags);
+ (void) ddi_copyout(ioc, (void *)arg, sizeof (*ioc), flags);
out:
if (ioc != NULL)
@@ -612,7 +612,7 @@ smb_usr_get_tree(smb_dev_t *sdp, int cmd, intptr_t arg, int flags, cred_t *cr)
* the tree connect response, so they can
* see if they got the requested type.
*/
- memcpy(tcon->tc_sh.sh_type_ret,
+ (void) memcpy(tcon->tc_sh.sh_type_ret,
ssp->ss_type_ret, SMBIOC_STYPE_LEN);
/*
diff --git a/usr/src/uts/common/fs/smbclnt/netsmb/subr_mchain.c b/usr/src/uts/common/fs/smbclnt/netsmb/subr_mchain.c
index 525beb671d..ecd2322da7 100644
--- a/usr/src/uts/common/fs/smbclnt/netsmb/subr_mchain.c
+++ b/usr/src/uts/common/fs/smbclnt/netsmb/subr_mchain.c
@@ -48,12 +48,7 @@
#include <sys/sunddi.h>
#include <sys/cmn_err.h>
-#ifdef APPLE
-#include <sys/smb_apple.h>
-#else
#include <netsmb/smb_osdep.h>
-#endif
-
#include <netsmb/mchain.h>
#include <netsmb/smb.h>
@@ -623,7 +618,7 @@ md_done(struct mdchain *mdp)
* Append a new message (separate mbuf chain).
* It is caller responsibility to prevent
* multiple calls to fetch/record routines.
- * XXX: Note (mis)use of mblk->b_next here.
+ * Note unusual use of mblk->b_next here.
*/
void
md_append_record(struct mdchain *mdp, mblk_t *top)
@@ -644,23 +639,31 @@ md_append_record(struct mdchain *mdp, mblk_t *top)
/*
* Advance mdp->md_top to the next message.
- * XXX: Note (mis)use of mblk->b_next here.
+ * Note unusual use of mblk->b_next here.
*/
-int
+void
md_next_record(struct mdchain *mdp)
{
- mblk_t *m;
+ mblk_t *m, *top;
+
+ if ((top = mdp->md_top) == NULL)
+ return;
- if (mdp->md_top == NULL)
- return (ENOENT);
- /* Get to next message (not b_cont chain) */
- m = mdp->md_top->b_next;
- mdp->md_top->b_next = NULL;
+ /*
+ * Get the next message, if any,
+ * stored by md_append_record.
+ * Note: NOT b_cont chain
+ */
+ m = top->b_next;
+ top->b_next = NULL;
+
+ /* Done with old "top". */
md_done(mdp);
if (m == NULL)
- return (ENOENT);
+ return;
+
+ /* Setup new "top". */
md_initm(mdp, m);
- return (0);
}
/*
@@ -961,7 +964,7 @@ m_copym(mblk_t *m, int off, int len, int wait)
if (len < dsz) {
adj = (ssize_t)len - (ssize_t)dsz;
ASSERT(adj < 0);
- adjmsg(n, adj);
+ (void) adjmsg(n, adj);
}
}
diff --git a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs.h b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs.h
index 9eb6cdbed3..68c626094a 100644
--- a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs.h
+++ b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs.h
@@ -50,7 +50,9 @@
#include <sys/param.h>
#include <sys/fstyp.h>
+#include <sys/avl.h>
#include <sys/list.h>
+#include <sys/t_lock.h>
#include <sys/vfs.h>
#include <sys/fs/smbfs_mount.h>
@@ -85,11 +87,14 @@ struct smbnode;
struct smb_share;
/*
- * The values for smi_flags.
+ * The values for smi_flags (from nfs_clnt.h)
*/
-#define SMI_INT 0x01 /* interrupts allowed */
-#define SMI_DEAD 0x02 /* zone shutting down */
+#define SMI_INT 0x04 /* interrupts allowed */
+#define SMI_NOAC 0x10 /* don't cache attributes */
#define SMI_LLOCK 0x80 /* local locking only */
+#define SMI_ACL 0x2000 /* share supports ACLs */
+#define SMI_EXTATTR 0x80000 /* share supports ext. attrs */
+#define SMI_DEAD 0x200000 /* mount has been terminated */
/*
* Stuff returned by smbfs_smb_qfsattr
@@ -118,6 +123,14 @@ typedef struct smbmntinfo {
#define smi_fsattr smi_fsa.fsa_aflags
/*
+ * The smbfs node cache for this mount.
+ * Named "hash" for historical reasons.
+ * See smbfs_node.h for details.
+ */
+ avl_tree_t smi_hash_avl;
+ krwlock_t smi_hash_lk;
+
+ /*
* Kstat statistics
*/
struct kstat *smi_io_kstats;
@@ -131,20 +144,34 @@ typedef struct smbmntinfo {
/* Lock for the list is: smi_globals_t -> smg_lock */
/*
- * Copy of the args from mount.
+ * Stuff copied or derived from the mount args
*/
- struct smbfs_args smi_args;
+ uid_t smi_uid; /* user id */
+ gid_t smi_gid; /* group id */
+ mode_t smi_fmode; /* mode for files */
+ mode_t smi_dmode; /* mode for dirs */
+
+ hrtime_t smi_acregmin; /* min time to hold cached file attr */
+ hrtime_t smi_acregmax; /* max time to hold cached file attr */
+ hrtime_t smi_acdirmin; /* min time to hold cached dir attr */
+ hrtime_t smi_acdirmax; /* max time to hold cached dir attr */
} smbmntinfo_t;
-typedef struct smbfattr {
- int fa_attr;
- len_t fa_size;
- struct timespec fa_atime;
- struct timespec fa_ctime;
- struct timespec fa_mtime;
- ino64_t fa_ino;
- struct timespec fa_reqtime;
-} smbfattr_t;
+/*
+ * Attribute cache timeout defaults (in seconds).
+ */
+#define SMBFS_ACREGMIN 3 /* min secs to hold cached file attr */
+#define SMBFS_ACREGMAX 60 /* max secs to hold cached file attr */
+#define SMBFS_ACDIRMIN 30 /* min secs to hold cached dir attr */
+#define SMBFS_ACDIRMAX 60 /* max secs to hold cached dir attr */
+/* and limits for the mount options */
+#define SMBFS_ACMINMAX 600 /* 10 min. is longest min timeout */
+#define SMBFS_ACMAXMAX 3600 /* 1 hr is longest max timeout */
+
+/*
+ * High-res time is nanoseconds.
+ */
+#define SEC2HR(sec) ((sec) * (hrtime_t)NANOSEC)
/*
* vnode pointer to mount info
diff --git a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_acl.c b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_acl.c
index e50e3b2389..81493f5783 100644
--- a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_acl.c
+++ b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_acl.c
@@ -39,11 +39,11 @@
#include <sys/vfs.h>
#include <sys/byteorder.h>
-#include <netsmb/smb_osdep.h>
+#include <netsmb/mchain.h>
#include <netsmb/smb.h>
#include <netsmb/smb_conn.h>
+#include <netsmb/smb_osdep.h>
#include <netsmb/smb_subr.h>
-#include <netsmb/mchain.h>
#include <smbfs/smbfs.h>
#include <smbfs/smbfs_node.h>
@@ -51,17 +51,15 @@
#include <sys/fs/smbfs_ioctl.h>
#include <fs/fs_subr.h>
+#include "smbfs_ntacl.h"
/* Sanity check SD sizes */
#define MAX_RAW_SD_SIZE 32768
#define SMALL_SD_SIZE 1024
-#undef ACL_SUPPORT /* not yet */
-
-
/*
- * smbfs_getsd(), smbfs_setsd() are common functions used by
- * both ioctl get/set ACL and VOP_GETSECATTR, VOP_SETSECATTR.
+ * smbfs_getsd() is a common function used by both
+ * smbfs_ioctl SMBFSIO_GETSD and VOP_GETSECATTR.
* Handles required rights, tmpopen/tmpclose.
*
* Note: smbfs_getsd allocates and returns an mblk chain,
@@ -119,7 +117,7 @@ again:
cerror = smbfs_smb_tmpclose(np, fid, &scred);
if (cerror)
- SMBERROR("error %d closing file %s\n",
+ SMBVDEBUG("error %d closing file %s\n",
cerror, np->n_rpath);
out:
@@ -174,7 +172,7 @@ smbfs_setsd(vnode_t *vp, uint32_t selector, mblk_t **mp, cred_t *cr)
cerror = smbfs_smb_tmpclose(np, fid, &scred);
if (cerror)
- SMBERROR("error %d closing file %s\n",
+ SMBVDEBUG("error %d closing file %s\n",
cerror, np->n_rpath);
out:
@@ -185,7 +183,7 @@ out:
}
/*
- * Entry points from VOP_IOCTL
+ * Helper for VOP_IOCTL: SMBFSIO_GETSD
*/
int
smbfs_ioc_getsd(vnode_t *vp, intptr_t arg, int flag, cred_t *cr)
@@ -245,6 +243,9 @@ out:
return (error);
}
+/*
+ * Helper for VOP_IOCTL: SMBFSIO_SETSD
+ */
int
smbfs_ioc_setsd(vnode_t *vp, intptr_t arg, int flag, cred_t *cr)
{
@@ -285,62 +286,26 @@ out:
}
-#ifdef ACL_SUPPORT
-/*
- * Conversion functions for VOP_GETSECATTR, VOP_SETSECATTR
- *
- * XXX: We may or may not add conversion code here, or we
- * may add that to usr/src/common (TBD). For now all the
- * ACL conversion code is in libsmbfs.
- */
-
-/*
- * Convert a Windows SD (in the mdchain mdp) into a
- * ZFS-style vsecattr_t and possibly uid, gid.
- */
-/* ARGSUSED */
-static int
-smb_ntsd2vsec(mdchain_t *mdp, vsecattr_t *vsa,
- int *uidp, int *gidp, cred_t *cr)
-{
- /* XXX NOT_YET */
- return (ENOSYS);
-}
-
-/*
- * Convert a ZFS-style vsecattr_t (and possibly uid, gid)
- * into a Windows SD (built in the mbchain mbp).
- */
-/* ARGSUSED */
-static int
-smb_vsec2ntsd(vsecattr_t *vsa, int uid, int gid,
- mbchain_t *mbp, cred_t *cr)
-{
- /* XXX NOT_YET */
- return (ENOSYS);
-}
-#endif /* ACL_SUPPORT */
/*
- * Entry points from VOP_GETSECATTR, VOP_SETSECATTR
- *
- * Disabled the real _getacl functionality for now,
- * because we have no way to return the owner and
- * primary group until we replace our fake uid/gid
- * in getattr with something derived from _getsd.
+ * Helper for VOP_GETSECATTR
+ * Call smbfs_getsd, convert NT to ZFS form.
*/
/* ARGSUSED */
int
smbfs_getacl(vnode_t *vp, vsecattr_t *vsa,
- int *uidp, int *gidp, int flag, cred_t *cr)
+ uid_t *uidp, gid_t *gidp, int flag, cred_t *cr)
{
-#ifdef ACL_SUPPORT
mdchain_t *mdp, md_store;
- mblk_t *m;
+ mblk_t *m = NULL;
+ i_ntsd_t *sd = NULL;
uint32_t selector;
int error;
+ bzero(&md_store, sizeof (md_store));
+ mdp = &md_store;
+
/*
* Which parts of the SD we request.
* XXX: We need a way to let the caller specify
@@ -365,41 +330,51 @@ smbfs_getacl(vnode_t *vp, vsecattr_t *vsa,
*/
error = smbfs_getsd(vp, selector, &m, cr);
if (error)
- return (error);
+ goto out;
+ /* Note: allocated *m */
+ md_initm(mdp, m);
/*
- * Have m. Must free it before return.
+ * Parse the OtW security descriptor,
+ * storing in our internal form.
*/
- mdp = &md_store;
- md_initm(mdp, m);
+ error = md_get_ntsd(mdp, &sd);
+ if (error)
+ goto out;
/*
* Convert the Windows security descriptor to a
* ZFS ACL (and owner ID, primary group ID).
- * This is the difficult part. (todo)
*/
- error = smb_ntsd2vsec(mdp, vsa, uidp, gidp, cr);
+ error = smbfs_acl_sd2zfs(sd, vsa, uidp, gidp);
+out:
+ if (sd != NULL)
+ smbfs_acl_free_sd(sd);
/* Note: m_freem(m) is done by... */
md_done(mdp);
return (error);
-#else /* ACL_SUPPORT */
- return (ENOSYS);
-#endif /* ACL_SUPPORT */
}
+/*
+ * Helper for VOP_SETSECATTR
+ * Convert ZFS to NT form, call smbfs_setsd.
+ */
/* ARGSUSED */
int
smbfs_setacl(vnode_t *vp, vsecattr_t *vsa,
- int uid, int gid, int flag, cred_t *cr)
+ uid_t uid, gid_t gid, int flag, cred_t *cr)
{
-#ifdef ACL_SUPPORT
mbchain_t *mbp, mb_store;
+ i_ntsd_t *sd = NULL;
uint32_t selector;
int error;
+ bzero(&mb_store, sizeof (mb_store));
+ mbp = &mb_store;
+
/*
* Which parts of the SD we'll modify.
* Ditto comments above re. SACL
@@ -407,25 +382,27 @@ smbfs_setacl(vnode_t *vp, vsecattr_t *vsa,
selector = 0;
if (vsa)
selector |= DACL_SECURITY_INFORMATION;
- if (uid != -1)
+ if (uid != (uid_t)-1)
selector |= OWNER_SECURITY_INFORMATION;
- if (gid != -1)
+ if (gid != (gid_t)-1)
selector |= GROUP_SECURITY_INFORMATION;
if (selector == 0)
return (0);
/*
- * Setup buffer for SD data.
+ * Convert a ZFS ACL (and owner ID, group ID)
+ * into an NT SD, internal form.
*/
- mbp = &mb_store;
- mb_init(mbp);
+ error = smbfs_acl_zfs2sd(vsa, uid, gid, &sd);
+ if (error)
+ goto out;
/*
- * Convert a ZFS ACL (and owner ID, group ID)
- * to a Windows security descriptor.
- * This is the difficult part. (todo)
+ * Marshall the internal form SD into an
+ * OtW security descriptor.
*/
- error = smb_vsec2ntsd(vsa, uid, gid, mbp, cr);
+ mb_init(mbp);
+ error = mb_put_ntsd(mbp, sd);
if (error)
goto out;
@@ -436,9 +413,8 @@ smbfs_setacl(vnode_t *vp, vsecattr_t *vsa,
error = smbfs_setsd(vp, selector, &mbp->mb_top, cr);
out:
+ if (sd != NULL)
+ smbfs_acl_free_sd(sd);
mb_done(mbp);
return (error);
-#else /* ACL_SUPPORT */
- return (ENOSYS);
-#endif /* ACL_SUPPORT */
}
diff --git a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_client.c b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_client.c
index fc089d4c33..c6d23011fe 100644
--- a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_client.c
+++ b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_client.c
@@ -40,7 +40,6 @@
#include <sys/cred.h>
#include <sys/kmem.h>
#include <sys/debug.h>
-#include <sys/dnlc.h>
#include <sys/vmsystm.h>
#include <sys/flock.h>
#include <sys/share.h>
@@ -54,7 +53,9 @@
#include <sys/list.h>
#include <sys/zone.h>
+#include <netsmb/smb.h>
#include <netsmb/smb_conn.h>
+#include <netsmb/smb_subr.h>
#include <smbfs/smbfs.h>
#include <smbfs/smbfs_node.h>
@@ -68,6 +69,10 @@
#include <vm/seg_map.h>
#include <vm/seg_vn.h>
+static int smbfs_getattr_cache(vnode_t *, struct smbfattr *);
+static int smbfattr_to_vattr(vnode_t *, struct smbfattr *,
+ struct vattr *);
+
/*
* The following code provide zone support in order to perform an action
* for each smbfs mount in a zone. This is also where we would add
@@ -84,6 +89,437 @@ typedef struct smi_globals smi_globals_t;
static zone_key_t smi_list_key;
+/*
+ * Attributes caching:
+ *
+ * Attributes are cached in the smbnode in struct vattr form.
+ * There is a time associated with the cached attributes (r_attrtime)
+ * which tells whether the attributes are valid. The time is initialized
+ * to the difference between current time and the modify time of the vnode
+ * when new attributes are cached. This allows the attributes for
+ * files that have changed recently to be timed out sooner than for files
+ * that have not changed for a long time. There are minimum and maximum
+ * timeout values that can be set per mount point.
+ */
+
+/*
+ * Validate caches by checking cached attributes. If they have timed out
+ * get the attributes from the server and compare mtimes. If mtimes are
+ * different purge all caches for this vnode.
+ */
+int
+smbfs_validate_caches(
+ struct vnode *vp,
+ cred_t *cr)
+{
+ struct vattr va;
+
+ va.va_mask = AT_SIZE;
+ return (smbfsgetattr(vp, &va, cr));
+}
+
+/*
+ * Purge all of the various data caches.
+ */
+/*ARGSUSED*/
+void
+smbfs_purge_caches(struct vnode *vp)
+{
+#if 0 /* not yet: mmap support */
+ /*
+ * NFS: Purge the DNLC for this vp,
+ * Clear any readdir state bits,
+ * the readlink response cache, ...
+ */
+ smbnode_t *np = VTOSMB(vp);
+
+ /*
+ * Flush the page cache.
+ */
+ if (vn_has_cached_data(vp)) {
+ (void) VOP_PUTPAGE(vp, (u_offset_t)0, 0, B_INVAL, cr, NULL);
+ }
+#endif /* not yet */
+}
+
+/*
+ * Check the attribute cache to see if the new attributes match
+ * those cached. If they do, the various `data' caches are
+ * considered to be good. Otherwise, purge the cached data.
+ */
+void
+smbfs_cache_check(
+ struct vnode *vp,
+ struct smbfattr *fap)
+{
+ smbnode_t *np;
+ int purge_data = 0;
+#if 0 /* not yet: ACL support */
+ int purge_acl = 0;
+ vsecattr_t *vsp = NULL;
+#endif /* not yet */
+
+ np = VTOSMB(vp);
+ mutex_enter(&np->r_statelock);
+
+ /*
+ * Compare with NFS macro: CACHE_VALID
+ * If the mtime or size has changed,
+ * purge cached data.
+ */
+ if (np->r_attr.fa_mtime.tv_sec != fap->fa_mtime.tv_sec ||
+ np->r_attr.fa_mtime.tv_nsec != fap->fa_mtime.tv_nsec)
+ purge_data = 1;
+ if (np->r_attr.fa_size != fap->fa_size)
+ purge_data = 1;
+
+#if 0 /* not yet: ACL support */
+ if (np->r_attr.fa_ctime.tv_sec != fap->fa_ctime.tv_sec ||
+ np->r_attr.fa_ctime.tv_nsec != fap->fa_ctime.tv_nsec)
+ purge_acl = 1;
+#endif /* not yet */
+
+ mutex_exit(&np->r_statelock);
+
+ if (purge_data)
+ smbfs_purge_caches(vp);
+
+#if 0 /* not yet: ACL support */
+ if (purge_acl) {
+ vsecattr_t *vsp;
+
+ if (np->r_secattr != NULL) {
+ mutex_enter(&np->r_statelock);
+ vsp = np->r_secattr;
+ np->r_secattr = NULL;
+ mutex_exit(&np->r_statelock);
+ if (vsp != NULL)
+ smbfs_acl_free(vsp);
+ }
+ }
+#endif /* not yet */
+}
+
+/*
+ * Set attributes cache for given vnode using vnode attributes.
+ * From NFS: nfs_attrcache_va
+ */
+#if 0 /* not yet (not sure if we need this) */
+void
+smbfs_attrcache_va(vnode_t *vp, struct vattr *vap)
+{
+ smbfattr_t fa;
+ smbnode_t *np;
+
+ vattr_to_fattr(vp, vap, &fa);
+ smbfs_attrcache_fa(vp, &fa);
+}
+#endif /* not yet */
+
+/*
+ * Set attributes cache for given vnode using SMB fattr
+ * and update the attribute cache timeout.
+ *
+ * From NFS: nfs_attrcache, nfs_attrcache_va
+ */
+void
+smbfs_attrcache_fa(vnode_t *vp, struct smbfattr *fap)
+{
+ smbnode_t *np;
+ smbmntinfo_t *smi;
+ hrtime_t delta, now;
+ u_offset_t newsize;
+ vtype_t vtype, oldvt;
+ mode_t mode;
+
+ np = VTOSMB(vp);
+ smi = VTOSMI(vp);
+
+ /*
+ * We allow v_type to change, so set that here
+ * (and the mode, which is derived from it).
+ */
+ if (fap->fa_attr & SMB_FA_DIR) {
+ vtype = VDIR;
+ mode = S_IFDIR | smi->smi_dmode;
+ } else {
+ vtype = VREG;
+ mode = S_IFREG | smi->smi_fmode;
+ }
+
+ /*
+ * For now, n_uid/n_gid never change after they are
+ * set by: smbfs_node_findcreate / make_smbnode.
+ * Later, they will change in getsecattr.
+ */
+
+ mutex_enter(&np->r_statelock);
+
+ now = gethrtime();
+
+ /*
+ * Delta is the number of nanoseconds that we will
+ * cache the attributes of the file. It is based on
+ * the number of nanoseconds since the last time that
+ * we detected a change. The assumption is that files
+ * that changed recently are likely to change again.
+ * There is a minimum and a maximum for regular files
+ * and for directories which is enforced though.
+ *
+ * Using the time since last change was detected
+ * eliminates direct comparison or calculation
+ * using mixed client and server times. SMBFS
+ * does not make any assumptions regarding the
+ * client and server clocks being synchronized.
+ */
+ if (fap->fa_mtime.tv_sec != np->r_attr.fa_mtime.tv_sec ||
+ fap->fa_mtime.tv_nsec != np->r_attr.fa_mtime.tv_nsec ||
+ fap->fa_size != np->r_attr.fa_size)
+ np->r_mtime = now;
+
+ if ((smi->smi_flags & SMI_NOAC) || (vp->v_flag & VNOCACHE))
+ delta = 0;
+ else {
+ delta = now - np->r_mtime;
+ if (vtype == VDIR) {
+ if (delta < smi->smi_acdirmin)
+ delta = smi->smi_acdirmin;
+ else if (delta > smi->smi_acdirmax)
+ delta = smi->smi_acdirmax;
+ } else {
+ if (delta < smi->smi_acregmin)
+ delta = smi->smi_acregmin;
+ else if (delta > smi->smi_acregmax)
+ delta = smi->smi_acregmax;
+ }
+ }
+
+ np->r_attrtime = now + delta;
+ np->r_attr = *fap;
+ np->n_mode = mode;
+ oldvt = vp->v_type;
+ vp->v_type = vtype;
+
+ /*
+ * Shall we update r_size? (local notion of size)
+ *
+ * The real criteria for updating r_size should be:
+ * if the file has grown on the server, or if
+ * the client has not modified the file.
+ *
+ * Also deal with the fact that SMB presents
+ * directories as having size=0. Doing that
+ * here and leaving fa_size as returned OtW
+ * avoids fixing the size lots of places.
+ */
+ newsize = fap->fa_size;
+ if (vtype == VDIR && newsize < DEV_BSIZE)
+ newsize = DEV_BSIZE;
+
+ if (np->r_size != newsize) {
+#if 0 /* not yet: mmap support */
+ if (!vn_has_cached_data(vp) || ...)
+ /* XXX: See NFS page cache code. */
+#endif /* not yet */
+ /* OK to set the size. */
+ np->r_size = newsize;
+ }
+
+ /* NFS: np->r_flags &= ~RWRITEATTR; */
+ np->n_flag &= ~NATTRCHANGED;
+
+ mutex_exit(&np->r_statelock);
+
+ if (oldvt != vtype) {
+ SMBVDEBUG("vtype change %d to %d\n", oldvt, vtype);
+ }
+}
+
+/*
+ * Fill in attribute from the cache.
+ *
+ * If valid, copy to *fap and return zero,
+ * otherwise return an error.
+ *
+ * From NFS: nfs_getattr_cache()
+ */
+int
+smbfs_getattr_cache(vnode_t *vp, struct smbfattr *fap)
+{
+ smbnode_t *np;
+ int error;
+
+ np = VTOSMB(vp);
+
+ mutex_enter(&np->r_statelock);
+ if (gethrtime() >= np->r_attrtime) {
+ /* cache expired */
+ error = ENOENT;
+ } else {
+ /* cache is valid */
+ *fap = np->r_attr;
+ error = 0;
+ }
+ mutex_exit(&np->r_statelock);
+
+ return (error);
+}
+
+/*
+ * Get attributes over-the-wire and update attributes cache
+ * if no error occurred in the over-the-wire operation.
+ * Return 0 if successful, otherwise error.
+ * From NFS: nfs_getattr_otw
+ */
+int
+smbfs_getattr_otw(vnode_t *vp, struct smbfattr *fap, cred_t *cr)
+{
+ struct smbnode *np;
+ struct smb_cred scred;
+ int error;
+
+ np = VTOSMB(vp);
+
+ /*
+ * NFS uses the ACL rpc here
+ * (if smi_flags & SMI_ACL)
+ */
+
+ /* Shared lock for (possible) n_fid use. */
+ if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
+ return (EINTR);
+ smb_credinit(&scred, cr);
+
+ bzero(fap, sizeof (*fap));
+ error = smbfs_smb_getfattr(np, fap, &scred);
+
+ smb_credrele(&scred);
+ smbfs_rw_exit(&np->r_lkserlock);
+
+ if (error) {
+ /* NFS had: PURGE_STALE_FH(error, vp, cr) */
+ smbfs_attrcache_remove(np);
+ if (error == ENOENT || error == ENOTDIR) {
+ /*
+ * Getattr failed because the object was
+ * removed or renamed by another client.
+ * Remove any cached attributes under it.
+ */
+ smbfs_attrcache_prune(np);
+ }
+ return (error);
+ }
+
+ /*
+ * NFS: smbfs_cache_fattr(vap, fa, vap, t, cr);
+ * which did: fattr_to_vattr, nfs_attr_cache.
+ * We cache the fattr form, so just do the
+ * cache check and store the attributes.
+ */
+ smbfs_cache_check(vp, fap);
+ smbfs_attrcache_fa(vp, fap);
+
+ return (0);
+}
+
+/*
+ * Return either cached or remote attributes. If get remote attr
+ * use them to check and invalidate caches, then cache the new attributes.
+ *
+ * From NFS: nfsgetattr()
+ */
+int
+smbfsgetattr(vnode_t *vp, struct vattr *vap, cred_t *cr)
+{
+ struct smbfattr fa;
+ int error;
+
+ ASSERT(curproc->p_zone == VTOSMI(vp)->smi_zone);
+
+ /*
+ * If we've got cached attributes, just use them;
+ * otherwise go to the server to get attributes,
+ * which will update the cache in the process.
+ */
+ error = smbfs_getattr_cache(vp, &fa);
+ if (error)
+ error = smbfs_getattr_otw(vp, &fa, cr);
+ if (error)
+ return (error);
+
+ /*
+ * Re. client's view of the file size, see:
+ * smbfs_attrcache_fa, smbfs_getattr_otw
+ */
+
+ error = smbfattr_to_vattr(vp, &fa, vap);
+ return (error);
+}
+
+
+/*
+ * Convert SMB over the wire attributes to vnode form.
+ * Returns 0 for success, error if failed (overflow, etc).
+ * From NFS: nattr_to_vattr()
+ */
+int
+smbfattr_to_vattr(vnode_t *vp, struct smbfattr *fa, struct vattr *vap)
+{
+ struct smbnode *np = VTOSMB(vp);
+
+ vap->va_mask = AT_ALL;
+
+ /*
+ * Take type, mode, uid, gid from the smbfs node,
+ * which has have been updated by _getattr_otw.
+ */
+ vap->va_type = vp->v_type;
+ vap->va_mode = np->n_mode;
+
+ vap->va_uid = np->n_uid;
+ vap->va_gid = np->n_gid;
+
+ vap->va_fsid = vp->v_vfsp->vfs_dev;
+ vap->va_nodeid = np->n_ino;
+ vap->va_nlink = 1;
+
+ /*
+ * Difference from NFS here: We cache attributes as
+ * reported by the server, so r_attr.fa_size is the
+ * server's idea of the file size. This is called
+ * for getattr, so we want to return the client's
+ * idea of the file size. NFS deals with that in
+ * nfsgetattr(), the equivalent of our caller.
+ */
+ vap->va_size = np->r_size;
+
+ /*
+ * Times. Note, already converted from NT to
+ * Unix form (in the unmarshalling code).
+ */
+ vap->va_atime = fa->fa_atime;
+ vap->va_mtime = fa->fa_mtime;
+ vap->va_ctime = fa->fa_ctime;
+
+ /*
+ * rdev, blksize, seq are made up.
+ * va_nblocks is 512 byte blocks.
+ */
+ vap->va_rdev = vp->v_rdev;
+ vap->va_blksize = MAXBSIZE;
+ vap->va_nblocks = (fsblkcnt64_t)btod(np->r_attr.fa_allocsz);
+ vap->va_seq = 0;
+
+ return (0);
+}
+
+
+/*
+ * SMB Client initialization and cleanup.
+ * Much of it is per-zone now.
+ */
+
+
/* ARGSUSED */
static void *
smbfs_zone_init(zoneid_t zoneid)
@@ -127,11 +563,6 @@ again:
*/
VFS_HOLD(smi->smi_vfsp);
- /*
- * purge the DNLC for this filesystem
- */
- (void) dnlc_purge_vfsp(smi->smi_vfsp, 0);
-
mutex_enter(&smi->smi_lock);
smi->smi_flags |= SMI_DEAD;
mutex_exit(&smi->smi_lock);
@@ -252,11 +683,7 @@ smb_fscb_t smbfs_cb = {
int
smbfs_clntinit(void)
{
- int error;
- error = smbfs_subrinit();
- if (error)
- return (error);
zone_key_create(&smi_list_key, smbfs_zone_init, smbfs_zone_shutdown,
smbfs_zone_destroy);
#ifdef NEED_SMBFS_CALLBACKS
@@ -276,5 +703,4 @@ smbfs_clntfini(void)
smb_fscb_set(NULL);
#endif /* NEED_SMBFS_CALLBACKS */
(void) zone_key_delete(smi_list_key);
- smbfs_subrfini();
}
diff --git a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_node.c b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_node.c
index 594dedecc0..6c8eda5a87 100644
--- a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_node.c
+++ b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_node.c
@@ -33,15 +33,14 @@
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/cred.h>
+#include <sys/time.h>
#include <sys/vfs.h>
#include <sys/vnode.h>
#include <sys/kmem.h>
@@ -51,11 +50,7 @@
#include <sys/sysmacros.h>
#include <sys/bitmap.h>
-#ifdef APPLE
-#include <sys/smb_apple.h>
-#else
#include <netsmb/smb_osdep.h>
-#endif
#include <netsmb/smb.h>
#include <netsmb/smb_conn.h>
@@ -65,10 +60,6 @@
#include <smbfs/smbfs_node.h>
#include <smbfs/smbfs_subr.h>
-#if defined(DEBUG) || defined(lint)
-#define SMBFS_NAME_DEBUG
-#endif
-
/*
* Lack of inode numbers leads us to the problem of generating them.
* Partially this problem can be solved by having a dir/file cache
@@ -83,8 +74,8 @@
#define FNV_32_PRIME ((uint32_t)0x01000193UL)
#define FNV1_32_INIT ((uint32_t)33554467UL)
-uint32_t
-smbfs_hash3(uint32_t ival, const char *name, int nmlen)
+static inline uint32_t
+smbfs_hash(uint32_t ival, const char *name, int nmlen)
{
uint32_t v;
@@ -95,166 +86,104 @@ smbfs_hash3(uint32_t ival, const char *name, int nmlen)
return (v);
}
+/*
+ * Compute the hash of the full (remote) path name
+ * using the three parts supplied separately.
+ */
uint32_t
-smbfs_hash(const char *name, int nmlen)
+smbfs_gethash(const char *rpath, int rplen)
{
uint32_t v;
- v = smbfs_hash3(FNV1_32_INIT, name, nmlen);
+ v = smbfs_hash(FNV1_32_INIT, rpath, rplen);
return (v);
}
/*
- * This is basically a hash of the full path name, but
- * computed without having the full path contiguously.
- * The path building logic needs to match what
- * smbfs_fullpath does.
- *
- * Note that smbfs_make_node computes inode numbers by
- * calling smbfs_hash on the full path name. This will
- * compute the same result given the directory path and
- * the last component separately.
+ * Like smbfs_gethash, but optimized a little by
+ * starting with the directory hash.
*/
uint32_t
smbfs_getino(struct smbnode *dnp, const char *name, int nmlen)
{
uint32_t ino;
+ char sep;
/* Start with directory hash */
ino = (uint32_t)dnp->n_ino;
- /*
- * If not the root, hash a slash.
- */
- if (dnp->n_rplen > 1)
- ino = smbfs_hash3(ino, "\\", 1);
+ /* separator (maybe) */
+ sep = SMBFS_DNP_SEP(dnp);
+ if (sep)
+ ino = smbfs_hash(ino, &sep, 1);
/* Now hash this component. */
- ino = smbfs_hash3(ino, name, nmlen);
+ ino = smbfs_hash(ino, name, nmlen);
return (ino);
}
-#define CHAR_FC '\374' /* 0xFC */
-#define CHAR_FE '\376' /* 0xFE */
+/*
+ * Allocate and copy a string of passed length.
+ * The passed length does NOT include the null.
+ */
char *
smbfs_name_alloc(const char *name, int nmlen)
{
char *cp;
- size_t alen;
-#ifdef SMBFS_NAME_DEBUG
- /*
- * Note: The passed length is strlen(name),
- * and does NOT include the terminating nul.
- * Allocated space holds: (in order)
- * (int)strlen
- * char 0xFC (1st marker)
- * copy of string
- * terminating null
- * char 0xFE (2nd marker)
- */
- alen = sizeof (int) + 1 + nmlen + 1 + 1;
- cp = kmem_alloc(alen, KM_SLEEP);
- /*LINTED*/
- *(int *)cp = nmlen;
- cp += sizeof (int);
- cp[0] = CHAR_FC;
- cp++;
- bcopy(name, cp, nmlen);
- cp[nmlen] = 0;
- cp[nmlen + 1] = CHAR_FE;
-#else
- alen = nmlen + 1; /* Passed length does NOT include the nul. */
- cp = kmem_alloc(alen, KM_SLEEP);
+ cp = kmem_alloc(nmlen + 1, KM_SLEEP);
bcopy(name, cp, nmlen);
cp[nmlen] = 0;
-#endif
+
return (cp);
}
/*
- * Note: Passed length does NOT include the nul,
- * the same as with smbfs_name_alloc().
+ * Free string from smbfs_name_alloc(). Again,
+ * the passed length does NOT include the null.
*/
void
smbfs_name_free(const char *name, int nmlen)
{
- size_t alen;
-#ifdef SMBFS_NAME_DEBUG
- int lnmlen;
- char *cp;
-
- /*
- * See comment in smbfs_name_alloc
- * about the layout of this memory.
- */
- alen = sizeof (int) + 1 + nmlen + 1 + 1;
- cp = (char *)name;
- cp--;
- if (*cp != CHAR_FC) {
- debug_enter("smbfs_name_free: name[-1] != 0xFC");
- }
- cp -= sizeof (int);
- /*LINTED*/
- lnmlen = *(int *)cp;
- if (lnmlen != nmlen) {
- debug_enter("smbfs_name_free: name[-5] != nmlen");
- }
- if (name[nmlen + 1] != CHAR_FE) {
- debug_enter("smbfs_name_free: name[nmlen+1] != 0xFE");
- }
- kmem_free(cp, alen);
-#else
- alen = nmlen + 1;
- kmem_free((char *)name, alen);
-#endif
+ kmem_free((char *)name, nmlen + 1);
}
/*
* smbfs_nget()
*
- * NOTES:
- *
- * It would be nice to be able to pass in a flag when the caller is sure
- * that the node does not exist and should just be allocated.
+ * Find or create a node under some directory node.
*/
int
smbfs_nget(vnode_t *dvp, const char *name, int nmlen,
- struct smbfattr *fap, vnode_t **vpp)
+ struct smbfattr *fap, vnode_t **vpp)
{
struct smbnode *dnp = VTOSMB(dvp);
struct smbnode *np;
vnode_t *vp;
char sep;
+ ASSERT(fap != NULL);
*vpp = NULL;
- /* Don't expect "." or ".." here anymore. */
- if ((nmlen == 1 && name[0] == '.') ||
+ /* Don't expect "" or "." or ".." here anymore. */
+ if (nmlen == 0 || (nmlen == 1 && name[0] == '.') ||
(nmlen == 2 && name[0] == '.' && name[1] == '.')) {
- DEBUG_ENTER("smbfs_nget: name is '.' or '..'");
return (EINVAL);
}
-
- /*
- * See the comment near the top of smbfs_xattr.c about
- * the logic for what separators to use where.
- */
- sep = (dnp->n_flag & N_XATTR) ? 0 : '\\';
+ sep = SMBFS_DNP_SEP(dnp);
/* Find or create the node. */
- vp = smbfs_make_node(dvp->v_vfsp,
+ np = smbfs_node_findcreate(dnp->n_mount,
dnp->n_rpath, dnp->n_rplen,
name, nmlen, sep, fap);
/*
- * We always have a vp now, because
- * smbfs_make_node / make_smbnode
- * calls kmem_alloc with KM_SLEEP.
+ * We should have np now, because we passed
+ * fap != NULL to smbfs_node_findcreate.
*/
- ASSERT(vp);
- np = VTOSMB(vp);
+ ASSERT(np != NULL);
+ vp = SMBTOV(np);
/*
* Files in an XATTR dir are also XATTR.
@@ -265,248 +194,57 @@ smbfs_nget(vnode_t *dvp, const char *name, int nmlen,
mutex_exit(&np->r_statelock);
}
-#ifdef NOT_YET
- /* update the attr_cache info if the file is clean */
- if (fap && !(VTOSMB(vp)->n_flag & NFLUSHWIRE))
- smbfs_attr_cacheenter(vp, fap);
- if (dvp && makeentry) {
- /* add entry to DNLC */
- cache_enter(dvp, vp, &cn);
- }
-#endif /* NOT_YET */
-
/* BSD symlink hack removed (smb_symmagic) */
-#ifdef NOT_YET
- smbfs_attr_cacheenter(vp, fap); /* update the attr_cache info */
-#endif /* NOT_YET */
-
*vpp = vp;
return (0);
}
/*
- * routines to maintain vnode attributes cache
- * smbfs_attr_cacheenter: unpack np.i to vnode_vattr structure
- *
- * Note that some SMB servers do not exhibit POSIX behaviour
- * with regard to the mtime on directories. To work around
- * this, we never allow the mtime on a directory to go backwards,
- * and bump it forwards elsewhere to simulate the correct
- * behaviour.
+ * smbfs_attrcache_enter, smbfs_attrcache_lookup replaced by
+ * code more closely resembling NFS. See smbfs_client.c
*/
-void
-smbfs_attr_cacheenter(vnode_t *vp, struct smbfattr *fap)
-{
- struct smbnode *np = VTOSMB(vp);
- int vtype;
- struct timespec ts;
-
- mutex_enter(&np->r_statelock);
-
- vtype = (fap->fa_attr & SMB_FA_DIR) ? VDIR : VREG;
- if (vp->v_type != vtype)
- SMBVDEBUG("vtype change %d to %d\n",
- vp->v_type, vtype);
- vp->v_type = vtype;
-
- if (vtype == VREG) {
- if (np->n_size != fap->fa_size) {
- /*
- * Had Darwin ubc_sync_range call here,
- * invalidating the truncated range.
- * XXX: Solaris equivalent?
- */
- SMBVDEBUG("Update size?\n");
- }
- np->n_size = fap->fa_size;
- } else if (vtype == VDIR) {
- np->n_size = 16384; /* XXX should be a better way ... */
- /*
- * Don't allow mtime to go backwards.
- * Yes this has its flaws. Better ideas are welcome!
- */
- /*CSTYLED*/
- if (timespeccmp(&fap->fa_mtime, &np->n_mtime, <))
- fap->fa_mtime = np->n_mtime;
- } else if (vtype != VLNK)
- goto out;
-
- np->n_atime = fap->fa_atime;
- np->n_ctime = fap->fa_ctime;
- np->n_mtime = fap->fa_mtime;
- np->n_dosattr = fap->fa_attr;
-
- np->n_flag &= ~NATTRCHANGED;
- gethrestime(&ts);
- np->n_attrage = ts.tv_sec;
-
-out:
- mutex_exit(&np->r_statelock);
-}
-
-int
-smbfs_attr_cachelookup(vnode_t *vp, struct vattr *vap)
-{
- struct smbnode *np = VTOSMB(vp);
- struct smbmntinfo *smi = VTOSMI(vp);
- time_t attrtimeo;
- struct timespec ts, *stime;
- mode_t type;
-
- /*
- * Determine attrtimeo. It will be something between SMB_MINATTRTIMO and
- * SMB_MAXATTRTIMO where recently modified files have a short timeout
- * and files that haven't been modified in a long time have a long
- * timeout. This is the same algorithm used by NFS.
- */
- gethrestime(&ts);
- stime = &np->r_mtime;
- attrtimeo = (ts.tv_sec - stime->tv_sec) / 10;
- if (attrtimeo < SMB_MINATTRTIMO) {
- attrtimeo = SMB_MINATTRTIMO;
- } else if (attrtimeo > SMB_MAXATTRTIMO)
- attrtimeo = SMB_MAXATTRTIMO;
- /* has too much time passed? */
- stime = (struct timespec *)&np->r_attrtime;
- if ((ts.tv_sec - stime->tv_sec) > attrtimeo)
- return (ENOENT);
-
- if (!vap)
- return (0);
-
- switch (vp->v_type) {
- case VREG:
- type = S_IFREG;
- break;
- case VLNK:
- type = S_IFLNK;
- break;
- case VDIR:
- type = S_IFDIR;
- break;
- default:
- SMBSDEBUG("unknown vnode_vtype %d\n", vp->v_type);
- return (EINVAL);
- }
-
- mutex_enter(&np->r_statelock);
-
- if (!(np->n_flag & NGOTIDS)) {
- np->n_mode = type;
-#ifdef APPLE
- if (smi->smi_fsattr & FILE_PERSISTENT_ACLS) {
- /* XXX: Can this block? Drop r_statelock? */
- if (!smbfs_getids(np, scredp)) {
- np->n_flag |= NGOTIDS;
- np->n_mode |= ACCESSPERMS; /* 0777 */
- }
- }
-#endif /* APPLE */
- if (!(np->n_flag & NGOTIDS)) {
- np->n_flag |= NGOTIDS;
- np->n_uid = smi->smi_args.uid;
- np->n_gid = smi->smi_args.gid;
- }
- }
-
- if (vap->va_mask & AT_TYPE)
- vap->va_type = vp->v_type;
- if (vap->va_mask & AT_MODE) {
- np->n_mode = 0;
- if (vp->v_type == VDIR)
- np->n_mode |= smi->smi_args.dir_mode;
- else /* symlink and regular file */
- np->n_mode |= smi->smi_args.file_mode;
- vap->va_mode = np->n_mode;
- }
- if (vap->va_mask & AT_SIZE)
- vap->va_size = np->n_size;
- if (vap->va_mask & AT_NODEID)
- vap->va_nodeid = np->n_ino;
- if (vap->va_mask & AT_ATIME)
- vap->va_atime = np->n_atime;
- if (vap->va_mask & AT_CTIME)
- vap->va_ctime = np->n_ctime;
- if (vap->va_mask & AT_MTIME)
- vap->va_mtime = np->n_mtime;
- vap->va_nlink = 1;
- vap->va_uid = np->n_uid;
- vap->va_gid = np->n_gid;
- vap->va_fsid = vp->v_vfsp->vfs_dev;
- vap->va_rdev = 0;
- vap->va_blksize = MAXBSIZE;
- vap->va_nblocks = (fsblkcnt64_t)btod(np->n_size);
- vap->va_seq = 0;
-
- mutex_exit(&np->r_statelock);
-
- return (0);
-}
/*
- * Some SMB servers don't exhibit POSIX behaviour with regard to
- * updating the directory mtime when the directory's contents
- * change.
- *
- * We force the issue here by updating our cached copy of the mtime
- * whenever we perform such an action ourselves, and then mark the
- * cache invalid. Subsequently when the invalidated cache entry is
- * updated, we disallow an update that would move the mtime backwards.
- *
- * This preserves correct or near-correct behaviour with a
- * compliant server, and gives near-correct behaviour with
- * a non-compliant server in the most common case (we are the
- * only client changing the directory).
- *
- * There are also complications if a server's time is ahead
- * of our own. We must 'touch' a directory when it is first
- * created, to ensure that the timestamp starts out sane,
- * however it may have a timestamp well ahead of the 'touch'
- * point which will be returned and cached the first time the
- * directory's attributes are fetched. Subsequently, the
- * directory's mtime will not appear to us to change at all
- * until our local time catches up to the server.
- *
- * Thus, any time a directory is 'touched', the saved timestamp
- * must advance at least far enough forwards to be visible to
- * the stat(2) interface.
- *
- * XXX note that better behaviour with non-compliant servers
- * could be obtained by bumping the mtime forwards when
- * an update for an invalidated entry returns a nonsensical
- * mtime.
+ * Update the local notion of the mtime of some directory.
+ * See comments re. r_mtime in smbfs_node.h
*/
-
void
smbfs_attr_touchdir(struct smbnode *dnp)
{
- struct timespec ts, ta;
mutex_enter(&dnp->r_statelock);
/*
- * XXX - not sure about this...
- * Creep the saved time forwards far enough that
- * layers above the kernel will notice.
- */
- ta.tv_sec = 1;
- ta.tv_nsec = 0;
- timespecadd(&dnp->n_mtime, &ta);
- /*
- * If the current time is later than the updated
- * saved time, apply it instead.
+ * Now that we keep the client's notion of mtime
+ * separately from the server, this is easy.
*/
- gethrestime(&ts);
- /*CSTYLED*/
- if (timespeccmp(&dnp->n_mtime, &ts, <))
- dnp->n_mtime = ts;
+ dnp->r_mtime = gethrtime();
+
/*
* Invalidate the cache, so that we go to the wire
* to check that the server doesn't have a better
* timestamp next time we care.
*/
- smbfs_attr_cacheremove(dnp);
+ smbfs_attrcache_rm_locked(dnp);
mutex_exit(&dnp->r_statelock);
}
+
+void
+smbfs_attrcache_remove(struct smbnode *np)
+{
+ mutex_enter(&np->r_statelock);
+ /* smbfs_attrcache_rm_locked(np); */
+ np->r_attrtime = gethrtime();
+ mutex_exit(&np->r_statelock);
+}
+
+/* See smbfs_node.h */
+#undef smbfs_attrcache_rm_locked
+void
+smbfs_attrcache_rm_locked(struct smbnode *np)
+{
+ ASSERT(MUTEX_HELD(&np->r_statelock));
+ np->r_attrtime = gethrtime();
+}
diff --git a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_node.h b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_node.h
index 08e31e0d4d..a85ceb5f60 100644
--- a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_node.h
+++ b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_node.h
@@ -42,6 +42,7 @@
/*
* Much code copied into here from Sun NFS.
+ * Compare with nfs_clnt.h
*/
#include <sys/avl.h>
@@ -51,6 +52,32 @@
extern "C" {
#endif
+/*
+ * These are the attributes we can get from the server via
+ * SMB commands such as TRANS2_QUERY_FILE_INFORMATION
+ * with info level SMB_QFILEINFO_ALL_INFO, and directory
+ * FindFirst/FindNext info. levels FIND_DIRECTORY_INFO
+ * and FIND_BOTH_DIRECTORY_INFO, etc.
+ *
+ * Values in this struct are always native endian,
+ * and times are converted converted to Unix form.
+ * Note: zero in any of the times means "unknown".
+ *
+ * XXX: Later, move this to nsmb
+ */
+typedef struct smbfattr {
+ timespec_t fa_createtime; /* Note, != ctime */
+ timespec_t fa_atime; /* these 3 are like unix */
+ timespec_t fa_mtime;
+ timespec_t fa_ctime;
+ u_offset_t fa_size; /* EOF position */
+ u_offset_t fa_allocsz; /* Allocated size. */
+ uint32_t fa_attr; /* Ext. file (DOS) attr */
+} smbfattr_t;
+
+/*
+ * Cache whole directories (not yet)
+ */
typedef struct rddir_cache {
lloff_t _cookie; /* cookie used to find this cache entry */
lloff_t _ncookie; /* cookie used to find the next cache entry */
@@ -93,32 +120,59 @@ typedef struct smbfs_rwlock {
} smbfs_rwlock_t;
/*
- * The format of the hash bucket used to lookup smbnodes from a file handle.
+ * The format of the smbfs node header, which contains the
+ * fields used to link nodes in the AVL tree, and those
+ * fields needed by the AVL node comparison functions.
+ * It's a separate struct so we can call avl_find with
+ * this relatively small struct as a stack local.
+ *
+ * The AVL tree is mntinfo.smi_hash_avl,
+ * and its lock is mntinfo.smi_hash_lk.
*/
-typedef struct rhashq {
- struct smbnode *r_hashf;
- struct smbnode *r_hashb;
- krwlock_t r_lock;
-} rhashq_t;
+typedef struct smbfs_node_hdr {
+ /*
+ * Our linkage in the node cache AVL tree.
+ */
+ avl_node_t hdr_avl_node;
+
+ /*
+ * Identity of this node: The full path name,
+ * in server form, relative to the share root.
+ */
+ char *hdr_n_rpath;
+ int hdr_n_rplen;
+} smbfs_node_hdr_t;
/*
- * Remote file information structure.
+ * Below is the SMBFS-specific representation of a "node".
+ * This struct is a mixture of Sun NFS and Darwin code.
+ * Fields starting with "r_" came from NFS struct "rnode"
+ * and fields starting with "n_" came from Darwin, or
+ * were added during the Solaris port. We have avoided
+ * renaming fields so we would not cause excessive
+ * changes in the code using this struct.
+ *
+ * Now using an AVL tree instead of hash lists, but kept the
+ * "hash" in some member names and functions to reduce churn.
+ * One AVL tree per mount replaces the global hash buckets.
+ *
+ * Notes carried over from the NFS code:
*
* The smbnode is the "inode" for remote files. It contains all the
* information necessary to handle remote file on the client side.
*
* Note on file sizes: we keep two file sizes in the smbnode: the size
* according to the client (r_size) and the size according to the server
- * (r_attr.va_size). They can differ because we modify r_size during a
+ * (r_attr.fa_size). They can differ because we modify r_size during a
* write system call (smbfs_rdwr), before the write request goes over the
* wire (before the file is actually modified on the server). If an OTW
* request occurs before the cached data is written to the server the file
- * size returned from the server (r_attr.va_size) may not match r_size.
- * r_size is the one we use, in general. r_attr.va_size is only used to
+ * size returned from the server (r_attr.fa_size) may not match r_size.
+ * r_size is the one we use, in general. r_attr.fa_size is only used to
* determine whether or not our cached data is valid.
*
* Each smbnode has 3 locks associated with it (not including the smbnode
- * hash table and free list locks):
+ * "hash" AVL tree and free list locks):
*
* r_rwlock: Serializes smbfs_write and smbfs_setattr requests
* and allows smbfs_read requests to proceed in parallel.
@@ -133,13 +187,12 @@ typedef struct rhashq {
* time (not accross entire putpage operations,
* for example).
*
- * The following members are protected by the mutex rpfreelist_lock:
+ * The following members are protected by the mutex smbfreelist_lock:
* r_freef
* r_freeb
*
- * The following members are protected by the hash bucket rwlock:
- * r_hashf
- * r_hashb
+ * The following members are protected by the AVL tree rwlock:
+ * r_avl_node (r__hdr.hdr_avl_node)
*
* Note: r_modaddr is only accessed when the r_statelock mutex is held.
* Its value is also controlled via r_rwlock. It is assumed that
@@ -156,99 +209,98 @@ typedef struct rhashq {
* Lock ordering:
* r_rwlock > r_lkserlock > r_statelock
*/
-struct exportinfo; /* defined in smbfs/export.h */
-struct failinfo; /* defined in smbfs/smbfs_clnt.h */
-struct mntinfo; /* defined in smbfs/smbfs_clnt.h */
-
-#ifdef _KERNEL
-/* Bits for smbnode.n_flag */
-#define NFLUSHINPROG 0x00001
-#define NFLUSHWANT 0x00002 /* they should gone ... */
-#define NMODIFIED 0x00004 /* bogus, until async IO implemented */
-#define NREFPARENT 0x00010 /* node holds parent from recycling */
-#define NGOTIDS 0x00020
-#define NRDIRSERIAL 0x00080 /* serialize readdir operation */
-#define NISMAPPED 0x00800
-#define NFLUSHWIRE 0x01000
-#define NATTRCHANGED 0x02000 /* use smbfs_attr_cacheremove at close */
-#define NALLOC 0x04000 /* being created */
-#define NWALLOC 0x08000 /* awaiting creation */
-#define N_XATTR 0x10000 /* extended attribute (dir or file) */
typedef struct smbnode {
- /* from Sun NFS struct rnode (XXX: cleanup needed) */
- /* the hash fields must be first to match the rhashq_t */
- /* Lock for the hash queue is: np->r_hashq->r_lock */
- struct smbnode *r_hashf; /* hash queue forward pointer */
- struct smbnode *r_hashb; /* hash queue back pointer */
- /* Lock for the free list is: smbfreelist_lock */
+ /* Our linkage in the node cache AVL tree (see above). */
+ smbfs_node_hdr_t r__hdr;
+
+ /* short-hand names for r__hdr members */
+#define r_avl_node r__hdr.hdr_avl_node
+#define n_rpath r__hdr.hdr_n_rpath
+#define n_rplen r__hdr.hdr_n_rplen
+
+ smbmntinfo_t *n_mount; /* VFS data */
+ vnode_t *r_vnode; /* associated vnode */
+
+ /*
+ * Linkage in smbfreelist, for reclaiming nodes.
+ * Lock for the free list is: smbfreelist_lock
+ */
struct smbnode *r_freef; /* free list forward pointer */
struct smbnode *r_freeb; /* free list back pointer */
- rhashq_t *r_hashq; /* pointer to the hash bucket */
- vnode_t *r_vnode; /* vnode for remote file */
- smbfs_rwlock_t r_rwlock; /* serializes write/setattr requests */
+
+ smbfs_rwlock_t r_rwlock; /* serialize write/setattr requests */
smbfs_rwlock_t r_lkserlock; /* serialize lock with other ops */
- kmutex_t r_statelock; /* protects (most of) smbnode fields */
- u_offset_t r_nextr; /* next byte read offset (read-ahead) */
+ kmutex_t r_statelock; /* protect (most) smbnode fields */
+
+ /*
+ * File handle, directory search handle,
+ * and reference counts for them, etc.
+ * Lock for these is: r_lkserlock
+ */
+ int n_dirrefs;
+ struct smbfs_fctx *n_dirseq; /* ff context */
+ int n_dirofs; /* last ff offset */
+ int n_fidrefs;
+ uint16_t n_fid; /* file handle */
+ enum vtype n_ovtype; /* vnode type opened */
+ uint32_t n_rights; /* granted rights */
+ int n_vcgenid; /* gereration no. (reconnect) */
+
+ /*
+ * Misc. bookkeeping
+ */
cred_t *r_cred; /* current credentials */
- len_t r_size; /* client's view of file size */
- struct vattr r_attr; /* cached vnode attributes */
- hrtime_t r_attrtime; /* time attributes become invalid */
+ u_offset_t r_nextr; /* next read offset (read-ahead) */
long r_mapcnt; /* count of mmapped pages */
uint_t r_count; /* # of refs not reflect in v_count */
uint_t r_awcount; /* # of outstanding async write */
uint_t r_gcount; /* getattrs waiting to flush pages */
- ushort_t r_flags; /* flags, see below */
- short r_error; /* async write error */
+ uint_t r_flags; /* flags, see below */
+ uint32_t n_flag; /* NXXX flags below */
+ uint_t r_error; /* async write error */
kcondvar_t r_cv; /* condvar for blocked threads */
avl_tree_t r_dir; /* cache of readdir responses */
rddir_cache *r_direof; /* pointer to the EOF entry */
kthread_t *r_serial; /* id of purging thread */
list_t r_indelmap; /* list of delmap callers */
+
/*
- * Members derived from Darwin struct smbnode.
- * Note: n_parent node pointer removed because it
- * caused unwanted "holds" on nodes in our cache.
- * Now keeping just the full remote path instead,
- * in server form, relative to the share root.
+ * Attributes: local, and as last seen on the server.
+ * See notes above re: r_size vs r_attr.fa_size, etc.
*/
- char *n_rpath;
- int n_rplen;
- uint32_t n_flag;
- smbmntinfo_t *n_mount;
- ino64_t n_ino;
- /* Lock for the next 7 is r_lkserlock */
- enum vtype n_ovtype; /* vnode type opened */
- int n_dirrefs;
- struct smbfs_fctx *n_dirseq; /* ff context */
- int n_dirofs; /* last ff offset */
- int n_vcgenid; /* gereration no. (reconnect) */
- int n_fidrefs;
- uint16_t n_fid; /* file handle */
- uint32_t n_rights; /* granted rights */
- /* Lock for the rest is r_statelock */
+ smbfattr_t r_attr; /* attributes from the server */
+ hrtime_t r_attrtime; /* time attributes become invalid */
+ hrtime_t r_mtime; /* client time file last modified */
+ len_t r_size; /* client's view of file size */
+
+ /*
+ * Other attributes, not carried in smbfattr_t
+ */
+ u_longlong_t n_ino;
uid_t n_uid;
gid_t n_gid;
mode_t n_mode;
- timestruc_t r_atime;
- timestruc_t r_ctime;
- timestruc_t r_mtime;
- int n_dosattr;
- /*
- * XXX: Maybe use this instead:
- * #define n_atime r_attr.va_atime
- * etc.
- */
-#define n_size r_size
-#define n_atime r_atime
-#define n_ctime r_ctime
-#define n_mtime r_mtime
-#define n_attrage r_attrtime
} smbnode_t;
-#endif /* _KERNEL */
/*
- * Flags
+ * Flag bits in: smbnode_t .n_flag
+ */
+#define NFLUSHINPROG 0x00001
+#define NFLUSHWANT 0x00002 /* they should gone ... */
+#define NMODIFIED 0x00004 /* bogus, until async IO implemented */
+#define NREFPARENT 0x00010 /* node holds parent from recycling */
+#define NGOTIDS 0x00020
+#define NRDIRSERIAL 0x00080 /* serialize readdir operation */
+#define NISMAPPED 0x00800
+#define NFLUSHWIRE 0x01000
+#define NATTRCHANGED 0x02000 /* kill cached attributes at close */
+#define NALLOC 0x04000 /* being created */
+#define NWALLOC 0x08000 /* awaiting creation */
+#define N_XATTR 0x10000 /* extended attribute (dir or file) */
+
+/*
+ * Flag bits in: smbnode_t .r_flags
*/
#define RREADDIRPLUS 0x1 /* issue a READDIRPLUS instead of READDIR */
#define RDIRTY 0x2 /* dirty pages from write operation */
@@ -258,7 +310,7 @@ typedef struct smbnode {
#define RHAVEVERF 0x20 /* have a write verifier to compare against */
#define RCOMMIT 0x40 /* commit in progress */
#define RCOMMITWAIT 0x80 /* someone is waiting to do a commit */
-#define RHASHED 0x100 /* smbnode is in hash queues */
+#define RHASHED 0x100 /* smbnode is in the "hash" AVL tree */
#define ROUTOFSPACE 0x200 /* an out of space error has happened */
#define RDIRECTIO 0x400 /* bypass the buffer cache */
#define RLOOKUP 0x800 /* a lookup has been performed */
@@ -272,27 +324,12 @@ typedef struct smbnode {
#define VTOSMB(vp) ((smbnode_t *)((vp)->v_data))
#define SMBTOV(np) ((np)->r_vnode)
-/* Attribute cache timeouts in seconds */
-#define SMB_MINATTRTIMO 2
-#define SMB_MAXATTRTIMO 30
-
/*
- * Function definitions.
+ * A macro to compute the separator that should be used for
+ * names under some directory. See smbfs_fullpath().
*/
-struct smb_cred;
-int smbfs_nget(vnode_t *dvp, const char *name, int nmlen,
- struct smbfattr *fap, vnode_t **vpp);
-void smbfs_attr_cacheenter(vnode_t *vp, struct smbfattr *fap);
-int smbfs_attr_cachelookup(vnode_t *vp, struct vattr *va);
-void smbfs_attr_touchdir(struct smbnode *dnp);
-char *smbfs_name_alloc(const char *name, int nmlen);
-void smbfs_name_free(const char *name, int nmlen);
-uint32_t smbfs_hash(const char *name, int nmlen);
-uint32_t smbfs_hash3(uint32_t ival, const char *name, int nmlen);
-uint32_t smbfs_getino(struct smbnode *dnp, const char *name, int nmlen);
-int smb_check_table(struct vfs *vfsp, smbnode_t *srp);
-
-#define smbfs_attr_cacheremove(np) (np)->n_attrage = 0
+#define SMBFS_DNP_SEP(dnp) \
+ (((dnp->n_flag & N_XATTR) == 0 && dnp->n_rplen > 1) ? '\\' : '\0')
#ifdef __cplusplus
}
diff --git a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_smb.c b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_smb.c
index 63c34c26d0..aa27feac67 100644
--- a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_smb.c
+++ b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_smb.c
@@ -44,12 +44,7 @@
#include <sys/sunddi.h>
#include <sys/cmn_err.h>
-#ifdef APPLE
-#include <sys/smb_apple.h>
-#include <sys/utfconv.h>
-#else
#include <netsmb/smb_osdep.h>
-#endif
#include <netsmb/smb.h>
#include <netsmb/smb_conn.h>
@@ -61,38 +56,37 @@
#include <smbfs/smbfs_subr.h>
/*
+ * Jan 1 1980 as 64 bit NT time.
+ * (tenths of microseconds since 1601)
+ */
+const uint64_t NT1980 = 11960035200ULL*10000000ULL;
+
+/*
* Local functions.
* Not static, to aid debugging.
*/
-int smbfs_smb_qfileinfo(struct smbnode *np, struct smbfattr *fap,
- struct smb_cred *scrp, short infolevel);
-int smbfs_smb_qpathinfo(struct smbnode *np, struct smbfattr *fap,
- struct smb_cred *scrp, short infolevel);
int smbfs_smb_query_info(struct smbnode *np, const char *name, int nmlen,
struct smbfattr *fap, struct smb_cred *scrp);
+int smbfs_smb_trans2_query(struct smbnode *np, struct smbfattr *fap,
+ struct smb_cred *scrp, uint16_t infolevel);
int smbfs_smb_statfsLM1(struct smb_share *ssp,
statvfs64_t *sbp, struct smb_cred *scrp);
int smbfs_smb_statfsLM2(struct smb_share *ssp,
statvfs64_t *sbp, struct smb_cred *scrp);
+int smbfs_smb_setfattrNT(struct smbnode *np, int fid,
+ uint32_t attr, struct timespec *mtime, struct timespec *atime,
+ struct smb_cred *scrp);
+
int smbfs_smb_setftime1(struct smbnode *np, uint16_t fid,
struct timespec *mtime, struct timespec *atime,
struct smb_cred *scrp);
-int smbfs_smb_setfattrNT(struct smbnode *np, uint16_t fid,
- uint32_t attr, struct timespec *mtime, struct timespec *atime,
- struct smb_cred *scrp);
int smbfs_smb_setpattr1(struct smbnode *np,
const char *name, int len, uint32_t attr,
struct timespec *mtime, struct smb_cred *scrp);
-int smbfs_smb_setpattr2(struct smbnode *np, uint32_t attr,
- struct timespec *mtime, struct timespec *atime,
- struct smb_cred *scrp);
-int smbfs_smb_setpattrNT(struct smbnode *np, uint32_t attr,
- struct timespec *mtime, struct timespec *atime,
- struct smb_cred *scrp);
/*
@@ -120,6 +114,7 @@ smbfs_smb_lockandx(struct smbnode *np, int op, uint32_t pid,
if (op == SMB_LOCK_SHARED)
ltype |= SMB_LOCKING_ANDX_SHARED_LOCK;
+ /* XXX: if (SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_LARGE_FILES)? */
if (largelock)
ltype |= SMB_LOCKING_ANDX_LARGE_FILES;
error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_LOCKING_ANDX, scrp);
@@ -177,9 +172,13 @@ smbfs_smb_lock(struct smbnode *np, int op, caddr_t id,
* TODO: use LOCK_BYTE_RANGE here.
*/
return (EINVAL);
- else
- return (smbfs_smb_lockandx(np, op, (uint32_t)id, start, len,
- largelock, scrp, timeout));
+
+ /*
+ * XXX: compute largelock via:
+ * (SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_LARGE_FILES)?
+ */
+ return (smbfs_smb_lockandx(np, op, (uint32_t)id, start, len,
+ largelock, scrp, timeout));
}
#endif /* APPLE */
@@ -197,8 +196,7 @@ smbfs_smb_getfattr(
int error;
/*
- * This lock is really only necessary for qfileinfo,
- * but hopefully we use that most of the time.
+ * This lock is necessary for FID-based calls.
* Lock may be writer (via open) or reader.
*/
ASSERT(np->r_lkserlock.count != 0);
@@ -211,35 +209,22 @@ smbfs_smb_getfattr(
return (error);
}
- if (np->n_fidrefs)
- error = smbfs_smb_qfileinfo(np, fap, scrp, 0);
- else
- error = smbfs_smb_qpathinfo(np, fap, scrp, 0);
+ error = smbfs_smb_trans2_query(np, fap, scrp, 0);
+ if (error != EINVAL)
+ return (error);
- if (error == EINVAL) {
- /* fallback */
- error = smbfs_smb_query_info(np, NULL, 0, fap, scrp);
- }
-
- /*
- * Note directory size is not provided by
- * windows servers (they leave it as zero)
- */
- if ((fap->fa_attr & SMB_FA_DIR) &&
- (fap->fa_size < DEV_BSIZE))
- fap->fa_size = DEV_BSIZE;
+ /* fallback */
+ error = smbfs_smb_query_info(np, NULL, 0, fap, scrp);
return (error);
}
-
/*
- * Nearly identical to smbfs_smb_qfileinfo (below).
- * Please keep them in sync.
+ * Common function for QueryFileInfo, QueryPathInfo.
*/
int
-smbfs_smb_qpathinfo(struct smbnode *np, struct smbfattr *fap,
- struct smb_cred *scrp, short infolevel)
+smbfs_smb_trans2_query(struct smbnode *np, struct smbfattr *fap,
+ struct smb_cred *scrp, uint16_t infolevel)
{
struct smb_share *ssp = np->n_mount->smi_share;
struct smb_vc *vcp = SSTOVC(ssp);
@@ -247,139 +232,7 @@ smbfs_smb_qpathinfo(struct smbnode *np, struct smbfattr *fap,
int error, svtz, timesok = 1;
struct mbchain *mbp;
struct mdchain *mdp;
- uint16_t date, time, wattr;
- uint64_t llongint, lsize;
- uint32_t size, dattr;
-
-top:
- error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_QUERY_PATH_INFORMATION,
- scrp, &t2p);
- if (error)
- return (error);
- mbp = &t2p->t2_tparam;
- mb_init(mbp);
- if (!infolevel) {
- if (SMB_DIALECT(vcp) < SMB_DIALECT_NTLM0_12)
- infolevel = SMB_QFILEINFO_STANDARD;
- else
- infolevel = SMB_QFILEINFO_ALL_INFO;
- }
- mb_put_uint16le(mbp, infolevel);
- mb_put_uint32le(mbp, 0);
- /* mb_put_uint8(mbp, SMB_DT_ASCII); specs are wrong */
- error = smbfs_fullpath(mbp, vcp, np, NULL, NULL, '\\');
- if (error) {
- smb_t2_done(t2p);
- return (error);
- }
- t2p->t2_maxpcount = 2;
- t2p->t2_maxdcount = vcp->vc_txmax;
- error = smb_t2_request(t2p);
- if (error) {
- smb_t2_done(t2p);
- /* Invalid info level? Try fallback. */
- if (error == EINVAL &&
- infolevel == SMB_QFILEINFO_ALL_INFO) {
- infolevel = SMB_QFILEINFO_STANDARD;
- goto top;
- }
- return (error);
- }
- mdp = &t2p->t2_rdata;
- svtz = vcp->vc_sopt.sv_tz;
- switch (infolevel) {
- case SMB_QFILEINFO_STANDARD:
- timesok = 0;
- md_get_uint16le(mdp, NULL);
- md_get_uint16le(mdp, NULL); /* creation time */
- md_get_uint16le(mdp, &date);
- md_get_uint16le(mdp, &time); /* access time */
- if (date || time) {
- timesok++;
- smb_dos2unixtime(date, time, 0, svtz, &fap->fa_atime);
- }
- md_get_uint16le(mdp, &date);
- md_get_uint16le(mdp, &time); /* modify time */
- if (date || time) {
- timesok++;
- smb_dos2unixtime(date, time, 0, svtz, &fap->fa_mtime);
- }
- md_get_uint32le(mdp, &size);
- fap->fa_size = size;
- md_get_uint32le(mdp, NULL); /* allocation size */
- md_get_uint16le(mdp, &wattr);
- fap->fa_attr = wattr;
- break;
- case SMB_QFILEINFO_ALL_INFO:
- timesok = 0;
- /* creation time (discard) */
- md_get_uint64le(mdp, NULL);
- /* last access time */
- md_get_uint64le(mdp, &llongint);
- if (llongint) {
- timesok++;
- smb_time_NT2local(llongint, svtz, &fap->fa_atime);
- }
- /* last write time */
- md_get_uint64le(mdp, &llongint);
- if (llongint) {
- timesok++;
- smb_time_NT2local(llongint, svtz, &fap->fa_mtime);
- }
- /* last change time */
- md_get_uint64le(mdp, &llongint);
- if (llongint) {
- timesok++;
- smb_time_NT2local(llongint, svtz, &fap->fa_ctime);
- }
- /* attributes */
- md_get_uint32le(mdp, &dattr);
- fap->fa_attr = dattr;
- /*
- * 4-Byte alignment - discard
- * Specs doesn't talk about this.
- */
- md_get_uint32le(mdp, NULL);
- /* allocation size (discard) */
- md_get_uint64le(mdp, NULL);
- /* File size */
- md_get_uint64le(mdp, &lsize);
- fap->fa_size = lsize;
- break;
- default:
- SMBVDEBUG("unexpected info level %d\n", infolevel);
- error = EINVAL;
- }
- smb_t2_done(t2p);
- /*
- * if all times are zero (observed with FAT on NT4SP6)
- * then fall back to older info level
- */
- if (!timesok) {
- if (infolevel == SMB_QFILEINFO_ALL_INFO) {
- infolevel = SMB_QFILEINFO_STANDARD;
- goto top;
- }
- error = EINVAL;
- }
- return (error);
-}
-
-/*
- * Nearly identical to smbfs_smb_qpathinfo (above).
- * Please keep them in sync.
- */
-int
-smbfs_smb_qfileinfo(struct smbnode *np, struct smbfattr *fap,
- struct smb_cred *scrp, short infolevel)
-{
- struct smb_share *ssp = np->n_mount->smi_share;
- struct smb_vc *vcp = SSTOVC(ssp);
- struct smb_t2rq *t2p;
- int error, svtz, timesok = 1;
- struct mbchain *mbp;
- struct mdchain *mdp;
- uint16_t date, time, wattr;
+ uint16_t cmd, date, time, wattr;
uint64_t llongint, lsize;
uint32_t size, dattr;
@@ -389,16 +242,18 @@ smbfs_smb_qfileinfo(struct smbnode *np, struct smbfattr *fap,
*/
ASSERT(np->r_lkserlock.count != 0);
- /* After reconnect, n_fid is invalid */
- if (np->n_vcgenid != ssp->ss_vcgenid)
- return (ESTALE);
-
- if (np->n_fid == SMB_FID_UNUSED)
- return (EBADF);
+ /*
+ * If we have a valid open FID, use it.
+ */
+ if ((np->n_fidrefs > 0) &&
+ (np->n_fid != SMB_FID_UNUSED) &&
+ (np->n_vcgenid == ssp->ss_vcgenid))
+ cmd = SMB_TRANS2_QUERY_FILE_INFORMATION;
+ else
+ cmd = SMB_TRANS2_QUERY_PATH_INFORMATION;
top:
- error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_QUERY_FILE_INFORMATION,
- scrp, &t2p);
+ error = smb_t2_alloc(SSTOCP(ssp), cmd, scrp, &t2p);
if (error)
return (error);
mbp = &t2p->t2_tparam;
@@ -409,8 +264,22 @@ top:
else
infolevel = SMB_QFILEINFO_ALL_INFO;
}
- mb_put_uint16le(mbp, np->n_fid);
+
+ if (cmd == SMB_TRANS2_QUERY_FILE_INFORMATION)
+ mb_put_uint16le(mbp, np->n_fid);
+
mb_put_uint16le(mbp, infolevel);
+
+ if (cmd == SMB_TRANS2_QUERY_PATH_INFORMATION) {
+ mb_put_uint32le(mbp, 0);
+ /* mb_put_uint8(mbp, SMB_DT_ASCII); specs are wrong */
+ error = smbfs_fullpath(mbp, vcp, np, NULL, NULL, '\\');
+ if (error) {
+ smb_t2_done(t2p);
+ return (error);
+ }
+ }
+
t2p->t2_maxpcount = 2;
t2p->t2_maxdcount = vcp->vc_txmax;
error = smb_t2_request(t2p);
@@ -428,61 +297,63 @@ top:
svtz = vcp->vc_sopt.sv_tz;
switch (infolevel) {
case SMB_QFILEINFO_STANDARD:
- timesok = 0;
- md_get_uint16le(mdp, NULL);
- md_get_uint16le(mdp, NULL); /* creation time */
+ md_get_uint16le(mdp, &date);
+ md_get_uint16le(mdp, &time); /* creation time */
+ smb_dos2unixtime(date, time, 0, svtz, &fap->fa_createtime);
md_get_uint16le(mdp, &date);
md_get_uint16le(mdp, &time); /* access time */
- if (date || time) {
- timesok++;
- smb_dos2unixtime(date, time, 0, svtz, &fap->fa_atime);
- }
+ smb_dos2unixtime(date, time, 0, svtz, &fap->fa_atime);
md_get_uint16le(mdp, &date);
md_get_uint16le(mdp, &time); /* modify time */
- if (date || time) {
- timesok++;
- smb_dos2unixtime(date, time, 0, svtz, &fap->fa_mtime);
- }
- md_get_uint32le(mdp, &size);
+ smb_dos2unixtime(date, time, 0, svtz, &fap->fa_mtime);
+ md_get_uint32le(mdp, &size); /* EOF position */
fap->fa_size = size;
- md_get_uint32le(mdp, NULL); /* allocation size */
- md_get_uint16le(mdp, &wattr);
+ md_get_uint32le(mdp, &size); /* allocation size */
+ fap->fa_allocsz = size;
+ error = md_get_uint16le(mdp, &wattr);
fap->fa_attr = wattr;
+ timesok = 1;
break;
case SMB_QFILEINFO_ALL_INFO:
timesok = 0;
- /* creation time (discard) */
- md_get_uint64le(mdp, NULL);
+ /* creation time */
+ md_get_uint64le(mdp, &llongint);
+ if (llongint)
+ timesok++;
+ smb_time_NT2local(llongint, &fap->fa_createtime);
+
/* last access time */
md_get_uint64le(mdp, &llongint);
- if (llongint) {
+ if (llongint)
timesok++;
- smb_time_NT2local(llongint, svtz, &fap->fa_atime);
- }
+ smb_time_NT2local(llongint, &fap->fa_atime);
+
/* last write time */
md_get_uint64le(mdp, &llongint);
- if (llongint) {
+ if (llongint)
timesok++;
- smb_time_NT2local(llongint, svtz, &fap->fa_mtime);
- }
+ smb_time_NT2local(llongint, &fap->fa_mtime);
+
/* last change time */
md_get_uint64le(mdp, &llongint);
- if (llongint) {
+ if (llongint)
timesok++;
- smb_time_NT2local(llongint, svtz, &fap->fa_ctime);
- }
+ smb_time_NT2local(llongint, &fap->fa_ctime);
+
/* attributes */
md_get_uint32le(mdp, &dattr);
fap->fa_attr = dattr;
+
/*
* 4-Byte alignment - discard
- * Specs doesn't talk about this.
+ * Specs don't talk about this.
*/
md_get_uint32le(mdp, NULL);
- /* allocation size (discard) */
- md_get_uint64le(mdp, NULL);
- /* File size */
+ /* allocation size */
md_get_uint64le(mdp, &lsize);
+ fap->fa_allocsz = lsize;
+ /* File size */
+ error = md_get_uint64le(mdp, &lsize);
fap->fa_size = lsize;
break;
default:
@@ -529,14 +400,15 @@ smbfs_smb_qfsattr(struct smb_share *ssp, struct smb_fs_attr_info *fsa,
t2p->t2_maxpcount = 4;
t2p->t2_maxdcount = 4 * 3 + 512;
error = smb_t2_request(t2p);
- if (error) {
- smb_t2_done(t2p);
- return (error);
- }
+ if (error)
+ goto out;
+
mdp = &t2p->t2_rdata;
md_get_uint32le(mdp, &fsa->fsa_aflags);
md_get_uint32le(mdp, &fsa->fsa_maxname);
- md_get_uint32le(mdp, &nlen); /* fs name length */
+ error = md_get_uint32le(mdp, &nlen); /* fs name length */
+ if (error)
+ goto out;
/*
* Get the FS type name.
@@ -548,7 +420,7 @@ smbfs_smb_qfsattr(struct smb_share *ssp, struct smb_fs_attr_info *fsa,
if (nlen > sizeof (tmpbuf))
nlen = sizeof (tmpbuf);
- md_get_mem(mdp, tmpbuf, nlen, MB_MSYSTEM);
+ error = md_get_mem(mdp, tmpbuf, nlen, MB_MSYSTEM);
tmplen = nlen / 2; /* UCS-2 chars */
outlen = FSTYPSZ - 1;
(void) uconv_u16tou8(tmpbuf, &tmplen,
@@ -557,9 +429,19 @@ smbfs_smb_qfsattr(struct smb_share *ssp, struct smb_fs_attr_info *fsa,
} else {
if (nlen > (FSTYPSZ - 1))
nlen = FSTYPSZ - 1;
- md_get_mem(mdp, fsa->fsa_tname, nlen, MB_MSYSTEM);
+ error = md_get_mem(mdp, fsa->fsa_tname, nlen, MB_MSYSTEM);
+ }
+
+ /*
+ * If fs_name starts with FAT, we can't set dates before 1980
+ */
+ if (0 == strncmp(fsa->fsa_tname, "FAT", 3)) {
+ SMB_SS_LOCK(ssp);
+ ssp->ss_flags |= SMBS_FST_FAT;
+ SMB_SS_UNLOCK(ssp);
}
+out:
smb_t2_done(t2p);
return (0);
}
@@ -600,16 +482,17 @@ smbfs_smb_statfsLM2(struct smb_share *ssp, statvfs64_t *sbp,
t2p->t2_maxpcount = 4;
t2p->t2_maxdcount = 4 * 4 + 2;
error = smb_t2_request(t2p);
- if (error) {
- smb_t2_done(t2p);
- return (error);
- }
+ if (error)
+ goto out;
+
mdp = &t2p->t2_rdata;
md_get_uint32le(mdp, NULL); /* fs id */
md_get_uint32le(mdp, &bpu);
md_get_uint32le(mdp, &units);
md_get_uint32le(mdp, &funits);
- md_get_uint16le(mdp, &bsize);
+ error = md_get_uint16le(mdp, &bsize);
+ if (error)
+ goto out;
s = bsize;
s *= bpu;
t = units;
@@ -638,6 +521,8 @@ smbfs_smb_statfsLM2(struct smb_share *ssp, statvfs64_t *sbp,
sbp->f_bavail = f; /* free blocks avail to non-superuser */
sbp->f_files = (-1); /* total file nodes in file system */
sbp->f_ffree = (-1); /* free file nodes in fs */
+
+out:
smb_t2_done(t2p);
return (0);
}
@@ -661,15 +546,16 @@ smbfs_smb_statfsLM1(struct smb_share *ssp, statvfs64_t *sbp,
smb_rq_bstart(rqp);
smb_rq_bend(rqp);
error = smb_rq_simple(rqp);
- if (error) {
- smb_rq_done(rqp);
- return (error);
- }
+ if (error)
+ goto out;
+
smb_rq_getreply(rqp, &mdp);
md_get_uint16le(mdp, &units);
md_get_uint16le(mdp, &bpu);
md_get_uint16le(mdp, &bsize);
- md_get_uint16le(mdp, &funits);
+ error = md_get_uint16le(mdp, &funits);
+ if (error)
+ goto out;
s = bsize;
s *= bpu;
t = units;
@@ -698,6 +584,8 @@ smbfs_smb_statfsLM1(struct smb_share *ssp, statvfs64_t *sbp,
sbp->f_bavail = f; /* free blocks avail to non-superuser */
sbp->f_files = (-1); /* total file nodes in file system */
sbp->f_ffree = (-1); /* free file nodes in fs */
+
+out:
smb_rq_done(rqp);
return (0);
}
@@ -722,12 +610,10 @@ smbfs_smb_seteof(struct smb_share *ssp, uint16_t fid, uint64_t newsize,
mb_put_uint16le(mbp, SMB_SFILEINFO_END_OF_FILE_INFORMATION);
else
mb_put_uint16le(mbp, SMB_SFILEINFO_END_OF_FILE_INFO);
- mb_put_uint32le(mbp, 0); /* XXX should be 16 not 32(?) */
+ mb_put_uint16le(mbp, 0); /* pad */
mbp = &t2p->t2_tdata;
mb_init(mbp);
mb_put_uint64le(mbp, newsize);
- mb_put_uint32le(mbp, 0); /* padding */
- mb_put_uint16le(mbp, 0);
t2p->t2_maxpcount = 2;
t2p->t2_maxdcount = 0;
error = smb_t2_request(t2p);
@@ -791,7 +677,8 @@ exit:
if (fid) {
cerror = smbfs_smb_tmpclose(tdnp, fid, scrp);
if (cerror)
- SMBERROR("error %d closing fid %d\n", cerror, fid);
+ SMBVDEBUG("error %d closing %s\n",
+ cerror, tdnp->n_rpath);
}
smb_t2_done(t2p);
return (error);
@@ -845,24 +732,17 @@ smbfs_smb_setfsize(struct smbnode *np, uint16_t fid, uint64_t newsize,
struct mbchain *mbp;
int error;
- /*
- * This call knows about 64-bit offsets.
- */
- error = smbfs_smb_seteof(ssp, fid, newsize, scrp);
- if (!error) {
- mutex_enter(&np->r_statelock);
- np->n_flag |= (NFLUSHWIRE | NATTRCHANGED);
- mutex_exit(&np->r_statelock);
- return (0);
- }
-
- /*
- * If we have SMB_CAP_LARGE_FILES, the above
- * should have worked. XXX: Don't fallback?
- * XXX: Or fallback on specific errors?
- */
- if (SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_LARGE_FILES) {
- SMBVDEBUG("Have CAP_LARGE but _seteof error=%d\n", error);
+ if (SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) {
+ /*
+ * This call knows about 64-bit offsets.
+ */
+ error = smbfs_smb_seteof(ssp, fid, newsize, scrp);
+ if (!error) {
+ mutex_enter(&np->r_statelock);
+ np->n_flag |= (NFLUSHWIRE | NATTRCHANGED);
+ mutex_exit(&np->r_statelock);
+ return (0);
+ }
}
/*
@@ -894,6 +774,9 @@ smbfs_smb_setfsize(struct smbnode *np, uint16_t fid, uint64_t newsize,
return (error);
}
+/*
+ * Old method for getting file attributes.
+ */
int
smbfs_smb_query_info(struct smbnode *np, const char *name, int nmlen,
struct smbfattr *fap, struct smb_cred *scrp)
@@ -915,79 +798,39 @@ smbfs_smb_query_info(struct smbnode *np, const char *name, int nmlen,
smb_rq_wend(rqp);
smb_rq_bstart(rqp);
mb_put_uint8(mbp, SMB_DT_ASCII);
- do {
- error = smbfs_fullpath(mbp, SSTOVC(ssp), np,
- name, &nmlen, '\\');
- if (error)
- break;
- smb_rq_bend(rqp);
- error = smb_rq_simple(rqp);
- if (error)
- break;
- smb_rq_getreply(rqp, &mdp);
- if (md_get_uint8(mdp, &wc) != 0 || wc != 10) {
- error = EBADRPC;
- break;
- }
- md_get_uint16le(mdp, &wattr);
- fap->fa_attr = wattr;
- /*
- * Be careful using the time returned here, as
- * with FAT on NT4SP6, at least, the time returned is low
- * 32 bits of 100s of nanoseconds (since 1601) so it rolls
- * over about every seven minutes!
- */
- md_get_uint32le(mdp, &longint); /* specs: secs since 1970 */
- if (longint) /* avoid bogus zero returns */
- smb_time_server2local(longint,
- SSTOVC(ssp)->vc_sopt.sv_tz, &fap->fa_mtime);
- md_get_uint32le(mdp, &longint);
- fap->fa_size = longint;
- /*LINTED*/
- } while (0);
- smb_rq_done(rqp);
- return (error);
-}
-
-int
-smbfs_smb_setpattr(struct smbnode *np, uint32_t attr,
- struct timespec *mtime, struct timespec *atime,
- struct smb_cred *scrp)
-{
- struct smb_share *ssp = np->n_mount->smi_share;
- struct smb_vc *vcp = SSTOVC(ssp);
- int error;
+ error = smbfs_fullpath(mbp, SSTOVC(ssp), np,
+ name, &nmlen, '\\');
+ if (error)
+ goto out;
+ smb_rq_bend(rqp);
+ error = smb_rq_simple(rqp);
+ if (error)
+ goto out;
+ smb_rq_getreply(rqp, &mdp);
+ error = md_get_uint8(mdp, &wc);
+ if (error)
+ goto out;
+ if (wc != 10) {
+ error = EBADRPC;
+ goto out;
+ }
+ md_get_uint16le(mdp, &wattr);
+ fap->fa_attr = wattr;
/*
- * This is the logic that was in smbfs_vnops.c
+ * Be careful using the time returned here, as
+ * with FAT on NT4SP6, at least, the time returned is low
+ * 32 bits of 100s of nanoseconds (since 1601) so it rolls
+ * over about every seven minutes!
*/
- if ((vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) &&
- (vcp->vc_flags & SMBV_NT4) == 0) {
- /*
- * NT4 doesn't understand "NT" style SMBs;
- * for NT4 we use the old SET_PATH_INFO
- * XXX Actually, I think the issue is that
- * NT requires an open handle for this.
- */
- error = smbfs_smb_setpattrNT(np,
- attr, mtime, atime, scrp);
- if (error != EBADRPC)
- return (error);
-
- /* NT4 response, remember */
- SMB_VC_LOCK(vcp);
- vcp->vc_flags |= SMBV_NT4;
- SMB_VC_UNLOCK(vcp);
- }
-
- if (SMB_DIALECT(vcp) >= SMB_DIALECT_LANMAN2_0) {
- error = smbfs_smb_setpattr2(np,
- attr, mtime, atime, scrp);
- } else {
- error = smbfs_smb_setpattr1(np, NULL, 0,
- attr, mtime, scrp);
- }
+ md_get_uint32le(mdp, &longint); /* specs: secs since 1970 */
+ smb_time_server2local(longint,
+ SSTOVC(ssp)->vc_sopt.sv_tz, &fap->fa_mtime);
+ error = md_get_uint32le(mdp, &longint);
+ fap->fa_size = longint;
+out:
+ smb_rq_done(rqp);
return (error);
}
@@ -1021,22 +864,20 @@ smbfs_smb_setpattr1(struct smbnode *np, const char *name, int len,
smb_rq_wend(rqp);
smb_rq_bstart(rqp);
mb_put_uint8(mbp, SMB_DT_ASCII);
- do {
- error = smbfs_fullpath(mbp, SSTOVC(ssp), np, name, &len, '\\');
- if (error)
- break;
- mb_put_uint8(mbp, SMB_DT_ASCII);
- if (SMB_UNICODE_STRINGS(SSTOVC(ssp))) {
- mb_put_padbyte(mbp);
- mb_put_uint8(mbp, 0); /* 1st byte NULL Unicode char */
- }
- mb_put_uint8(mbp, 0);
- smb_rq_bend(rqp);
- error = smb_rq_simple(rqp);
- if (error)
- break;
- /*LINTED*/
- } while (0);
+
+ error = smbfs_fullpath(mbp, SSTOVC(ssp), np, name, &len, '\\');
+ if (error)
+ goto out;
+ mb_put_uint8(mbp, SMB_DT_ASCII);
+ if (SMB_UNICODE_STRINGS(SSTOVC(ssp))) {
+ mb_put_padbyte(mbp);
+ mb_put_uint8(mbp, 0); /* 1st byte NULL Unicode char */
+ }
+ mb_put_uint8(mbp, 0);
+ smb_rq_bend(rqp);
+ error = smb_rq_simple(rqp);
+
+out:
smb_rq_done(rqp);
return (error);
}
@@ -1077,188 +918,41 @@ smbfs_smb_unhideit(struct smbnode *np, const char *name, int len,
}
/*
- * Note, win95 doesn't support this call.
+ * Set file attributes (optionally: DOS attr, atime, mtime)
+ * either by open FID or by path name (FID == -1).
*/
int
-smbfs_smb_setpattr2(struct smbnode *np, uint32_t attr,
- struct timespec *mtime, struct timespec *atime,
- struct smb_cred *scrp)
-{
- struct smb_t2rq *t2p;
- struct smb_share *ssp = np->n_mount->smi_share;
- struct smb_vc *vcp = SSTOVC(ssp);
- struct mbchain *mbp;
- uint16_t date, time;
- int error, tzoff;
-
- error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_SET_PATH_INFORMATION,
- scrp, &t2p);
- if (error)
- return (error);
- mbp = &t2p->t2_tparam;
- mb_init(mbp);
- mb_put_uint16le(mbp, SMB_SFILEINFO_STANDARD);
- mb_put_uint32le(mbp, 0); /* MBZ */
- /* mb_put_uint8(mbp, SMB_DT_ASCII); specs incorrect */
- error = smbfs_fullpath(mbp, vcp, np, NULL, NULL, '\\');
- if (error) {
- smb_t2_done(t2p);
- return (error);
- }
- tzoff = vcp->vc_sopt.sv_tz;
- mbp = &t2p->t2_tdata;
- mb_init(mbp);
- mb_put_uint32le(mbp, 0); /* creation time */
- if (atime)
- smb_time_unix2dos(atime, tzoff, &date, &time, NULL);
- else
- time = date = 0;
- mb_put_uint16le(mbp, date);
- mb_put_uint16le(mbp, time);
- if (mtime)
- smb_time_unix2dos(mtime, tzoff, &date, &time, NULL);
- else
- time = date = 0;
- mb_put_uint16le(mbp, date);
- mb_put_uint16le(mbp, time);
- mb_put_uint32le(mbp, 0); /* file size */
- mb_put_uint32le(mbp, 0); /* allocation unit size */
- mb_put_uint16le(mbp, attr); /* DOS attr */
- mb_put_uint32le(mbp, 0); /* EA size */
- t2p->t2_maxpcount = 5 * 2;
- t2p->t2_maxdcount = vcp->vc_txmax;
- error = smb_t2_request(t2p);
- smb_t2_done(t2p);
- return (error);
-}
-
-/*
- * *BASIC_INFO works with Samba, but Win2K servers say it is an
- * invalid information level on a SET_PATH_INFO. Note Win2K does
- * support *BASIC_INFO on a SET_FILE_INFO, and they support the
- * equivalent *BASIC_INFORMATION on SET_PATH_INFO. Go figure.
- */
-int
-smbfs_smb_setpattrNT(struct smbnode *np, uint32_t attr,
- struct timespec *mtime, struct timespec *atime,
+smbfs_smb_setfattr(
+ struct smbnode *np,
+ int fid,
+ uint32_t attr,
+ struct timespec *mtime,
+ struct timespec *atime,
struct smb_cred *scrp)
{
- struct smb_t2rq *t2p;
struct smb_share *ssp = np->n_mount->smi_share;
struct smb_vc *vcp = SSTOVC(ssp);
- struct mbchain *mbp;
- uint64_t tm;
- int error, tzoff;
- /* 64 bit value for Jan 1 1980 */
- PRIVSYM uint64_t DIFF1980TO1601 = 11960035200ULL*10000000ULL;
-
- error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_SET_PATH_INFORMATION,
- scrp, &t2p);
- if (error)
- return (error);
- mbp = &t2p->t2_tparam;
- mb_init(mbp);
- if (vcp->vc_sopt.sv_caps & SMB_CAP_INFOLEVEL_PASSTHRU)
- mb_put_uint16le(mbp, SMB_SFILEINFO_BASIC_INFORMATION);
- else
- mb_put_uint16le(mbp, SMB_SFILEINFO_BASIC_INFO);
- mb_put_uint32le(mbp, 0); /* MBZ */
- /* mb_put_uint8(mbp, SMB_DT_ASCII); specs incorrect */
- error = smbfs_fullpath(mbp, vcp, np, NULL, NULL, '\\');
- if (error) {
- smb_t2_done(t2p);
- return (error);
- }
- tzoff = vcp->vc_sopt.sv_tz;
+ int error;
- /* do we know it won't support dates < 1980? */
- if (!(ssp->ss_flags & SMBS_1980)) {
- mbp = &t2p->t2_tdata;
- mb_init(mbp);
- mb_put_uint64le(mbp, 0); /* creation time */
- if (atime) {
- smb_time_local2NT(atime, tzoff, &tm);
- } else
- tm = 0;
- mb_put_uint64le(mbp, tm); /* access time */
- if (mtime) {
- smb_time_local2NT(mtime, tzoff, &tm);
- } else
- tm = 0;
- mb_put_uint64le(mbp, tm); /* last write time */
- mb_put_uint64le(mbp, tm); /* change time */
- mb_put_uint32le(mbp, attr); /* attr */
- mb_put_uint32le(mbp, 0); /* undocumented padding */
- t2p->t2_maxpcount = 24;
- t2p->t2_maxdcount = 56;
- error = smb_t2_request(t2p);
- }
/*
- * "invalid argument" error probably means it's a
- * FAT drive that doesn't accept dates earlier
- * than 1980, so adjust dates and retry. If the
- * 1980 flag is on we fell thru the if {} above
+ * Normally can use the trans2 call.
*/
- if ((ssp->ss_flags & SMBS_1980) || (error == EINVAL)) {
- mbp = &t2p->t2_tdata;
- mb_init(mbp);
- mb_put_uint64le(mbp, 0); /* creation time */
- if (atime) {
- smb_time_local2NT(atime, tzoff, &tm);
- if (tm < DIFF1980TO1601)
- tm = DIFF1980TO1601;
- } else
- tm = 0;
- mb_put_uint64le(mbp, tm); /* access time */
- if (mtime) {
- smb_time_local2NT(mtime, tzoff, &tm);
- if (tm < DIFF1980TO1601)
- tm = DIFF1980TO1601;
- } else
- tm = 0;
- mb_put_uint64le(mbp, tm); /* last write time */
- mb_put_uint64le(mbp, tm); /* change time */
- mb_put_uint32le(mbp, attr); /* attr */
- mb_put_uint32le(mbp, 0); /* undocumented padding */
- t2p->t2_maxpcount = 24;
- t2p->t2_maxdcount = 56;
- error = smb_t2_request(t2p);
-
- /* if this worked set flag to do the right thing next time */
- if (!(error)) {
- SMB_SS_LOCK(ssp);
- ssp->ss_flags |= SMBS_1980;
- SMB_SS_UNLOCK(ssp);
- }
+ if (vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) {
+ error = smbfs_smb_setfattrNT(np, fid,
+ attr, mtime, atime, scrp);
+ return (error);
}
- smb_t2_done(t2p);
- return (error);
-}
-
-int
-smbfs_smb_setfattr(struct smbnode *np, uint16_t fid,
- uint32_t attr, struct timespec *mtime,
- struct timespec *atime, struct smb_cred *scrp)
-{
- struct smb_share *ssp = np->n_mount->smi_share;
- struct smb_vc *vcp = SSTOVC(ssp);
- int error;
/*
- * This is the logic that was in smbfs_vnops.c
- * Might not be quite right for older dialects.
- * (XXX: What about the DOS attributes?)
+ * Fall-back for older protocols.
*/
- if (vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS)
- error = smbfs_smb_setfattrNT(np, fid,
- np->n_dosattr, mtime, atime, scrp);
- else if (SMB_DIALECT(vcp) >= SMB_DIALECT_LANMAN1_0)
+ if (SMB_DIALECT(vcp) >= SMB_DIALECT_LANMAN1_0) {
error = smbfs_smb_setftime1(np, fid,
mtime, atime, scrp);
- else
- error = smbfs_smb_setpattr1(np, NULL, 0,
- attr, mtime, scrp);
-
+ return (error);
+ }
+ error = smbfs_smb_setpattr1(np, NULL, 0,
+ attr, mtime, scrp);
return (error);
}
@@ -1282,6 +976,7 @@ smbfs_smb_setftime1(
error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_SET_INFORMATION2, scrp);
if (error)
return (error);
+
tzoff = SSTOVC(ssp)->vc_sopt.sv_tz;
smb_rq_getrequest(rqp, &mbp);
smb_rq_wstart(rqp);
@@ -1310,53 +1005,91 @@ smbfs_smb_setftime1(
}
/*
- * Set DOS file attributes.
+ * Set DOS file attributes, either via open FID or by path name.
* Looks like this call can be used only if CAP_NT_SMBS bit is on.
+ *
+ * When setting via path (fid == -1):
+ * *BASIC_INFO works with Samba, but Win2K servers say it is an
+ * invalid information level on a SET_PATH_INFO. Note Win2K does
+ * support *BASIC_INFO on a SET_FILE_INFO, and they support the
+ * equivalent *BASIC_INFORMATION on SET_PATH_INFO. Go figure.
*/
int
-smbfs_smb_setfattrNT(struct smbnode *np, uint16_t fid,
- uint32_t attr, struct timespec *mtime,
- struct timespec *atime, struct smb_cred *scrp)
+smbfs_smb_setfattrNT(
+ struct smbnode *np,
+ int fid, /* if fid == -1, set by path */
+ uint32_t attr,
+ struct timespec *mtime,
+ struct timespec *atime,
+ struct smb_cred *scrp)
{
struct smb_t2rq *t2p;
struct smb_share *ssp = np->n_mount->smi_share;
struct smb_vc *vcp = SSTOVC(ssp);
struct mbchain *mbp;
uint64_t tm;
- int error, svtz;
+ int error;
+ uint16_t cmd, level;
- error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_SET_FILE_INFORMATION,
- scrp, &t2p);
+ if (fid == -1) {
+ cmd = SMB_TRANS2_SET_PATH_INFORMATION;
+ } else {
+ if (fid > UINT16_MAX)
+ return (EINVAL);
+ cmd = SMB_TRANS2_SET_FILE_INFORMATION;
+ }
+ if (vcp->vc_sopt.sv_caps & SMB_CAP_INFOLEVEL_PASSTHRU)
+ level = SMB_SFILEINFO_BASIC_INFORMATION;
+ else
+ level = SMB_SFILEINFO_BASIC_INFO;
+
+ error = smb_t2_alloc(SSTOCP(ssp), cmd, scrp, &t2p);
if (error)
return (error);
- svtz = SSTOVC(ssp)->vc_sopt.sv_tz;
+
mbp = &t2p->t2_tparam;
mb_init(mbp);
- mb_put_uint16le(mbp, fid);
- if (vcp->vc_sopt.sv_caps & SMB_CAP_INFOLEVEL_PASSTHRU)
- mb_put_uint16le(mbp, SMB_SFILEINFO_BASIC_INFORMATION);
- else
- mb_put_uint16le(mbp, SMB_SFILEINFO_BASIC_INFO);
- mb_put_uint32le(mbp, 0); /* XXX should be 16 not 32(?) */
+
+ if (cmd == SMB_TRANS2_SET_FILE_INFORMATION)
+ mb_put_uint16le(mbp, fid);
+
+ mb_put_uint16le(mbp, level);
+ mb_put_uint32le(mbp, 0); /* MBZ */
+
+ if (cmd == SMB_TRANS2_SET_PATH_INFORMATION) {
+ error = smbfs_fullpath(mbp, vcp, np, NULL, NULL, '\\');
+ if (error != 0)
+ goto out;
+ }
+
+ /* FAT file systems don't support dates earlier than 1980. */
+
mbp = &t2p->t2_tdata;
mb_init(mbp);
mb_put_uint64le(mbp, 0); /* creation time */
if (atime) {
- smb_time_local2NT(atime, svtz, &tm);
+ smb_time_local2NT(atime, &tm);
+ if (tm != 0 && (ssp->ss_flags & SMBS_FST_FAT) &&
+ tm < NT1980)
+ tm = NT1980;
} else
tm = 0;
mb_put_uint64le(mbp, tm); /* access time */
if (mtime) {
- smb_time_local2NT(mtime, svtz, &tm);
+ smb_time_local2NT(mtime, &tm);
+ if (tm != 0 && (ssp->ss_flags & SMBS_FST_FAT) &&
+ tm < NT1980)
+ tm = NT1980;
} else
tm = 0;
mb_put_uint64le(mbp, tm); /* last write time */
- mb_put_uint64le(mbp, tm); /* change time */
+ mb_put_uint64le(mbp, 0); /* ctime (no change) */
mb_put_uint32le(mbp, attr);
- mb_put_uint32le(mbp, 0); /* padding */
+ mb_put_uint32le(mbp, 0); /* padding */
t2p->t2_maxpcount = 2;
t2p->t2_maxdcount = 0;
error = smb_t2_request(t2p);
+out:
smb_t2_done(t2p);
return (error);
}
@@ -1380,38 +1113,34 @@ smbfs_smb_setfattrNT(struct smbnode *np, uint16_t fid,
* now too, which may or may not create a new object.
*/
int
-smbfs_smb_ntcreatex(struct smbnode *np, uint32_t rights,
- struct smb_cred *scrp, enum vtype vt,
- int *attrcacheupdated, uint16_t *fidp,
- const char *name, int nmlen, uint32_t disp, int xattr,
- len_t *sizep, uint32_t *rightsp)
+smbfs_smb_ntcreatex(
+ struct smbnode *np,
+ const char *name,
+ int nmlen,
+ int xattr, /* is named stream? */
+ uint32_t req_acc, /* requested access */
+ uint32_t efa, /* ext. file attrs (DOS attr +) */
+ uint32_t share_acc,
+ uint32_t disp, /* open disposition */
+ uint32_t createopt, /* NTCREATEX_OPTIONS_ */
+ struct smb_cred *scrp,
+ uint16_t *fidp,
+ uint32_t *cr_act_p, /* create action */
+ struct smbfattr *fap) /* optional */
{
struct smb_rq rq, *rqp = &rq;
struct smb_share *ssp = np->n_mount->smi_share;
struct smb_vc *vcp = SSTOVC(ssp);
struct mbchain *mbp;
struct mdchain *mdp;
- struct smbfattr fap;
+ struct smbfattr fa;
uint8_t wc;
- uint32_t longint, createact, createopt, efa;
+ uint32_t longint, createact;
uint64_t llongint;
int error;
uint16_t fid, *namelenp;
- /*
- * Set the File attributes and Create options.
- * WinXP uses EFA_NORMAL in all of these cases.
- */
- createopt = (vt == VDIR) ?
- NTCREATEX_OPTIONS_DIRECTORY :
- NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
- efa = SMB_EFA_NORMAL;
- if (disp != NTCREATEX_DISP_OPEN && !xattr) {
- if (name && *name == '.')
- efa = SMB_EFA_HIDDEN;
- }
-
- gethrestime(&fap.fa_reqtime);
+ bzero(&fa, sizeof (fa));
error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_NT_CREATE_ANDX, scrp);
if (error)
return (error);
@@ -1426,127 +1155,87 @@ smbfs_smb_ntcreatex(struct smbnode *np, uint32_t rights,
* XP to a W2K Server does not use NTCREATEX_FLAGS_OPEN_DIRECTORY
* for creating nor for opening a directory. Samba ignores the bit.
*/
-#if 0 /* causes sharing violation when making dir on W2K! */
- mb_put_uint32le(mbp, vt == VDIR ? NTCREATEX_FLAGS_OPEN_DIRECTORY : 0);
-#else
mb_put_uint32le(mbp, 0); /* NTCREATEX_FLAGS_* */
-#endif
mb_put_uint32le(mbp, 0); /* FID - basis for path if not root */
- mb_put_uint32le(mbp, rights);
+ mb_put_uint32le(mbp, req_acc);
mb_put_uint64le(mbp, 0); /* "initial allocation size" */
mb_put_uint32le(mbp, efa);
- mb_put_uint32le(mbp, NTCREATEX_SHARE_ACCESS_ALL);
+ mb_put_uint32le(mbp, share_acc);
mb_put_uint32le(mbp, disp);
mb_put_uint32le(mbp, createopt);
mb_put_uint32le(mbp, NTCREATEX_IMPERSONATION_IMPERSONATION); /* (?) */
mb_put_uint8(mbp, 0); /* security flags (?) */
smb_rq_wend(rqp);
smb_rq_bstart(rqp);
- do {
- if (name == NULL)
- nmlen = 0;
- error = smbfs_fullpath(mbp, vcp, np, name, &nmlen,
- xattr ? ':' : '\\');
- if (error)
- break;
- *namelenp = htoles(nmlen); /* includes null */
- smb_rq_bend(rqp);
- /*
- * Don't want to risk missing a successful
- * open response, or we could "leak" FIDs.
- */
- rqp->sr_flags |= SMBR_NOINTR_RECV;
- error = smb_rq_simple_timed(rqp, smb_timo_open);
- if (error)
- break;
- smb_rq_getreply(rqp, &mdp);
- /*
- * spec says 26 for word count, but 34 words are defined
- * and observed from win2000
- */
- if (md_get_uint8(mdp, &wc) != 0 ||
- (wc != 26 && wc != 34 && wc != 42)) {
- error = EBADRPC;
- break;
- }
- md_get_uint8(mdp, NULL); /* secondary cmd */
- md_get_uint8(mdp, NULL); /* mbz */
- md_get_uint16le(mdp, NULL); /* andxoffset */
- md_get_uint8(mdp, NULL); /* oplock lvl granted */
- md_get_uint16le(mdp, &fid); /* file ID */
- md_get_uint32le(mdp, &createact); /* create_action */
- md_get_uint64le(mdp, &llongint); /* creation time */
- md_get_uint64le(mdp, &llongint); /* access time */
- if (llongint) /* avoid bogus 0 time (on FAT roots) */
- smb_time_NT2local(llongint, vcp->vc_sopt.sv_tz,
- &fap.fa_atime);
- md_get_uint64le(mdp, &llongint); /* write time */
- if (llongint) /* avoid bogus 0 time (on FAT roots) */
- smb_time_NT2local(llongint, vcp->vc_sopt.sv_tz,
- &fap.fa_mtime);
- md_get_uint64le(mdp, &llongint); /* change time */
- if (llongint) /* avoid bogus 0 time (on FAT roots) */
- smb_time_NT2local(llongint, vcp->vc_sopt.sv_tz,
- &fap.fa_ctime);
- md_get_uint32le(mdp, &longint); /* attributes */
- fap.fa_attr = longint;
- md_get_uint64le(mdp, NULL); /* allocation size */
- md_get_uint64le(mdp, &llongint); /* EOF */
- fap.fa_size = llongint;
- if (sizep)
- *sizep = fap.fa_size;
- md_get_uint16le(mdp, NULL); /* file type */
- md_get_uint16le(mdp, NULL); /* device state */
- md_get_uint8(mdp, NULL); /* directory (boolean) */
- /*LINTED*/
- } while (0);
- smb_rq_done(rqp);
+
+ if (name == NULL)
+ nmlen = 0;
+ error = smbfs_fullpath(mbp, vcp, np, name, &nmlen,
+ xattr ? ':' : '\\');
if (error)
- return (error);
- if (fidp)
- *fidp = fid;
- if (rightsp)
- *rightsp = rights;
+ goto done;
+ *namelenp = htoles(nmlen); /* includes null */
+ smb_rq_bend(rqp);
/*
- * Is it possible that we have cached attributes?
- * Assume "not cached" if we created the object.
+ * Don't want to risk missing a successful
+ * open response, or we could "leak" FIDs.
*/
- if (createact == NTCREATEX_ACTION_CREATED || xattr)
- goto uncached;
- if (attrcacheupdated)
- *attrcacheupdated = 0;
+ rqp->sr_flags |= SMBR_NOINTR_RECV;
+ error = smb_rq_simple_timed(rqp, smb_timo_open);
+ if (error)
+ goto done;
+ smb_rq_getreply(rqp, &mdp);
/*
- * Update the cached attributes if they are still valid
- * in the cache and if nothing has changed.
+ * spec says 26 for word count, but 34 words are defined
+ * and observed from win2000
*/
- if (np->r_vnode == NULL)
- goto uncached;
- if (smbfs_attr_cachelookup(np->r_vnode, NULL) != 0)
- goto uncached; /* the cached attributes are not valid */
- if (fap.fa_size != np->n_size)
- goto uncached; /* the size is different */
- if (fap.fa_attr != np->n_dosattr)
- goto uncached; /* the attrs are different */
- /*
- * fap.fa_mtime is in two second increments while np->n_mtime
- * may be in one second increments, so comparing the times is
- * somewhat sloppy.
- *
- * XXX: true fap.fa_mtime resolution must depend upon server's
- * local filesystem and is thus indeterminate... XXX ...TBD how that
- * affects this code... note wire resolution here is 100ns versus
- * 1sec down in smbfs_smb_oldopen(SMB_COM_OPEN)
- */
- if (fap.fa_mtime.tv_sec != np->n_mtime.tv_sec &&
- fap.fa_mtime.tv_sec != np->n_mtime.tv_sec - 1 &&
- fap.fa_mtime.tv_sec != np->n_mtime.tv_sec + 1)
- goto uncached; /* the mod time is different */
-
- fap.fa_mtime.tv_sec = np->n_mtime.tv_sec; /* keep higher res time */
- smbfs_attr_cacheenter(np->r_vnode, &fap);
- if (attrcacheupdated)
- *attrcacheupdated = 1;
-uncached:
+ error = md_get_uint8(mdp, &wc);
+ if (error)
+ goto done;
+ if (wc != 26 && wc != 34 && wc != 42) {
+ error = EBADRPC;
+ goto done;
+ }
+ md_get_uint8(mdp, NULL); /* secondary cmd */
+ md_get_uint8(mdp, NULL); /* mbz */
+ md_get_uint16le(mdp, NULL); /* andxoffset */
+ md_get_uint8(mdp, NULL); /* oplock lvl granted */
+ md_get_uint16le(mdp, &fid); /* file ID */
+ md_get_uint32le(mdp, &createact); /* create_action */
+
+ md_get_uint64le(mdp, &llongint); /* creation time */
+ smb_time_NT2local(llongint, &fa.fa_createtime);
+ md_get_uint64le(mdp, &llongint); /* access time */
+ smb_time_NT2local(llongint, &fa.fa_atime);
+ md_get_uint64le(mdp, &llongint); /* write time */
+ smb_time_NT2local(llongint, &fa.fa_mtime);
+ md_get_uint64le(mdp, &llongint); /* change time */
+ smb_time_NT2local(llongint, &fa.fa_ctime);
+
+ md_get_uint32le(mdp, &longint); /* attributes */
+ fa.fa_attr = longint;
+
+ md_get_uint64le(mdp, &llongint); /* allocation size */
+ fa.fa_allocsz = llongint;
+
+ md_get_uint64le(mdp, &llongint); /* EOF position */
+ fa.fa_size = llongint;
+
+ error = md_get_uint16le(mdp, NULL); /* file type */
+ /* other stuff we don't care about */
+
+done:
+ smb_rq_done(rqp);
+ if (error)
+ return (error);
+
+ if (fidp)
+ *fidp = fid;
+ if (cr_act_p)
+ *cr_act_p = createact;
+ if (fap)
+ *fap = fa; /* struct copy */
+
return (0);
}
@@ -1554,18 +1243,32 @@ static uint32_t
smb_mode2rights(int mode)
{
mode = mode & SMB_AM_OPENMODE;
+ uint32_t rights =
+ STD_RIGHT_SYNCHRONIZE_ACCESS |
+ STD_RIGHT_READ_CONTROL_ACCESS;
- switch (mode) {
- case SMB_AM_OPENREAD:
- return (GENERIC_RIGHT_READ_ACCESS);
- case SMB_AM_OPENWRITE:
- return (GENERIC_RIGHT_WRITE_ACCESS);
- case SMB_AM_OPENRW:
- return (GENERIC_RIGHT_ALL_ACCESS);
- case SMB_AM_OPENEXEC:
- return (GENERIC_RIGHT_EXECUTE_ACCESS);
+ if ((mode == SMB_AM_OPENREAD) ||
+ (mode == SMB_AM_OPENRW)) {
+ rights |=
+ SA_RIGHT_FILE_READ_ATTRIBUTES |
+ SA_RIGHT_FILE_READ_DATA;
}
- return (0);
+
+ if ((mode == SMB_AM_OPENWRITE) ||
+ (mode == SMB_AM_OPENRW)) {
+ rights |=
+ SA_RIGHT_FILE_WRITE_ATTRIBUTES |
+ SA_RIGHT_FILE_APPEND_DATA |
+ SA_RIGHT_FILE_WRITE_DATA;
+ }
+
+ if (mode == SMB_AM_OPENEXEC) {
+ rights |=
+ SA_RIGHT_FILE_READ_ATTRIBUTES |
+ SA_RIGHT_FILE_EXECUTE;
+ }
+
+ return (rights);
}
static int
@@ -1576,34 +1279,43 @@ smb_rights2mode(uint32_t rights)
if (rights & (SA_RIGHT_FILE_APPEND_DATA | SA_RIGHT_FILE_DELETE_CHILD |
SA_RIGHT_FILE_WRITE_EA | SA_RIGHT_FILE_WRITE_ATTRIBUTES |
SA_RIGHT_FILE_WRITE_DATA | STD_RIGHT_WRITE_OWNER_ACCESS |
- STD_RIGHT_DELETE_ACCESS | STD_RIGHT_WRITE_DAC_ACCESS |
- GENERIC_RIGHT_ALL_ACCESS | GENERIC_RIGHT_WRITE_ACCESS))
+ STD_RIGHT_DELETE_ACCESS | STD_RIGHT_WRITE_DAC_ACCESS))
accmode = SMB_AM_OPENWRITE;
if (rights & (SA_RIGHT_FILE_READ_DATA | SA_RIGHT_FILE_READ_ATTRIBUTES |
- SA_RIGHT_FILE_READ_EA | STD_RIGHT_READ_CONTROL_ACCESS |
- GENERIC_RIGHT_ALL_ACCESS | GENERIC_RIGHT_READ_ACCESS))
+ SA_RIGHT_FILE_READ_EA | STD_RIGHT_READ_CONTROL_ACCESS))
accmode = (accmode == SMB_AM_OPENEXEC) ? SMB_AM_OPENREAD
: SMB_AM_OPENRW;
return (accmode);
}
static int
-smbfs_smb_oldopen(struct smbnode *np, int accmode, struct smb_cred *scrp,
- int *attrcacheupdated, uint16_t *fidp, const char *name,
- int nmlen, int xattr, len_t *sizep, uint32_t *rightsp)
+smbfs_smb_oldopen(
+ struct smbnode *np,
+ const char *name,
+ int nmlen,
+ int xattr,
+ int accmode,
+ struct smb_cred *scrp,
+ uint16_t *fidp,
+ uint16_t *granted_mode_p,
+ smbfattr_t *fap)
{
struct smb_rq rq, *rqp = &rq;
struct smb_share *ssp = np->n_mount->smi_share;
struct smb_vc *vcp = SSTOVC(ssp);
struct mbchain *mbp;
struct mdchain *mdp;
- struct smbfattr fap;
+ struct smbfattr fa;
uint8_t wc;
- uint16_t fid, wattr, grantedmode;
+ uint16_t wattr;
uint32_t longint;
int error;
+ bzero(&fa, sizeof (fa));
+
/*
+ * XXX: move to callers...
+ *
* Use DENYNONE to give unixy semantics of permitting
* everything not forbidden by permissions. Ie denial
* is up to server with clients/openers needing to use
@@ -1611,7 +1323,6 @@ smbfs_smb_oldopen(struct smbnode *np, int accmode, struct smb_cred *scrp,
*/
accmode |= SMB_SM_DENYNONE;
- gethrestime(&fap.fa_reqtime);
error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_OPEN, scrp);
if (error)
return (error);
@@ -1623,91 +1334,55 @@ smbfs_smb_oldopen(struct smbnode *np, int accmode, struct smb_cred *scrp,
smb_rq_wend(rqp);
smb_rq_bstart(rqp);
mb_put_uint8(mbp, SMB_DT_ASCII);
- do {
- error = smbfs_fullpath(mbp, vcp, np, name, &nmlen,
- xattr ? ':' : '\\');
- if (error)
- break;
- smb_rq_bend(rqp);
- /*
- * Don't want to risk missing a successful
- * open response, or we could "leak" FIDs.
- */
- rqp->sr_flags |= SMBR_NOINTR_RECV;
- error = smb_rq_simple_timed(rqp, smb_timo_open);
- if (error)
- break;
- smb_rq_getreply(rqp, &mdp);
- /*
- * 8/2002 a DAVE server returned wc of 15 so we ignore that.
- * (the actual packet length and data was correct)
- */
- if (md_get_uint8(mdp, &wc) != 0 || (wc != 7 && wc != 15)) {
- error = EBADRPC;
- break;
- }
- md_get_uint16le(mdp, &fid);
- md_get_uint16le(mdp, &wattr);
- fap.fa_attr = wattr;
- /*
- * Be careful using the time returned here, as
- * with FAT on NT4SP6, at least, the time returned is low
- * 32 bits of 100s of nanoseconds (since 1601) so it rolls
- * over about every seven minutes!
- */
- md_get_uint32le(mdp, &longint); /* specs: secs since 1970 */
- if (longint) /* avoid bogus zero returns */
- smb_time_server2local(longint, vcp->vc_sopt.sv_tz,
- &fap.fa_mtime);
- md_get_uint32le(mdp, &longint);
- fap.fa_size = longint;
- if (sizep)
- *sizep = fap.fa_size;
- md_get_uint16le(mdp, &grantedmode);
- /*LINTED*/
- } while (0);
- smb_rq_done(rqp);
+
+ error = smbfs_fullpath(mbp, vcp, np, name, &nmlen,
+ xattr ? ':' : '\\');
if (error)
- return (error);
- if (fidp)
- *fidp = fid;
- if (xattr)
- goto uncached;
- if (rightsp)
- *rightsp = smb_mode2rights(grantedmode);
- if (attrcacheupdated)
- *attrcacheupdated = 0;
+ goto done;
+ smb_rq_bend(rqp);
/*
- * Update the cached attributes if they are still valid
- * in the cache and if nothing has changed.
- * Note that this won't ever update if the file size is
- * greater than the 32-bits returned by SMB_COM_OPEN.
- * For 64-bit file sizes, SMB_COM_NT_CREATE_ANDX must
- * be used instead of SMB_COM_OPEN.
+ * Don't want to risk missing a successful
+ * open response, or we could "leak" FIDs.
*/
- if (np->r_vnode == NULL)
- goto uncached;
- if (smbfs_attr_cachelookup(np->r_vnode, NULL) != 0)
- goto uncached; /* the cached attributes are not valid */
- if (fap.fa_size != np->n_size)
- goto uncached; /* the size is different */
- if (fap.fa_attr != np->n_dosattr)
- goto uncached; /* the attrs are different */
+ rqp->sr_flags |= SMBR_NOINTR_RECV;
+ error = smb_rq_simple_timed(rqp, smb_timo_open);
+ if (error)
+ goto done;
+ smb_rq_getreply(rqp, &mdp);
/*
- * fap.fa_mtime is in two second increments while np->n_mtime
- * may be in one second increments, so comparing the times is
- * somewhat sloppy.
+ * 8/2002 a DAVE server returned wc of 15 so we ignore that.
+ * (the actual packet length and data was correct)
*/
- if (fap.fa_mtime.tv_sec != np->n_mtime.tv_sec &&
- fap.fa_mtime.tv_sec != np->n_mtime.tv_sec - 1 &&
- fap.fa_mtime.tv_sec != np->n_mtime.tv_sec + 1)
- goto uncached; /* the mod time is different */
-
- fap.fa_mtime.tv_sec = np->n_mtime.tv_sec; /* keep higher res time */
- smbfs_attr_cacheenter(np->r_vnode, &fap);
- if (attrcacheupdated)
- *attrcacheupdated = 1;
-uncached:
+ error = md_get_uint8(mdp, &wc);
+ if (error)
+ goto done;
+ if (wc != 7 && wc != 15) {
+ error = EBADRPC;
+ goto done;
+ }
+ md_get_uint16le(mdp, fidp);
+ md_get_uint16le(mdp, &wattr);
+ fa.fa_attr = wattr;
+ /*
+ * Be careful using the time returned here, as
+ * with FAT on NT4SP6, at least, the time returned is low
+ * 32 bits of 100s of nanoseconds (since 1601) so it rolls
+ * over about every seven minutes!
+ */
+ md_get_uint32le(mdp, &longint); /* specs: secs since 1970 */
+ smb_time_server2local(longint, vcp->vc_sopt.sv_tz, &fa.fa_mtime);
+ md_get_uint32le(mdp, &longint);
+ fa.fa_size = longint;
+ error = md_get_uint16le(mdp, granted_mode_p);
+
+done:
+ smb_rq_done(rqp);
+ if (error)
+ return (error);
+
+ if (fap)
+ *fap = fa; /* struct copy */
+
return (0);
}
@@ -1717,8 +1392,7 @@ smbfs_smb_tmpopen(struct smbnode *np, uint32_t rights, struct smb_cred *scrp,
{
struct smb_share *ssp = np->n_mount->smi_share;
struct smb_vc *vcp = SSTOVC(ssp);
- enum vtype vt = VREG;
- int error;
+ int accmode, error;
/* Shared lock for n_fid use below. */
ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_READER));
@@ -1735,18 +1409,27 @@ smbfs_smb_tmpopen(struct smbnode *np, uint32_t rights, struct smb_cred *scrp,
}
mutex_exit(&np->r_statelock);
- if (!(vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS)) {
- int mode = smb_rights2mode(rights);
- error = smbfs_smb_oldopen(np, mode, scrp,
- NULL, fidp, NULL, 0, 0, NULL, NULL);
- } else {
- if (SMBTOV(np))
- vt = SMBTOV(np)->v_type;
- error = smbfs_smb_ntcreatex(np, rights, scrp, vt,
- NULL, fidp, NULL, 0, NTCREATEX_DISP_OPEN, 0,
- NULL, NULL);
+ /* re-open an existing file. */
+ if (vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) {
+ error = smbfs_smb_ntcreatex(np,
+ NULL, 0, 0, /* name nmlen xattr */
+ rights, SMB_EFA_NORMAL,
+ NTCREATEX_SHARE_ACCESS_ALL,
+ NTCREATEX_DISP_OPEN,
+ 0, /* create options */
+ scrp, fidp,
+ NULL, NULL); /* cr_act_p fa_p */
+ return (error);
}
+ accmode = smb_rights2mode(rights);
+ error = smbfs_smb_oldopen(np,
+ NULL, 0, 0, /* name nmlen xattr */
+ accmode, scrp,
+ fidp,
+ NULL, /* granted mode p */
+ NULL); /* fa p */
+
return (error);
}
@@ -1786,27 +1469,48 @@ smbfs_smb_tmpclose(struct smbnode *np, uint16_t fid, struct smb_cred *scrp)
}
int
-smbfs_smb_open(struct smbnode *np, uint32_t rights, struct smb_cred *scrp,
- int *attrcacheupdated, uint16_t *fidp, const char *name,
- int nmlen, int xattr, len_t *sizep, uint32_t *rightsp)
+smbfs_smb_open(
+ struct smbnode *np,
+ const char *name,
+ int nmlen,
+ int xattr,
+ uint32_t rights,
+ struct smb_cred *scrp,
+ uint16_t *fidp,
+ uint32_t *rightsp,
+ smbfattr_t *fap)
{
- int error;
struct smb_share *ssp = np->n_mount->smi_share;
struct smb_vc *vcp = SSTOVC(ssp);
- enum vtype vt = VREG;
+ int accmode, error;
+ uint16_t grantedmode;
+ /* open an existing file */
if (vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) {
- if (SMBTOV(np))
- vt = SMBTOV(np)->v_type;
- error = smbfs_smb_ntcreatex(np, rights, scrp, vt,
- attrcacheupdated, fidp, name, nmlen,
- NTCREATEX_DISP_OPEN, xattr, sizep, rightsp);
- } else {
- error = smbfs_smb_oldopen(np, smb_rights2mode(rights), scrp,
- attrcacheupdated, fidp, name, nmlen, xattr, sizep, rightsp);
+ error = smbfs_smb_ntcreatex(np,
+ name, nmlen, xattr,
+ rights, SMB_EFA_NORMAL,
+ NTCREATEX_SHARE_ACCESS_ALL,
+ NTCREATEX_DISP_OPEN,
+ 0, /* create options */
+ scrp, fidp,
+ NULL, fap); /* cr_act_p fa_p */
+ if (error != 0)
+ return (error);
+ *rightsp = rights;
+ return (0);
}
- return (error);
+ accmode = smb_rights2mode(rights);
+ error = smbfs_smb_oldopen(np,
+ name, nmlen, xattr, accmode, scrp,
+ fidp, &grantedmode, fap);
+ if (error != 0)
+ return (error);
+ *rightsp = smb_mode2rights(grantedmode);
+ (void) smbfs_smb_getfattr(np, fap, scrp);
+
+ return (0);
}
int
@@ -1825,7 +1529,8 @@ smbfs_smb_close(struct smb_share *ssp, uint16_t fid, struct timespec *mtime,
smb_rq_wstart(rqp);
mb_put_uint16le(mbp, fid);
if (mtime) {
- smb_time_local2server(mtime, SSTOVC(ssp)->vc_sopt.sv_tz, &time);
+ int sv_tz = SSTOVC(ssp)->vc_sopt.sv_tz;
+ smb_time_local2server(mtime, sv_tz, &time);
} else
time = 0;
mb_put_uint32le(mbp, time);
@@ -1865,7 +1570,7 @@ smbfs_smb_close(struct smb_share *ssp, uint16_t fid, struct timespec *mtime,
static int
smbfs_smb_oldcreate(struct smbnode *dnp, const char *name, int nmlen,
- struct smb_cred *scrp, uint16_t *fidp, int xattr)
+ int xattr, struct smb_cred *scrp, uint16_t *fidp)
{
struct smb_rq rq, *rqp = &rq;
struct smb_share *ssp = dnp->n_mount->smi_share;
@@ -1893,32 +1598,45 @@ smbfs_smb_oldcreate(struct smbnode *dnp, const char *name, int nmlen,
mb_put_uint8(mbp, SMB_DT_ASCII);
error = smbfs_fullpath(mbp, SSTOVC(ssp), dnp, name, &nmlen,
xattr ? ':' : '\\');
- if (!error) {
- smb_rq_bend(rqp);
- /*
- * Don't want to risk missing a successful
- * open response, or we could "leak" FIDs.
- */
- rqp->sr_flags |= SMBR_NOINTR_RECV;
- error = smb_rq_simple_timed(rqp, smb_timo_open);
- if (!error) {
- smb_rq_getreply(rqp, &mdp);
- md_get_uint8(mdp, &wc);
- if (wc == 1)
- md_get_uint16le(mdp, fidp);
- else
- error = EBADRPC;
- }
+ if (error)
+ goto out;
+ smb_rq_bend(rqp);
+ /*
+ * Don't want to risk missing a successful
+ * open response, or we could "leak" FIDs.
+ */
+ rqp->sr_flags |= SMBR_NOINTR_RECV;
+ error = smb_rq_simple_timed(rqp, smb_timo_open);
+ if (error)
+ goto out;
+
+ smb_rq_getreply(rqp, &mdp);
+ md_get_uint8(mdp, &wc);
+ if (wc != 1) {
+ error = EBADRPC;
+ goto out;
}
+ error = md_get_uint16le(mdp, fidp);
+
+out:
smb_rq_done(rqp);
return (error);
}
int
-smbfs_smb_create(struct smbnode *dnp, const char *name, int nmlen,
- struct smb_cred *scrp, uint16_t *fidp, uint32_t disp, int xattr)
+smbfs_smb_create(
+ struct smbnode *dnp,
+ const char *name,
+ int nmlen,
+ int xattr,
+ uint32_t disp,
+ struct smb_cred *scrp,
+ uint16_t *fidp)
{
- struct smb_vc *vcp = SSTOVC(dnp->n_mount->smi_share);
+ struct smb_share *ssp = dnp->n_mount->smi_share;
+ struct smb_vc *vcp = SSTOVC(ssp);
+ uint32_t efa, rights;
+ int error;
/*
* At present the only access we might need is to WRITE data,
@@ -1927,12 +1645,21 @@ smbfs_smb_create(struct smbnode *dnp, const char *name, int nmlen,
* and be set upstream.
*/
if (vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) {
- return (smbfs_smb_ntcreatex(dnp, SA_RIGHT_FILE_WRITE_DATA,
- scrp, VREG, NULL, fidp, name, nmlen, disp, xattr,
- NULL, NULL));
- } else
- return (smbfs_smb_oldcreate(dnp, name, nmlen, scrp, fidp,
- xattr));
+ rights = SA_RIGHT_FILE_WRITE_DATA;
+ efa = SMB_EFA_NORMAL;
+ if (!xattr && name && *name == '.')
+ efa = SMB_EFA_HIDDEN;
+ error = smbfs_smb_ntcreatex(dnp,
+ name, nmlen, xattr, rights, efa,
+ NTCREATEX_SHARE_ACCESS_ALL,
+ disp, /* != NTCREATEX_DISP_OPEN */
+ NTCREATEX_OPTIONS_NON_DIRECTORY_FILE,
+ scrp, fidp, NULL, NULL); /* cr_act_p fa_p */
+ return (error);
+ }
+
+ error = smbfs_smb_oldcreate(dnp, name, nmlen, xattr, scrp, fidp);
+ return (error);
}
int
@@ -2031,19 +1758,18 @@ smbfs_smb_move(struct smbnode *src, struct smbnode *tdnp,
smb_rq_wend(rqp);
smb_rq_bstart(rqp);
mb_put_uint8(mbp, SMB_DT_ASCII);
- do {
- error = smbfs_fullpath(mbp, SSTOVC(ssp), src, NULL, NULL, '\\');
- if (error)
- break;
- mb_put_uint8(mbp, SMB_DT_ASCII);
- error = smbfs_fullpath(mbp, SSTOVC(ssp), tdnp, tname, &tnmlen,
- '\\');
- if (error)
- break;
- smb_rq_bend(rqp);
- error = smb_rq_simple(rqp);
- /*LINTED*/
- } while (0);
+
+ error = smbfs_fullpath(mbp, SSTOVC(ssp), src, NULL, NULL, '\\');
+ if (error)
+ goto out;
+ mb_put_uint8(mbp, SMB_DT_ASCII);
+ error = smbfs_fullpath(mbp, SSTOVC(ssp), tdnp, tname, &tnmlen, '\\');
+ if (error)
+ goto out;
+ smb_rq_bend(rqp);
+ error = smb_rq_simple(rqp);
+
+out:
smb_rq_done(rqp);
return (error);
}
@@ -2075,10 +1801,12 @@ smbfs_smb_oldmkdir(struct smbnode *dnp, const char *name, int len,
}
int
-smbfs_smb_mkdir(struct smbnode *dnp, const char *name, int len,
+smbfs_smb_mkdir(struct smbnode *dnp, const char *name, int nmlen,
struct smb_cred *scrp)
{
struct smb_share *ssp = dnp->n_mount->smi_share;
+ struct smb_vc *vcp = SSTOVC(ssp);
+ uint32_t rights;
uint16_t fid;
int error;
@@ -2087,18 +1815,23 @@ smbfs_smb_mkdir(struct smbnode *dnp, const char *name, int len,
* just to be asking for something. The rights==0 case could
* easily be broken on some old or unusual servers.
*/
- if (SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) {
- error = smbfs_smb_ntcreatex(dnp, SA_RIGHT_FILE_READ_DATA,
- scrp, VDIR, NULL, &fid, name, len,
- NTCREATEX_DISP_CREATE, 0, NULL, NULL);
+ if (vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) {
+ rights = SA_RIGHT_FILE_READ_DATA;
+ error = smbfs_smb_ntcreatex(dnp,
+ name, nmlen, 0, /* xattr */
+ rights, SMB_EFA_DIRECTORY,
+ NTCREATEX_SHARE_ACCESS_ALL,
+ NTCREATEX_DISP_CREATE,
+ NTCREATEX_OPTIONS_DIRECTORY,
+ scrp, &fid, NULL, NULL); /* cr_act_p fa_p */
if (error)
return (error);
- error = smbfs_smb_close(ssp, fid, NULL, scrp);
- if (error)
- SMBERROR("error %d closing fid %d\n", error, fid);
+ (void) smbfs_smb_close(ssp, fid, NULL, scrp);
return (0);
- } else
- return (smbfs_smb_oldmkdir(dnp, name, len, scrp));
+ }
+
+ error = smbfs_smb_oldmkdir(dnp, name, nmlen, scrp);
+ return (error);
}
int
@@ -2183,21 +1916,25 @@ smbfs_smb_search(struct smbfs_fctx *ctx)
} else if (error)
return (error);
smb_rq_getreply(rqp, &mdp);
- md_get_uint8(mdp, &wc);
+ error = md_get_uint8(mdp, &wc);
+ if (error)
+ return (error);
if (wc != 1)
return (iseof ? ENOENT : EBADRPC);
md_get_uint16le(mdp, &ec);
+ md_get_uint16le(mdp, &bc);
+ md_get_uint8(mdp, &bt);
+ error = md_get_uint16le(mdp, &dlen);
+ if (error)
+ return (error);
if (ec == 0)
return (ENOENT);
ctx->f_ecnt = ec;
- md_get_uint16le(mdp, &bc);
if (bc < 3)
return (EBADRPC);
bc -= 3;
- md_get_uint8(mdp, &bt);
if (bt != SMB_DT_VARIABLE)
return (EBADRPC);
- md_get_uint16le(mdp, &dlen);
if (dlen != bc || dlen % SMB_DENTRYLEN != 0)
return (EBADRPC);
return (0);
@@ -2249,7 +1986,6 @@ smbfs_smb_findnextLM1(struct smbfs_fctx *ctx, uint16_t limit)
error = smbfs_smb_search(ctx);
if (error)
return (error);
- ctx->f_attr.fa_reqtime = ts;
}
rqp = ctx->f_rq;
smb_rq_getreply(rqp, &mdp);
@@ -2259,7 +1995,7 @@ smbfs_smb_findnextLM1(struct smbfs_fctx *ctx, uint16_t limit)
md_get_uint16le(mdp, &date);
md_get_uint32le(mdp, &size);
cp = ctx->f_name;
- md_get_mem(mdp, cp, sizeof (ctx->f_fname), MB_MSYSTEM);
+ error = md_get_mem(mdp, cp, sizeof (ctx->f_fname), MB_MSYSTEM);
cp[sizeof (ctx->f_fname) - 1] = 0;
cp += strlen(cp) - 1;
while (*cp == ' ' && cp >= ctx->f_name)
@@ -2473,7 +2209,6 @@ smbfs_smb_findnextLM2(struct smbfs_fctx *ctx, uint16_t limit)
error = smbfs_smb_trans2find2(ctx);
if (error)
return (error);
- ctx->f_attr.fa_reqtime = ts;
ctx->f_otws++;
}
t2p = ctx->f_t2;
@@ -2485,6 +2220,8 @@ smbfs_smb_findnextLM2(struct smbfs_fctx *ctx, uint16_t limit)
fxsz = 0;
md_get_uint16le(mdp, &date);
md_get_uint16le(mdp, &time); /* creation time */
+ smb_dos2unixtime(date, time, 0, svtz,
+ &ctx->f_attr.fa_createtime);
md_get_uint16le(mdp, &date);
md_get_uint16le(mdp, &time); /* access time */
smb_dos2unixtime(date, time, 0, svtz, &ctx->f_attr.fa_atime);
@@ -2493,7 +2230,8 @@ smbfs_smb_findnextLM2(struct smbfs_fctx *ctx, uint16_t limit)
smb_dos2unixtime(date, time, 0, svtz, &ctx->f_attr.fa_mtime);
md_get_uint32le(mdp, &size);
ctx->f_attr.fa_size = size;
- md_get_uint32le(mdp, NULL); /* allocation size */
+ md_get_uint32le(mdp, &size); /* allocation size */
+ ctx->f_attr.fa_allocsz = size;
md_get_uint16le(mdp, &wattr);
ctx->f_attr.fa_attr = wattr;
error = md_get_uint8(mdp, &tb);
@@ -2507,18 +2245,19 @@ smbfs_smb_findnextLM2(struct smbfs_fctx *ctx, uint16_t limit)
case SMB_FIND_BOTH_DIRECTORY_INFO:
md_get_uint32le(mdp, &next);
md_get_uint32le(mdp, &resumekey); /* file index (resume key) */
- md_get_uint64le(mdp, NULL); /* creation time */
+ md_get_uint64le(mdp, &llongint); /* creation time */
+ smb_time_NT2local(llongint, &ctx->f_attr.fa_createtime);
md_get_uint64le(mdp, &llongint);
- smb_time_NT2local(llongint, svtz, &ctx->f_attr.fa_atime);
+ smb_time_NT2local(llongint, &ctx->f_attr.fa_atime);
md_get_uint64le(mdp, &llongint);
- smb_time_NT2local(llongint, svtz, &ctx->f_attr.fa_mtime);
+ smb_time_NT2local(llongint, &ctx->f_attr.fa_mtime);
md_get_uint64le(mdp, &llongint);
- smb_time_NT2local(llongint, svtz, &ctx->f_attr.fa_ctime);
+ smb_time_NT2local(llongint, &ctx->f_attr.fa_ctime);
md_get_uint64le(mdp, &llongint); /* file size */
ctx->f_attr.fa_size = llongint;
- md_get_uint64le(mdp, NULL); /* real size (should use) */
- /* freebsd bug: fa_attr endian bug */
- md_get_uint32le(mdp, &dattr); /* extended file attributes */
+ md_get_uint64le(mdp, &llongint); /* alloc. size */
+ ctx->f_attr.fa_allocsz = llongint;
+ md_get_uint32le(mdp, &dattr); /* ext. file attributes */
ctx->f_attr.fa_attr = dattr;
error = md_get_uint32le(mdp, &size); /* name len */
if (error)
@@ -2541,6 +2280,7 @@ smbfs_smb_findnextLM2(struct smbfs_fctx *ctx, uint16_t limit)
SMBVDEBUG("unexpected info level %d\n", ctx->f_infolevel);
return (EINVAL);
}
+
if (SMB_UNICODE_STRINGS(SSTOVC(ctx->f_ssp)))
nmlen = min(size, SMB_MAXFNAMELEN * 2);
else
@@ -2631,7 +2371,12 @@ smbfs_smb_findcloseLM2(struct smbfs_fctx *ctx)
kmem_free(ctx->f_name, ctx->f_namesz);
if (ctx->f_t2)
smb_t2_done(ctx->f_t2);
- if ((ctx->f_flags & SMBFS_RDD_NOCLOSE) == 0)
+ /*
+ * If SMBFS_RDD_FINDFIRST is still set, we were opened
+ * but never saw a findfirst, so we don't have any
+ * search handle to close.
+ */
+ if ((ctx->f_flags & (SMBFS_RDD_FINDFIRST | SMBFS_RDD_NOCLOSE)) == 0)
error = smbfs_smb_findclose2(ctx);
return (error);
}
@@ -2656,8 +2401,7 @@ smbfs_smb_findopen(struct smbnode *dnp, const char *wild, int wlen,
goto out;
}
- if (SMB_DIALECT(SSTOVC(ctx->f_ssp)) < SMB_DIALECT_LANMAN2_0 ||
- (dnp->n_mount->smi_args.flags & SMBFS_MOUNT_NO_LONG)) {
+ if (SMB_DIALECT(SSTOVC(ctx->f_ssp)) < SMB_DIALECT_LANMAN2_0) {
error = smbfs_smb_findopenLM1(ctx, dnp, wild, wlen, attr);
} else {
error = smbfs_smb_findopenLM2(ctx, dnp, wild, wlen, attr);
@@ -2718,8 +2462,7 @@ smbfs_smb_findnext(struct smbfs_fctx *ctx, int limit, struct smb_cred *scrp)
* the ..._findnext functions above.
*/
- ctx->f_attr.fa_ino = smbfs_getino(ctx->f_dnp, ctx->f_name,
- ctx->f_nmlen);
+ ctx->f_inum = smbfs_getino(ctx->f_dnp, ctx->f_name, ctx->f_nmlen);
return (0);
}
@@ -2780,6 +2523,11 @@ smbfs_smb_lookup(struct smbnode *dnp, const char **namep, int *nmlenp,
}
/*
+ * XXX: Should use _qpathinfo here instead.
+ * (if SMB_CAP_NT_SMBS)
+ */
+
+ /*
* Shared lock for n_fid use (smb_flush).
*/
intr = dnp->n_mount->smi_flags & SMI_INT;
@@ -2802,8 +2550,11 @@ smbfs_smb_lookup(struct smbnode *dnp, const char **namep, int *nmlenp,
error = smbfs_smb_findnext(ctx, 1, scrp);
if (error == 0) {
*fap = ctx->f_attr;
- if (name == NULL)
- fap->fa_ino = dnp->n_ino;
+ /*
+ * Solaris smbfattr doesn't have fa_ino,
+ * and we don't allow name==NULL in this
+ * function anymore.
+ */
if (namep)
*namep = (const char *)smbfs_name_alloc(
ctx->f_name, ctx->f_nmlen);
diff --git a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_subr.c b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_subr.c
index 508dcbdede..90549cbbc7 100644
--- a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_subr.c
+++ b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_subr.c
@@ -43,13 +43,7 @@
#include <sys/vnode.h>
#include <sys/sunddi.h>
-#ifdef APPLE
-#include <sys/smb_apple.h>
-#include <sys/utfconv.h>
-#include <sys/smb_iconv.h>
-#else /* APPLE */
#include <netsmb/smb_osdep.h>
-#endif /* APPLE */
#include <netsmb/smb.h>
#include <netsmb/smb_conn.h>
@@ -60,203 +54,6 @@
#include <smbfs/smbfs_node.h>
#include <smbfs/smbfs_subr.h>
-#ifdef APPLE
-MALLOC_DEFINE(M_SMBFSDATA, "SMBFS data", "SMBFS private data");
-#endif /* APPLE */
-
-/*
- * Time & date conversion routines taken from msdosfs. Although leap
- * year calculation is bogus, it's sufficient before 2100 :)
- */
-/*
- * This is the format of the contents of the deTime field in the direntry
- * structure.
- * We don't use bitfields because we don't know how compilers for
- * arbitrary machines will lay them out.
- */
-#define DT_2SECONDS_MASK 0x1F /* seconds divided by 2 */
-#define DT_2SECONDS_SHIFT 0
-#define DT_MINUTES_MASK 0x7E0 /* minutes */
-#define DT_MINUTES_SHIFT 5
-#define DT_HOURS_MASK 0xF800 /* hours */
-#define DT_HOURS_SHIFT 11
-
-/*
- * This is the format of the contents of the deDate field in the direntry
- * structure.
- */
-#define DD_DAY_MASK 0x1F /* day of month */
-#define DD_DAY_SHIFT 0
-#define DD_MONTH_MASK 0x1E0 /* month */
-#define DD_MONTH_SHIFT 5
-#define DD_YEAR_MASK 0xFE00 /* year - 1980 */
-#define DD_YEAR_SHIFT 9
-/*
- * Total number of days that have passed for each month in a regular year.
- */
-static ushort_t regyear[] = {
- 31, 59, 90, 120, 151, 181,
- 212, 243, 273, 304, 334, 365
-};
-
-/*
- * Total number of days that have passed for each month in a leap year.
- */
-static ushort_t leapyear[] = {
- 31, 60, 91, 121, 152, 182,
- 213, 244, 274, 305, 335, 366
-};
-
-/*
- * Variables used to remember parts of the last time conversion. Maybe we
- * can avoid a full conversion.
- */
-static ulong_t lasttime;
-static ulong_t lastday;
-static ushort_t lastddate;
-static ushort_t lastdtime;
-
-#ifdef APPLE
-PRIVSYM int wall_cmos_clock = 0; /* XXX */
-PRIVSYM int adjkerntz = 0; /* XXX */
-#endif /* APPLE */
-
-void
-smb_time_unix2dos(struct timespec *tsp, int tzoff, u_int16_t *ddp,
- u_int16_t *dtp, u_int8_t *dhp)
-{
- long t;
- ulong_t days, year, month, inc;
- ushort_t *months;
-
- /*
- * If the time from the last conversion is the same as now, then
- * skip the computations and use the saved result.
- */
- smb_time_local2server(tsp, tzoff, &t);
- t &= ~1;
- if (lasttime != t) {
- lasttime = t;
- if (t < 0) {
- /*
- * This is before 1970, so it's before 1980,
- * and can't be represented as a DOS time.
- * Just represent it as the DOS epoch.
- */
- lastdtime = 0;
- lastddate = (1 << DD_DAY_SHIFT)
- + (1 << DD_MONTH_SHIFT)
- + ((1980 - 1980) << DD_YEAR_SHIFT);
- } else {
- lastdtime = (((t / 2) % 30) << DT_2SECONDS_SHIFT)
- + (((t / 60) % 60) << DT_MINUTES_SHIFT)
- + (((t / 3600) % 24) << DT_HOURS_SHIFT);
-
- /*
- * If the number of days since 1970 is the same as
- * the last time we did the computation then skip
- * all this leap year and month stuff.
- */
- days = t / (24 * 60 * 60);
- if (days != lastday) {
- lastday = days;
- for (year = 1970; ; year++) {
- /*
- * XXX - works in 2000, but won't
- * work in 2100.
- */
- inc = year & 0x03 ? 365 : 366;
- if (days < inc)
- break;
- days -= inc;
- }
- /*
- * XXX - works in 2000, but won't work in 2100.
- */
- months = year & 0x03 ? regyear : leapyear;
- for (month = 0; days >= months[month]; month++)
- ;
- if (month > 0)
- days -= months[month - 1];
- lastddate = ((days + 1) << DD_DAY_SHIFT)
- + ((month + 1) << DD_MONTH_SHIFT);
- /*
- * Remember DOS's idea of time is relative
- * to 1980, but UN*X's is relative to 1970.
- * If somehow we get a time before 1980 then
- * don't give totally crazy results.
- */
- if (year > 1980)
- lastddate += (year - 1980) <<
- DD_YEAR_SHIFT;
- }
- }
- }
- if (dtp)
- *dtp = lastdtime;
- if (dhp)
- *dhp = (tsp->tv_sec & 1) * 100 + tsp->tv_nsec / 10000000;
-
- *ddp = lastddate;
-}
-
-/*
- * The number of seconds between Jan 1, 1970 and Jan 1, 1980. In that
- * interval there were 8 regular years and 2 leap years.
- */
-#define SECONDSTO1980 (((8 * 365) + (2 * 366)) * (24 * 60 * 60))
-
-static ushort_t lastdosdate;
-static ulong_t lastseconds;
-
-void
-smb_dos2unixtime(uint_t dd, uint_t dt, uint_t dh, int tzoff,
- struct timespec *tsp)
-{
- ulong_t seconds;
- ulong_t month;
- ulong_t year;
- ulong_t days;
- ushort_t *months;
-
- if (dd == 0) {
- tsp->tv_sec = 0;
- tsp->tv_nsec = 0;
- return;
- }
- seconds = (((dt & DT_2SECONDS_MASK) >> DT_2SECONDS_SHIFT) << 1)
- + ((dt & DT_MINUTES_MASK) >> DT_MINUTES_SHIFT) * 60
- + ((dt & DT_HOURS_MASK) >> DT_HOURS_SHIFT) * 3600
- + dh / 100;
- /*
- * If the year, month, and day from the last conversion are the
- * same then use the saved value.
- */
- if (lastdosdate != dd) {
- lastdosdate = (ushort_t)dd;
- days = 0;
- year = (dd & DD_YEAR_MASK) >> DD_YEAR_SHIFT;
- days = year * 365;
- days += year / 4 + 1; /* add in leap days */
- /*
- * XXX - works in 2000, but won't work in 2100.
- */
- if ((year & 0x03) == 0)
- days--; /* if year is a leap year */
- months = year & 0x03 ? regyear : leapyear;
- month = (dd & DD_MONTH_MASK) >> DD_MONTH_SHIFT;
- if (month < 1 || month > 12) {
- month = 1;
- }
- if (month > 1)
- days += months[month - 2];
- days += ((dd & DD_DAY_MASK) >> DD_DAY_SHIFT) - 1;
- lastseconds = (days * 24 * 60 * 60) + SECONDSTO1980;
- }
- smb_time_server2local(seconds + lastseconds, tzoff, tsp);
- tsp->tv_nsec = (dh % 100) * 10000000;
-}
-
/*
* In the Darwin code, this function used to compute the full path
* by following the chain of n_parent pointers back to the root.
@@ -388,7 +185,7 @@ smbfs_fname_tolocal(struct smbfs_fctx *ctx)
errout:
/*
* Conversion failed, but our caller does not
- * deal with errors here, so... (hack).
+ * deal with errors here, so just put a "?".
* Don't expect to ever see this.
*/
(void) strlcpy(ctx->f_name, "?", ctx->f_namesz);
diff --git a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_subr.h b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_subr.h
index 7c1107378b..78a50077d9 100644
--- a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_subr.h
+++ b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_subr.h
@@ -110,6 +110,7 @@ struct smbfs_fctx {
* Return values
*/
struct smbfattr f_attr; /* current attributes */
+ u_longlong_t f_inum; /* current I number */
char *f_name; /* current file name */
int f_nmlen; /* name len */
int f_namesz; /* memory allocated */
@@ -148,7 +149,7 @@ typedef struct smbfs_fctx smbfs_fctx_t;
#define f_t2 f_urq.uf_t2
/*
- * smb level
+ * smb level (smbfs_smb.c)
*/
int smbfs_smb_lock(struct smbnode *np, int op, caddr_t id,
offset_t start, uint64_t len, int largelock,
@@ -163,25 +164,21 @@ int smbfs_smb_setfsize(struct smbnode *np, uint16_t fid, uint64_t newsize,
int smbfs_smb_getfattr(struct smbnode *np, struct smbfattr *fap,
struct smb_cred *scrp);
-int smbfs_smb_setfattr(struct smbnode *np, uint16_t fid,
+int smbfs_smb_setfattr(struct smbnode *np, int fid,
uint32_t attr, struct timespec *mtime, struct timespec *atime,
struct smb_cred *scrp);
-int smbfs_smb_setpattr(struct smbnode *np,
- uint32_t attr, struct timespec *mtime, struct timespec *atime,
- struct smb_cred *scrp);
-
-int smbfs_smb_open(struct smbnode *np, uint32_t rights, struct smb_cred *scrp,
- int *attrcacheupdated, uint16_t *fidp, const char *name, int nmlen,
- int xattr, len_t *sizep, uint32_t *rightsp);
+int smbfs_smb_open(struct smbnode *np, const char *name, int nmlen,
+ int xattr, uint32_t rights, struct smb_cred *scrp,
+ uint16_t *fidp, uint32_t *rightsp, struct smbfattr *fap);
int smbfs_smb_tmpopen(struct smbnode *np, uint32_t rights,
struct smb_cred *scrp, uint16_t *fidp);
int smbfs_smb_close(struct smb_share *ssp, uint16_t fid,
struct timespec *mtime, struct smb_cred *scrp);
int smbfs_smb_tmpclose(struct smbnode *ssp, uint16_t fid,
struct smb_cred *scrp);
-int smbfs_smb_create(struct smbnode *dnp, const char *name, int len,
- struct smb_cred *scrp, uint16_t *fidp, uint32_t disp, int xattr);
+int smbfs_smb_create(struct smbnode *dnp, const char *name, int nmlen,
+ int xattr, uint32_t disp, struct smb_cred *scrp, uint16_t *fidp);
int smbfs_smb_delete(struct smbnode *np, struct smb_cred *scrp,
const char *name, int len, int xattr);
int smbfs_smb_rename(struct smbnode *src, struct smbnode *tdnp,
@@ -218,9 +215,9 @@ int smbfs_smb_setsec_m(struct smb_share *ssp, uint16_t fid,
struct smb_cred *scrp, uint32_t selector, mblk_t **mp);
int smbfs_getacl(vnode_t *vp, vsecattr_t *vsecattr,
- int *uidp, int *gidp, int flag, cred_t *cr);
+ uid_t *uidp, gid_t *gidp, int flag, cred_t *cr);
int smbfs_setacl(vnode_t *vp, vsecattr_t *vsecattr,
- int uid, int gid, int flag, cred_t *cr);
+ uid_t uid, gid_t gid, int flag, cred_t *cr);
int smbfs_getsd(vnode_t *vp, uint32_t sel, mblk_t **mp, cred_t *cr);
int smbfs_setsd(vnode_t *vp, uint32_t sel, mblk_t **mp, cred_t *cr);
@@ -238,33 +235,62 @@ int smbfs_smb_qstreaminfo(struct smbnode *np, struct smb_cred *scrp,
uio_t uio, size_t *sizep);
#endif /* NOT_YET */
-void smbfs_fname_tolocal(struct smbfs_fctx *ctx);
+/*
+ * VFS-level init, fini stuff
+ */
-void smb_time_local2server(struct timespec *tsp, int tzoff, long *seconds);
-void smb_time_server2local(ulong_t seconds, int tzoff, struct timespec *tsp);
-void smb_time_NT2local(uint64_t nsec, int tzoff, struct timespec *tsp);
-void smb_time_local2NT(struct timespec *tsp, int tzoff, uint64_t *nsec);
-void smb_time_unix2dos(struct timespec *tsp, int tzoff, uint16_t *ddp,
- uint16_t *dtp, uint8_t *dhp);
-void smb_dos2unixtime(uint_t dd, uint_t dt, uint_t dh, int tzoff,
- struct timespec *tsp);
-
-/* Stuff borrowed from NFS (and then hacked) */
-vnode_t *smbfs_make_node(vfs_t *vfsp,
- const char *dir, int dirlen,
- const char *name, int nmlen,
- char sep, struct smbfattr *fap);
-void smb_addfree(smbnode_t *sp);
-void smb_addhash(smbnode_t *sp);
-void smb_rmhash(smbnode_t *);
+int smbfs_vfsinit(void);
+void smbfs_vfsfini(void);
int smbfs_subrinit(void);
void smbfs_subrfini(void);
int smbfs_clntinit(void);
void smbfs_clntfini(void);
+
void smbfs_zonelist_add(smbmntinfo_t *smi);
void smbfs_zonelist_remove(smbmntinfo_t *smi);
+
+int smbfs_check_table(struct vfs *vfsp, struct smbnode *srp);
void smbfs_destroy_table(struct vfs *vfsp);
+void smbfs_rflush(struct vfs *vfsp, cred_t *cr);
+
+/*
+ * Function definitions - those having to do with
+ * smbfs nodes, vnodes, etc
+ */
+
+void smbfs_attrcache_prune(struct smbnode *np);
+void smbfs_attrcache_remove(struct smbnode *np);
+void smbfs_attrcache_rm_locked(struct smbnode *np);
+#ifndef DEBUG
+#define smbfs_attrcache_rm_locked(np) (np)->r_attrtime = gethrtime()
+#endif
+void smbfs_attr_touchdir(struct smbnode *dnp);
+void smbfs_attrcache_fa(vnode_t *vp, struct smbfattr *fap);
+void smbfs_cache_check(struct vnode *vp, struct smbfattr *fap);
+
+void smbfs_addfree(struct smbnode *sp);
+void smbfs_rmhash(struct smbnode *);
+
+/* See avl_create in smbfs_vfsops.c */
+void smbfs_init_hash_avl(avl_tree_t *);
+
+uint32_t smbfs_gethash(const char *rpath, int prlen);
+uint32_t smbfs_getino(struct smbnode *dnp, const char *name, int nmlen);
+
+extern struct smbfattr smbfs_fattr0;
+smbnode_t *smbfs_node_findcreate(smbmntinfo_t *mi,
+ const char *dir, int dirlen,
+ const char *name, int nmlen,
+ char sep, struct smbfattr *fap);
+
+int smbfs_nget(vnode_t *dvp, const char *name, int nmlen,
+ struct smbfattr *fap, vnode_t **vpp);
+
+void smbfs_fname_tolocal(struct smbfs_fctx *ctx);
+char *smbfs_name_alloc(const char *name, int nmlen);
+void smbfs_name_free(const char *name, int nmlen);
+
int smbfs_readvnode(vnode_t *, uio_t *, cred_t *, struct vattr *);
int smbfs_writevnode(vnode_t *vp, uio_t *uiop, cred_t *cr,
int ioflag, int timo);
diff --git a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_subr2.c b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_subr2.c
index a1c65b236f..0e787c0d2c 100644
--- a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_subr2.c
+++ b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_subr2.c
@@ -27,8 +27,9 @@
*/
/*
- * Node hash implementation borrowed from NFS.
- * See: uts/common/fs/nfs/nfs_subr.c
+ * Node hash implementation initially borrowed from NFS (nfs_subr.c)
+ * but then heavily modified. It's no longer an array of hash lists,
+ * but an AVL tree per mount point. More on this below.
*/
#include <sys/param.h>
@@ -39,14 +40,9 @@
#include <sys/dnlc.h>
#include <sys/kmem.h>
#include <sys/sunddi.h>
+#include <sys/sysmacros.h>
-#ifdef APPLE
-#include <sys/smb_apple.h>
-#include <sys/utfconv.h>
-#include <sys/smb_iconv.h>
-#else
#include <netsmb/smb_osdep.h>
-#endif
#include <netsmb/smb.h>
#include <netsmb/smb_conn.h>
@@ -58,62 +54,63 @@
#include <smbfs/smbfs_subr.h>
/*
- * The hash queues for the access to active and cached smbnodes
- * are organized as doubly linked lists. A reader/writer lock
- * for each hash bucket is used to control access and to synchronize
- * lookups, additions, and deletions from the hash queue.
+ * The AVL trees (now per-mount) allow finding an smbfs node by its
+ * full remote path name. It also allows easy traversal of all nodes
+ * below (path wise) any given node. A reader/writer lock for each
+ * (per mount) AVL tree is used to control access and to synchronize
+ * lookups, additions, and deletions from that AVL tree.
+ *
+ * Previously, this code use a global array of hash chains, each with
+ * its own rwlock. A few struct members, functions, and comments may
+ * still refer to a "hash", and those should all now be considered to
+ * refer to the per-mount AVL tree that replaced the old hash chains.
+ * (i.e. member smi_hash_lk, function sn_hashfind, etc.)
*
* The smbnode freelist is organized as a doubly linked list with
* a head pointer. Additions and deletions are synchronized via
* a single mutex.
*
- * In order to add an smbnode to the free list, it must be hashed into
- * a hash queue and the exclusive lock to the hash queue be held.
- * If an smbnode is not hashed into a hash queue, then it is destroyed
+ * In order to add an smbnode to the free list, it must be linked into
+ * the mount's AVL tree and the exclusive lock for the AVL must be held.
+ * If an smbnode is not linked into the AVL tree, then it is destroyed
* because it represents no valuable information that can be reused
- * about the file. The exclusive lock to the hash queue must be
- * held in order to prevent a lookup in the hash queue from finding
- * the smbnode and using it and assuming that the smbnode is not on the
- * freelist. The lookup in the hash queue will have the hash queue
- * locked, either exclusive or shared.
+ * about the file. The exclusive lock for the AVL tree must be held
+ * in order to prevent a lookup in the AVL tree from finding the
+ * smbnode and using it and assuming that the smbnode is not on the
+ * freelist. The lookup in the AVL tree will have the AVL tree lock
+ * held, either exclusive or shared.
*
* The vnode reference count for each smbnode is not allowed to drop
* below 1. This prevents external entities, such as the VM
* subsystem, from acquiring references to vnodes already on the
* freelist and then trying to place them back on the freelist
* when their reference is released. This means that the when an
- * smbnode is looked up in the hash queues, then either the smbnode
+ * smbnode is looked up in the AVL tree, then either the smbnode
* is removed from the freelist and that reference is tranfered to
* the new reference or the vnode reference count must be incremented
* accordingly. The mutex for the freelist must be held in order to
* accurately test to see if the smbnode is on the freelist or not.
- * The hash queue lock might be held shared and it is possible that
+ * The AVL tree lock might be held shared and it is possible that
* two different threads may race to remove the smbnode from the
* freelist. This race can be resolved by holding the mutex for the
* freelist. Please note that the mutex for the freelist does not
* need to held if the smbnode is not on the freelist. It can not be
* placed on the freelist due to the requirement that the thread
* putting the smbnode on the freelist must hold the exclusive lock
- * to the hash queue and the thread doing the lookup in the hash
- * queue is holding either a shared or exclusive lock to the hash
- * queue.
+ * for the AVL tree and the thread doing the lookup in the AVL tree
+ * is holding either a shared or exclusive lock for the AVL tree.
*
* The lock ordering is:
*
- * hash bucket lock -> vnode lock
- * hash bucket lock -> freelist lock
+ * AVL tree lock -> vnode lock
+ * AVL tree lock -> freelist lock
*/
-static rhashq_t *smbtable;
static kmutex_t smbfreelist_lock;
static smbnode_t *smbfreelist = NULL;
static ulong_t smbnodenew = 0;
long nsmbnode = 0;
-static int smbtablesize;
-static int smbtablemask;
-static int smbhashlen = 4;
-
static struct kmem_cache *smbnode_cache;
/*
@@ -125,19 +122,25 @@ kmutex_t smbfs_minor_lock;
int smbfs_major;
int smbfs_minor;
+/* See smbfs_node_findcreate() */
+struct smbfattr smbfs_fattr0;
+
/*
* Local functions.
- * Not static, to aid debugging.
+ * SN for Smb Node
*/
-void smb_rmfree(smbnode_t *);
-void smbinactive(smbnode_t *);
-void smb_rmhash_locked(smbnode_t *);
-void smb_destroy_node(smbnode_t *);
+static void sn_rmfree(smbnode_t *);
+static void sn_inactive(smbnode_t *);
+static void sn_addhash_locked(smbnode_t *, avl_index_t);
+static void sn_rmhash_locked(smbnode_t *);
+static void sn_destroy_node(smbnode_t *);
void smbfs_kmem_reclaim(void *cdrarg);
-smbnode_t *smbhashfind(struct vfs *, const char *, int, rhashq_t *);
-static vnode_t *make_smbnode(vfs_t *, char *, int, rhashq_t *, int *);
+static smbnode_t *
+sn_hashfind(smbmntinfo_t *, const char *, int, avl_index_t *);
+static smbnode_t *
+make_smbnode(smbmntinfo_t *, const char *, int, int *);
/*
* Free the resources associated with an smbnode.
@@ -145,135 +148,147 @@ static vnode_t *make_smbnode(vfs_t *, char *, int, rhashq_t *, int *);
*
* NFS: nfs_subr.c:rinactive
*/
-void
-smbinactive(smbnode_t *np)
+static void
+sn_inactive(smbnode_t *np)
{
+ cred_t *oldcr;
+ char *orpath;
+ int orplen;
- if (np->n_rpath) {
- kmem_free(np->n_rpath, np->n_rplen + 1);
- np->n_rpath = NULL;
- }
+ /*
+ * Flush and invalidate all pages (todo)
+ * Free any held credentials and caches...
+ * etc. (See NFS code)
+ */
+ mutex_enter(&np->r_statelock);
+
+ oldcr = np->r_cred;
+ np->r_cred = NULL;
+
+ orpath = np->n_rpath;
+ orplen = np->n_rplen;
+ np->n_rpath = NULL;
+ np->n_rplen = 0;
+
+ mutex_exit(&np->r_statelock);
+
+ if (oldcr != NULL)
+ crfree(oldcr);
+
+ if (orpath != NULL)
+ kmem_free(orpath, orplen + 1);
}
/*
- * Return a vnode for the given CIFS directory and filename.
- * If no smbnode exists for this fhandle, create one and put it
- * into the hash queues. If the smbnode for this fhandle
- * already exists, return it.
+ * Find and optionally create an smbnode for the passed
+ * mountinfo, directory, separator, and name. If the
+ * desired smbnode already exists, return a reference.
+ * If the file attributes pointer is non-null, the node
+ * is created if necessary and linked into the AVL tree.
+ *
+ * Callers that need a node created but don't have the
+ * real attributes pass smbfs_fattr0 to force creation.
*
- * Note: make_smbnode() may upgrade the hash bucket lock to exclusive.
+ * Note: make_smbnode() may upgrade the "hash" lock to exclusive.
*
* NFS: nfs_subr.c:makenfsnode
*/
-vnode_t *
-smbfs_make_node(
- vfs_t *vfsp,
- const char *dir,
+smbnode_t *
+smbfs_node_findcreate(
+ smbmntinfo_t *mi,
+ const char *dirnm,
int dirlen,
const char *name,
int nmlen,
char sep,
struct smbfattr *fap)
{
- char *rpath;
- int rplen, idx;
- uint32_t hash;
- rhashq_t *rhtp;
+ char tmpbuf[256];
+ size_t rpalloc;
+ char *p, *rpath;
+ int rplen;
smbnode_t *np;
vnode_t *vp;
-#ifdef NOT_YET
- vattr_t va;
-#endif
int newnode;
/*
- * Build the full path name in allocated memory
- * so we have it for lookup, etc. Note the
- * special case at the root (dir=="\\", dirlen==1)
- * where this does not add a slash separator.
- * To do that would make a double slash, which
- * has special meaning in CIFS.
- *
- * ToDo: Would prefer to allocate a remote path
- * only when we will create a new node.
+ * Build the search string, either in tmpbuf or
+ * in allocated memory if larger than tmpbuf.
*/
- if (dirlen <= 1 && sep == '\\')
- sep = '\0'; /* no slash */
-
- /* Compute the length of rpath and allocate. */
rplen = dirlen;
- if (sep)
+ if (sep != '\0')
rplen++;
- if (name)
- rplen += nmlen;
-
- rpath = kmem_alloc(rplen + 1, KM_SLEEP);
-
- /* Fill in rpath */
- bcopy(dir, rpath, dirlen);
- if (sep)
- rpath[dirlen++] = sep;
- if (name)
- bcopy(name, &rpath[dirlen], nmlen);
- rpath[rplen] = 0;
-
- hash = smbfs_hash(rpath, rplen);
- idx = hash & smbtablemask;
- rhtp = &smbtable[idx];
- rw_enter(&rhtp->r_lock, RW_READER);
-
- vp = make_smbnode(vfsp, rpath, rplen, rhtp, &newnode);
- np = VTOSMB(vp);
- np->n_ino = hash; /* Equivalent to: smbfs_getino() */
+ rplen += nmlen;
+ if (rplen < sizeof (tmpbuf)) {
+ /* use tmpbuf */
+ rpalloc = 0;
+ rpath = tmpbuf;
+ } else {
+ rpalloc = rplen + 1;
+ rpath = kmem_alloc(rpalloc, KM_SLEEP);
+ }
+ p = rpath;
+ bcopy(dirnm, p, dirlen);
+ p += dirlen;
+ if (sep != '\0')
+ *p++ = sep;
+ if (name != NULL) {
+ bcopy(name, p, nmlen);
+ p += nmlen;
+ }
+ ASSERT(p == rpath + rplen);
/*
- * Note: make_smbnode keeps a reference to rpath in
- * new nodes it creates, so only free when we found
- * an existing node.
+ * Find or create a node with this path.
*/
- if (!newnode) {
- kmem_free(rpath, rplen + 1);
- rpath = NULL;
- }
+ rw_enter(&mi->smi_hash_lk, RW_READER);
+ if (fap == NULL)
+ np = sn_hashfind(mi, rpath, rplen, NULL);
+ else
+ np = make_smbnode(mi, rpath, rplen, &newnode);
+ rw_exit(&mi->smi_hash_lk);
+
+ if (rpalloc)
+ kmem_free(rpath, rpalloc);
if (fap == NULL) {
-#ifdef NOT_YET
- if (newnode) {
- PURGE_ATTRCACHE(vp);
- }
-#endif
- rw_exit(&rhtp->r_lock);
- return (vp);
+ /*
+ * Caller is "just looking" (no create)
+ * so np may or may not be NULL here.
+ * Either way, we're done.
+ */
+ return (np);
}
- /* Have SMB attributes. */
- vp->v_type = (fap->fa_attr & SMB_FA_DIR) ? VDIR : VREG;
- /* XXX: np->n_ino = fap->fa_ino; see above */
- np->r_size = fap->fa_size;
- /* XXX: np->r_attr = *fap here instead? */
- np->r_atime = fap->fa_atime;
- np->r_ctime = fap->fa_ctime;
- np->r_mtime = fap->fa_mtime;
+ /*
+ * We should have a node, possibly created.
+ * Do we have (real) attributes to apply?
+ */
+ ASSERT(np != NULL);
+ if (fap == &smbfs_fattr0)
+ return (np);
-#ifdef NOT_YET
+ /*
+ * Apply the given attributes to this node,
+ * dealing with any cache impact, etc.
+ */
+ vp = SMBTOV(np);
if (!newnode) {
- rw_exit(&rhtp->r_lock);
- (void) nfs_cache_fattr(vp, attr, &va, t, cr);
- } else {
- if (attr->na_type < NFNON || attr->na_type > NFSOC)
- vp->v_type = VBAD;
- else
- vp->v_type = n2v_type(attr);
- vp->v_rdev = makedevice(attr->rdev.specdata1,
- attr->rdev.specdata2);
- nfs_attrcache(vp, attr, t);
- rw_exit(&rhtp->r_lock);
+ /*
+ * Found an existing node.
+ * Maybe purge caches...
+ */
+ smbfs_cache_check(vp, fap);
}
-#else
- rw_exit(&rhtp->r_lock);
-#endif
+ smbfs_attrcache_fa(vp, fap);
- return (vp);
+ /*
+ * Note NFS sets vp->v_type here, assuming it
+ * can never change for the life of a node.
+ * We allow v_type to change, and set it in
+ * smbfs_attrcache(). Also: mode, uid, gid
+ */
+ return (np);
}
/*
@@ -285,33 +300,32 @@ smbfs_make_node(
* Find or create an smbnode.
* NFS: nfs_subr.c:make_rnode
*/
-static vnode_t *
+static smbnode_t *
make_smbnode(
- vfs_t *vfsp,
- char *rpath,
+ smbmntinfo_t *mi,
+ const char *rpath,
int rplen,
- rhashq_t *rhtp,
int *newnode)
{
smbnode_t *np;
smbnode_t *tnp;
vnode_t *vp;
- smbmntinfo_t *mi;
+ vfs_t *vfsp;
+ avl_index_t where;
+ char *new_rpath = NULL;
- ASSERT(RW_READ_HELD(&rhtp->r_lock));
-
- mi = VFTOSMI(vfsp);
+ ASSERT(RW_READ_HELD(&mi->smi_hash_lk));
+ vfsp = mi->smi_vfsp;
start:
- np = smbhashfind(vfsp, rpath, rplen, rhtp);
+ np = sn_hashfind(mi, rpath, rplen, NULL);
if (np != NULL) {
- vp = SMBTOV(np);
*newnode = 0;
- return (vp);
+ return (np);
}
/* Note: will retake this lock below. */
- rw_exit(&rhtp->r_lock);
+ rw_exit(&mi->smi_hash_lk);
/*
* see if we can find something on the freelist
@@ -319,33 +333,36 @@ start:
mutex_enter(&smbfreelist_lock);
if (smbfreelist != NULL && smbnodenew >= nsmbnode) {
np = smbfreelist;
- smb_rmfree(np);
+ sn_rmfree(np);
mutex_exit(&smbfreelist_lock);
vp = SMBTOV(np);
if (np->r_flags & RHASHED) {
- rw_enter(&np->r_hashq->r_lock, RW_WRITER);
+ smbmntinfo_t *tmp_mi = np->n_mount;
+ ASSERT(tmp_mi != NULL);
+ rw_enter(&tmp_mi->smi_hash_lk, RW_WRITER);
mutex_enter(&vp->v_lock);
if (vp->v_count > 1) {
vp->v_count--;
mutex_exit(&vp->v_lock);
- rw_exit(&np->r_hashq->r_lock);
- rw_enter(&rhtp->r_lock, RW_READER);
+ rw_exit(&tmp_mi->smi_hash_lk);
+ /* start over */
+ rw_enter(&mi->smi_hash_lk, RW_READER);
goto start;
}
mutex_exit(&vp->v_lock);
- smb_rmhash_locked(np);
- rw_exit(&np->r_hashq->r_lock);
+ sn_rmhash_locked(np);
+ rw_exit(&tmp_mi->smi_hash_lk);
}
- smbinactive(np);
+ sn_inactive(np);
mutex_enter(&vp->v_lock);
if (vp->v_count > 1) {
vp->v_count--;
mutex_exit(&vp->v_lock);
- rw_enter(&rhtp->r_lock, RW_READER);
+ rw_enter(&mi->smi_hash_lk, RW_READER);
goto start;
}
mutex_exit(&vp->v_lock);
@@ -380,6 +397,13 @@ start:
vp = new_vp;
}
+ /*
+ * Allocate and copy the rpath we'll need below.
+ */
+ new_rpath = kmem_alloc(rplen + 1, KM_SLEEP);
+ bcopy(rpath, new_rpath, rplen);
+ new_rpath[rplen] = '\0';
+
/* Initialize smbnode_t */
bzero(np, sizeof (*np));
@@ -391,11 +415,11 @@ start:
np->r_vnode = vp;
np->n_mount = mi;
- np->r_hashq = rhtp;
+
np->n_fid = SMB_FID_UNUSED;
- np->n_uid = UID_NOBODY;
- np->n_gid = GID_NOBODY;
- /* XXX: make attributes stale? */
+ np->n_uid = mi->smi_uid;
+ np->n_gid = mi->smi_gid;
+ /* Leave attributes "stale." */
#if 0 /* XXX dircache */
/*
@@ -414,77 +438,94 @@ start:
vp->v_type = VNON;
/*
- * There is a race condition if someone else
- * alloc's the smbnode while no locks are held, so we
- * check again and recover if found.
+ * We entered with mi->smi_hash_lk held (reader).
+ * Retake it now, (as the writer).
+ * Will return with it held.
*/
- rw_enter(&rhtp->r_lock, RW_WRITER);
- tnp = smbhashfind(vfsp, rpath, rplen, rhtp);
+ rw_enter(&mi->smi_hash_lk, RW_WRITER);
+
+ /*
+ * There is a race condition where someone else
+ * may alloc the smbnode while no locks are held,
+ * so check again and recover if found.
+ */
+ tnp = sn_hashfind(mi, rpath, rplen, &where);
if (tnp != NULL) {
- vp = SMBTOV(tnp);
+ /*
+ * Lost the race. Put the node we were building
+ * on the free list and return the one we found.
+ */
+ rw_exit(&mi->smi_hash_lk);
+ kmem_free(new_rpath, rplen + 1);
+ smbfs_addfree(np);
+ rw_enter(&mi->smi_hash_lk, RW_READER);
*newnode = 0;
- rw_exit(&rhtp->r_lock);
- /* The node we were building goes on the free list. */
- smb_addfree(np);
- rw_enter(&rhtp->r_lock, RW_READER);
- return (vp);
+ return (tnp);
}
/*
- * Hash search identifies nodes by the full pathname,
- * so store that before linking in the hash list.
- * Note: caller allocates the rpath, and knows
- * about this reference when *newnode is set.
+ * Hash search identifies nodes by the remote path
+ * (n_rpath) so fill that in now, before linking
+ * this node into the node cache (AVL tree).
*/
- np->n_rpath = rpath;
+ np->n_rpath = new_rpath;
np->n_rplen = rplen;
+ np->n_ino = smbfs_gethash(new_rpath, rplen);
- smb_addhash(np);
+ sn_addhash_locked(np, where);
*newnode = 1;
- return (vp);
+ return (np);
}
/*
- * smb_addfree
- * Put a smbnode on the free list.
+ * smbfs_addfree
+ * Put an smbnode on the free list, or destroy it immediately
+ * if it offers no value were it to be reclaimed later. Also
+ * destroy immediately when we have too many smbnodes, etc.
*
* Normally called by smbfs_inactive, but also
* called in here during cleanup operations.
*
- * Smbnodes which were allocated above and beyond the normal limit
- * are immediately freed.
- *
* NFS: nfs_subr.c:rp_addfree
*/
void
-smb_addfree(smbnode_t *np)
+smbfs_addfree(smbnode_t *np)
{
vnode_t *vp;
struct vfs *vfsp;
+ smbmntinfo_t *mi;
+
+ ASSERT(np->r_freef == NULL && np->r_freeb == NULL);
vp = SMBTOV(np);
ASSERT(vp->v_count >= 1);
- ASSERT(np->r_freef == NULL && np->r_freeb == NULL);
+
+ vfsp = vp->v_vfsp;
+ mi = VFTOSMI(vfsp);
/*
- * If we have too many smbnodes allocated and there are no
- * references to this smbnode, or if the smbnode is no longer
- * accessible by it does not reside in the hash queues,
- * or if an i/o error occurred while writing to the file,
- * then just free it instead of putting it on the smbnode
- * freelist.
+ * If there are no more references to this smbnode and:
+ * we have too many smbnodes allocated, or if the node
+ * is no longer accessible via the AVL tree (!RHASHED),
+ * or an i/o error occurred while writing to the file,
+ * or it's part of an unmounted FS, then try to destroy
+ * it instead of putting it on the smbnode freelist.
*/
- vfsp = vp->v_vfsp;
- if (((smbnodenew > nsmbnode || !(np->r_flags & RHASHED) ||
- np->r_error || (vfsp->vfs_flag & VFS_UNMOUNTED)) &&
- np->r_count == 0)) {
+ if (np->r_count == 0 && (
+ (np->r_flags & RHASHED) == 0 ||
+ (np->r_error != 0) ||
+ (vfsp->vfs_flag & VFS_UNMOUNTED) ||
+ (smbnodenew > nsmbnode))) {
+
+ /* Try to destroy this node. */
+
if (np->r_flags & RHASHED) {
- rw_enter(&np->r_hashq->r_lock, RW_WRITER);
+ rw_enter(&mi->smi_hash_lk, RW_WRITER);
mutex_enter(&vp->v_lock);
if (vp->v_count > 1) {
vp->v_count--;
mutex_exit(&vp->v_lock);
- rw_exit(&np->r_hashq->r_lock);
+ rw_exit(&mi->smi_hash_lk);
return;
/*
* Will get another call later,
@@ -492,23 +533,23 @@ smb_addfree(smbnode_t *np)
*/
}
mutex_exit(&vp->v_lock);
- smb_rmhash_locked(np);
- rw_exit(&np->r_hashq->r_lock);
+ sn_rmhash_locked(np);
+ rw_exit(&mi->smi_hash_lk);
}
- smbinactive(np);
+ sn_inactive(np);
/*
* Recheck the vnode reference count. We need to
* make sure that another reference has not been
* acquired while we were not holding v_lock. The
- * smbnode is not in the smbnode hash queues, so the
- * only way for a reference to have been acquired
+ * smbnode is not in the smbnode "hash" AVL tree, so
+ * the only way for a reference to have been acquired
* is for a VOP_PUTPAGE because the smbnode was marked
- * with RDIRTY or for a modified page. This
+ * with RDIRTY or for a modified page. This vnode
* reference may have been acquired before our call
- * to smbinactive. The i/o may have been completed,
- * thus allowing smbinactive to complete, but the
+ * to sn_inactive. The i/o may have been completed,
+ * thus allowing sn_inactive to complete, but the
* reference to the vnode may not have been released
* yet. In any case, the smbnode can not be destroyed
* until the other references to this vnode have been
@@ -525,33 +566,31 @@ smb_addfree(smbnode_t *np)
}
mutex_exit(&vp->v_lock);
- smb_destroy_node(np);
+ sn_destroy_node(np);
return;
}
+
/*
- * Lock the hash queue and then recheck the reference count
+ * Lock the AVL tree and then recheck the reference count
* to ensure that no other threads have acquired a reference
* to indicate that the smbnode should not be placed on the
* freelist. If another reference has been acquired, then
* just release this one and let the other thread complete
* the processing of adding this smbnode to the freelist.
*/
- rw_enter(&np->r_hashq->r_lock, RW_WRITER);
+ rw_enter(&mi->smi_hash_lk, RW_WRITER);
mutex_enter(&vp->v_lock);
if (vp->v_count > 1) {
vp->v_count--;
mutex_exit(&vp->v_lock);
- rw_exit(&np->r_hashq->r_lock);
+ rw_exit(&mi->smi_hash_lk);
return;
}
mutex_exit(&vp->v_lock);
/*
- * If there is no cached data or metadata for this file, then
- * put the smbnode on the front of the freelist so that it will
- * be reused before other smbnodes which may have cached data or
- * metadata associated with them.
+ * Put this node on the free list.
*/
mutex_enter(&smbfreelist_lock);
if (smbfreelist == NULL) {
@@ -566,7 +605,7 @@ smb_addfree(smbnode_t *np)
}
mutex_exit(&smbfreelist_lock);
- rw_exit(&np->r_hashq->r_lock);
+ rw_exit(&mi->smi_hash_lk);
}
/*
@@ -577,8 +616,8 @@ smb_addfree(smbnode_t *np)
*
* NFS: nfs_subr.c:rp_rmfree
*/
-void
-smb_rmfree(smbnode_t *np)
+static void
+sn_rmfree(smbnode_t *np)
{
ASSERT(MUTEX_HELD(&smbfreelist_lock));
@@ -597,23 +636,21 @@ smb_rmfree(smbnode_t *np)
}
/*
- * Put a smbnode in the hash table.
+ * Put an smbnode in the "hash" AVL tree.
*
- * The caller must be holding the exclusive hash queue lock.
+ * The caller must be hold the rwlock as writer.
*
* NFS: nfs_subr.c:rp_addhash
*/
-void
-smb_addhash(smbnode_t *np)
+static void
+sn_addhash_locked(smbnode_t *np, avl_index_t where)
{
+ smbmntinfo_t *mi = np->n_mount;
- ASSERT(RW_WRITE_HELD(&np->r_hashq->r_lock));
+ ASSERT(RW_WRITE_HELD(&mi->smi_hash_lk));
ASSERT(!(np->r_flags & RHASHED));
- np->r_hashf = np->r_hashq->r_hashf;
- np->r_hashq->r_hashf = np;
- np->r_hashb = (smbnode_t *)np->r_hashq;
- np->r_hashf->r_hashb = np;
+ avl_insert(&mi->smi_hash_avl, np, where);
mutex_enter(&np->r_statelock);
np->r_flags |= RHASHED;
@@ -621,21 +658,21 @@ smb_addhash(smbnode_t *np)
}
/*
- * Remove a smbnode from the hash table.
+ * Remove an smbnode from the "hash" AVL tree.
*
- * The caller must be holding the hash queue lock.
+ * The caller must hold the rwlock as writer.
*
* NFS: nfs_subr.c:rp_rmhash_locked
*/
-void
-smb_rmhash_locked(smbnode_t *np)
+static void
+sn_rmhash_locked(smbnode_t *np)
{
+ smbmntinfo_t *mi = np->n_mount;
- ASSERT(RW_WRITE_HELD(&np->r_hashq->r_lock));
+ ASSERT(RW_WRITE_HELD(&mi->smi_hash_lk));
ASSERT(np->r_flags & RHASHED);
- np->r_hashb->r_hashf = np->r_hashf;
- np->r_hashf->r_hashb = np->r_hashb;
+ avl_remove(&mi->smi_hash_avl, np);
mutex_enter(&np->r_statelock);
np->r_flags &= ~RHASHED;
@@ -643,83 +680,177 @@ smb_rmhash_locked(smbnode_t *np)
}
/*
- * Remove a smbnode from the hash table.
+ * Remove an smbnode from the "hash" AVL tree.
*
- * The caller must not be holding the hash queue lock.
+ * The caller must not be holding the rwlock.
*/
void
-smb_rmhash(smbnode_t *np)
+smbfs_rmhash(smbnode_t *np)
{
+ smbmntinfo_t *mi = np->n_mount;
- rw_enter(&np->r_hashq->r_lock, RW_WRITER);
- smb_rmhash_locked(np);
- rw_exit(&np->r_hashq->r_lock);
+ rw_enter(&mi->smi_hash_lk, RW_WRITER);
+ sn_rmhash_locked(np);
+ rw_exit(&mi->smi_hash_lk);
}
/*
- * Lookup a smbnode by fhandle.
+ * Lookup an smbnode by remote pathname
*
- * The caller must be holding the hash queue lock, either shared or exclusive.
- * XXX: make static?
+ * The caller must be holding the AVL rwlock, either shared or exclusive.
*
* NFS: nfs_subr.c:rfind
*/
-smbnode_t *
-smbhashfind(
- struct vfs *vfsp,
+static smbnode_t *
+sn_hashfind(
+ smbmntinfo_t *mi,
const char *rpath,
int rplen,
- rhashq_t *rhtp)
+ avl_index_t *pwhere) /* optional */
{
+ smbfs_node_hdr_t nhdr;
smbnode_t *np;
vnode_t *vp;
- ASSERT(RW_LOCK_HELD(&rhtp->r_lock));
+ ASSERT(RW_LOCK_HELD(&mi->smi_hash_lk));
- for (np = rhtp->r_hashf; np != (smbnode_t *)rhtp; np = np->r_hashf) {
- vp = SMBTOV(np);
- if (vp->v_vfsp == vfsp &&
- np->n_rplen == rplen &&
- bcmp(np->n_rpath, rpath, rplen) == 0) {
- /*
- * remove smbnode from free list, if necessary.
- */
- if (np->r_freef != NULL) {
- mutex_enter(&smbfreelist_lock);
- /*
- * If the smbnode is on the freelist,
- * then remove it and use that reference
- * as the new reference. Otherwise,
- * need to increment the reference count.
- */
- if (np->r_freef != NULL) {
- smb_rmfree(np);
- mutex_exit(&smbfreelist_lock);
- } else {
- mutex_exit(&smbfreelist_lock);
- VN_HOLD(vp);
- }
- } else
- VN_HOLD(vp);
- return (np);
+ bzero(&nhdr, sizeof (nhdr));
+ nhdr.hdr_n_rpath = (char *)rpath;
+ nhdr.hdr_n_rplen = rplen;
+
+ /* See smbfs_node_cmp below. */
+ np = avl_find(&mi->smi_hash_avl, &nhdr, pwhere);
+
+ if (np == NULL)
+ return (NULL);
+
+ /*
+ * Found it in the "hash" AVL tree.
+ * Remove from free list, if necessary.
+ */
+ vp = SMBTOV(np);
+ if (np->r_freef != NULL) {
+ mutex_enter(&smbfreelist_lock);
+ /*
+ * If the smbnode is on the freelist,
+ * then remove it and use that reference
+ * as the new reference. Otherwise,
+ * need to increment the reference count.
+ */
+ if (np->r_freef != NULL) {
+ sn_rmfree(np);
+ mutex_exit(&smbfreelist_lock);
+ } else {
+ mutex_exit(&smbfreelist_lock);
+ VN_HOLD(vp);
}
+ } else
+ VN_HOLD(vp);
+
+ return (np);
+}
+
+static int
+smbfs_node_cmp(const void *va, const void *vb)
+{
+ const smbfs_node_hdr_t *a = va;
+ const smbfs_node_hdr_t *b = vb;
+ int clen, diff;
+
+ /*
+ * Same semantics as strcmp, but does not
+ * assume the strings are null terminated.
+ */
+ clen = (a->hdr_n_rplen < b->hdr_n_rplen) ?
+ a->hdr_n_rplen : b->hdr_n_rplen;
+ diff = strncmp(a->hdr_n_rpath, b->hdr_n_rpath, clen);
+ if (diff < 0)
+ return (-1);
+ if (diff > 0)
+ return (1);
+ /* they match through clen */
+ if (b->hdr_n_rplen > clen)
+ return (-1);
+ if (a->hdr_n_rplen > clen)
+ return (1);
+ return (0);
+}
+
+/*
+ * Setup the "hash" AVL tree used for our node cache.
+ * See: smbfs_mount, smbfs_destroy_table.
+ */
+void
+smbfs_init_hash_avl(avl_tree_t *avl)
+{
+ avl_create(avl, smbfs_node_cmp, sizeof (smbnode_t),
+ offsetof(smbnode_t, r_avl_node));
+}
+
+/*
+ * Invalidate the cached attributes for all nodes "under" the
+ * passed-in node. Note: the passed-in node is NOT affected by
+ * this call. This is used both for files under some directory
+ * after the directory is deleted or renamed, and for extended
+ * attribute files (named streams) under a plain file after that
+ * file is renamed or deleted.
+ *
+ * Do this by walking the AVL tree starting at the passed in node,
+ * and continuing while the visited nodes have a path prefix matching
+ * the entire path of the passed-in node, and a separator just after
+ * that matching path prefix. Watch out for cases where the AVL tree
+ * order may not exactly match the order of an FS walk, i.e.
+ * consider this sequence:
+ * "foo" (directory)
+ * "foo bar" (name containing a space)
+ * "foo/bar"
+ * The walk needs to skip "foo bar" and keep going until it finds
+ * something that doesn't match the "foo" name prefix.
+ */
+void
+smbfs_attrcache_prune(smbnode_t *top_np)
+{
+ smbmntinfo_t *mi;
+ smbnode_t *np;
+ char *rpath;
+ int rplen;
+
+ mi = top_np->n_mount;
+ rw_enter(&mi->smi_hash_lk, RW_READER);
+
+ np = top_np;
+ rpath = top_np->n_rpath;
+ rplen = top_np->n_rplen;
+ for (;;) {
+ np = avl_walk(&mi->smi_hash_avl, np, AVL_AFTER);
+ if (np == NULL)
+ break;
+ if (np->n_rplen < rplen)
+ break;
+ if (0 != strncmp(np->n_rpath, rpath, rplen))
+ break;
+ if (np->n_rplen > rplen && (
+ np->n_rpath[rplen] == ':' ||
+ np->n_rpath[rplen] == '\\'))
+ smbfs_attrcache_remove(np);
}
- return (NULL);
+
+ rw_exit(&mi->smi_hash_lk);
}
#ifdef SMB_VNODE_DEBUG
-int smb_check_table_debug = 1;
+int smbfs_check_table_debug = 1;
#else /* SMB_VNODE_DEBUG */
-int smb_check_table_debug = 0;
+int smbfs_check_table_debug = 0;
#endif /* SMB_VNODE_DEBUG */
/*
* Return 1 if there is a active vnode belonging to this vfs in the
- * smbtable cache.
+ * smbnode cache.
*
* Several of these checks are done without holding the usual
- * locks. This is safe because destroy_smbtable(), smb_addfree(),
+ * locks. This is safe because destroy_smbtable(), smbfs_addfree(),
* etc. will redo the necessary checks before actually destroying
* any smbnodes.
*
@@ -729,117 +860,148 @@ int smb_check_table_debug = 0;
* Relatively harmless, so left 'em in.
*/
int
-smb_check_table(struct vfs *vfsp, smbnode_t *rtnp)
+smbfs_check_table(struct vfs *vfsp, smbnode_t *rtnp)
{
+ smbmntinfo_t *mi;
smbnode_t *np;
vnode_t *vp;
- int index;
int busycnt = 0;
- for (index = 0; index < smbtablesize; index++) {
- rw_enter(&smbtable[index].r_lock, RW_READER);
- for (np = smbtable[index].r_hashf;
- np != (smbnode_t *)(&smbtable[index]);
- np = np->r_hashf) {
- if (np == rtnp)
- continue; /* skip the root */
- vp = SMBTOV(np);
- if (vp->v_vfsp != vfsp)
- continue; /* skip other mount */
-
- /* Now the 'busy' checks: */
- /* Not on the free list? */
- if (np->r_freef == NULL) {
- SMBVDEBUG("!r_freef: node=0x%p, v_path=%s\n",
- (void *)np, vp->v_path);
- busycnt++;
- }
+ mi = VFTOSMI(vfsp);
+ rw_enter(&mi->smi_hash_lk, RW_READER);
+ for (np = avl_first(&mi->smi_hash_avl); np != NULL;
+ np = avl_walk(&mi->smi_hash_avl, np, AVL_AFTER)) {
- /* Has dirty pages? */
- if (vn_has_cached_data(vp) &&
- (np->r_flags & RDIRTY)) {
- SMBVDEBUG("is dirty: node=0x%p, v_path=%s\n",
- (void *)np, vp->v_path);
- busycnt++;
- }
+ if (np == rtnp)
+ continue; /* skip the root */
+ vp = SMBTOV(np);
- /* Other refs? (not reflected in v_count) */
- if (np->r_count > 0) {
- SMBVDEBUG("+r_count: node=0x%p, v_path=%s\n",
- (void *)np, vp->v_path);
- busycnt++;
- }
+ /* Now the 'busy' checks: */
+ /* Not on the free list? */
+ if (np->r_freef == NULL) {
+ SMBVDEBUG("!r_freef: node=0x%p, rpath=%s\n",
+ (void *)np, np->n_rpath);
+ busycnt++;
+ }
- if (busycnt && !smb_check_table_debug)
- break;
+ /* Has dirty pages? */
+ if (vn_has_cached_data(vp) &&
+ (np->r_flags & RDIRTY)) {
+ SMBVDEBUG("is dirty: node=0x%p, rpath=%s\n",
+ (void *)np, np->n_rpath);
+ busycnt++;
+ }
+ /* Other refs? (not reflected in v_count) */
+ if (np->r_count > 0) {
+ SMBVDEBUG("+r_count: node=0x%p, rpath=%s\n",
+ (void *)np, np->n_rpath);
+ busycnt++;
}
- rw_exit(&smbtable[index].r_lock);
+
+ if (busycnt && !smbfs_check_table_debug)
+ break;
+
}
+ rw_exit(&mi->smi_hash_lk);
+
return (busycnt);
}
/*
- * Destroy inactive vnodes from the hash queues which belong to this
+ * Destroy inactive vnodes from the AVL tree which belong to this
* vfs. It is essential that we destroy all inactive vnodes during a
* forced unmount as well as during a normal unmount.
*
* NFS: nfs_subr.c:destroy_rtable
+ *
+ * In here, we're normally destrying all or most of the AVL tree,
+ * so the natural choice is to use avl_destroy_nodes. However,
+ * there may be a few busy nodes that should remain in the AVL
+ * tree when we're done. The solution: use a temporary tree to
+ * hold the busy nodes until we're done destroying the old tree,
+ * then copy the temporary tree over the (now emtpy) real tree.
*/
void
smbfs_destroy_table(struct vfs *vfsp)
{
- int index;
+ avl_tree_t tmp_avl;
+ smbmntinfo_t *mi;
smbnode_t *np;
smbnode_t *rlist;
- smbnode_t *r_hashf;
- vnode_t *vp;
+ void *v;
+ mi = VFTOSMI(vfsp);
rlist = NULL;
+ smbfs_init_hash_avl(&tmp_avl);
- for (index = 0; index < smbtablesize; index++) {
- rw_enter(&smbtable[index].r_lock, RW_WRITER);
- for (np = smbtable[index].r_hashf;
- np != (smbnode_t *)(&smbtable[index]);
- np = r_hashf) {
- /* save the hash pointer before destroying */
- r_hashf = np->r_hashf;
- vp = SMBTOV(np);
- if (vp->v_vfsp == vfsp) {
- mutex_enter(&smbfreelist_lock);
- if (np->r_freef != NULL) {
- smb_rmfree(np);
- mutex_exit(&smbfreelist_lock);
- smb_rmhash_locked(np);
- np->r_hashf = rlist;
- rlist = np;
- } else
- mutex_exit(&smbfreelist_lock);
- }
+ rw_enter(&mi->smi_hash_lk, RW_WRITER);
+ v = NULL;
+ while ((np = avl_destroy_nodes(&mi->smi_hash_avl, &v)) != NULL) {
+
+ mutex_enter(&smbfreelist_lock);
+ if (np->r_freef == NULL) {
+ /*
+ * Busy node (not on the free list).
+ * Will keep in the final AVL tree.
+ */
+ mutex_exit(&smbfreelist_lock);
+ avl_add(&tmp_avl, np);
+ } else {
+ /*
+ * It's on the free list. Remove and
+ * arrange for it to be destroyed.
+ */
+ sn_rmfree(np);
+ mutex_exit(&smbfreelist_lock);
+
+ /*
+ * Last part of sn_rmhash_locked().
+ * NB: avl_destroy_nodes has already
+ * removed this from the "hash" AVL.
+ */
+ mutex_enter(&np->r_statelock);
+ np->r_flags &= ~RHASHED;
+ mutex_exit(&np->r_statelock);
+
+ /*
+ * Add to the list of nodes to destroy.
+ * Borrowing avl_child[0] for this list.
+ */
+ np->r_avl_node.avl_child[0] =
+ (struct avl_node *)rlist;
+ rlist = np;
}
- rw_exit(&smbtable[index].r_lock);
}
+ avl_destroy(&mi->smi_hash_avl);
- for (np = rlist; np != NULL; np = rlist) {
- rlist = np->r_hashf;
- /*
- * This call to smb_addfree will end up destroying the
- * smbnode, but in a safe way with the appropriate set
- * of checks done.
- */
- smb_addfree(np);
- }
+ /*
+ * Replace the (now destroyed) "hash" AVL with the
+ * temporary AVL, which restores the busy nodes.
+ */
+ mi->smi_hash_avl = tmp_avl;
+ rw_exit(&mi->smi_hash_lk);
+ /*
+ * Now destroy the nodes on our temporary list (rlist).
+ * This call to smbfs_addfree will end up destroying the
+ * smbnode, but in a safe way with the appropriate set
+ * of checks done.
+ */
+ while ((np = rlist) != NULL) {
+ rlist = (smbnode_t *)np->r_avl_node.avl_child[0];
+ smbfs_addfree(np);
+ }
}
/*
* This routine destroys all the resources associated with the smbnode
- * and then the smbnode itself.
+ * and then the smbnode itself. Note: sn_inactive has been called.
*
* NFS: nfs_subr.c:destroy_rnode
*/
-void
-smb_destroy_node(smbnode_t *np)
+static void
+sn_destroy_node(smbnode_t *np)
{
vnode_t *vp;
vfs_t *vfsp;
@@ -850,6 +1012,8 @@ smb_destroy_node(smbnode_t *np)
ASSERT(vp->v_count == 1);
ASSERT(np->r_count == 0);
ASSERT(np->r_mapcnt == 0);
+ ASSERT(np->r_cred == NULL);
+ ASSERT(np->n_rpath == NULL);
ASSERT(!(np->r_flags & RHASHED));
ASSERT(np->r_freef == NULL && np->r_freeb == NULL);
atomic_add_long((ulong_t *)&smbnodenew, -1);
@@ -859,7 +1023,17 @@ smb_destroy_node(smbnode_t *np)
VFS_RELE(vfsp);
}
-/* rflush? */
+/*
+ * Flush all vnodes in this (or every) vfs.
+ * Used by nfs_sync and by nfs_unmount.
+ */
+/*ARGSUSED*/
+void
+smbfs_rflush(struct vfs *vfsp, cred_t *cr)
+{
+ /* Todo: mmap support. */
+}
+
/* access cache */
/* client handles */
@@ -867,17 +1041,15 @@ smb_destroy_node(smbnode_t *np)
* initialize resources that are used by smbfs_subr.c
* this is called from the _init() routine (by the way of smbfs_clntinit())
*
- * allocate and initialze smbfs hash table
* NFS: nfs_subr.c:nfs_subrinit
*/
int
smbfs_subrinit(void)
{
- int i;
ulong_t nsmbnode_max;
/*
- * Allocate and initialize the smbnode hash queues
+ * Allocate and initialize the smbnode cache
*/
if (nsmbnode <= 0)
nsmbnode = ncsize; /* dnlc.h */
@@ -889,14 +1061,6 @@ smbfs_subrinit(void)
nsmbnode = nsmbnode_max;
}
- smbtablesize = 1 << highbit(nsmbnode / smbhashlen);
- smbtablemask = smbtablesize - 1;
- smbtable = kmem_alloc(smbtablesize * sizeof (*smbtable), KM_SLEEP);
- for (i = 0; i < smbtablesize; i++) {
- smbtable[i].r_hashf = (smbnode_t *)(&smbtable[i]);
- smbtable[i].r_hashb = (smbnode_t *)(&smbtable[i]);
- rw_init(&smbtable[i].r_lock, NULL, RW_DEFAULT, NULL);
- }
smbnode_cache = kmem_cache_create("smbnode_cache", sizeof (smbnode_t),
0, NULL, NULL, smbfs_kmem_reclaim, NULL, NULL, 0);
@@ -926,17 +1090,12 @@ smbfs_subrinit(void)
void
smbfs_subrfini(void)
{
- int i;
/*
- * Deallocate the smbnode hash queues
+ * Destroy the smbnode cache
*/
kmem_cache_destroy(smbnode_cache);
- for (i = 0; i < smbtablesize; i++)
- rw_destroy(&smbtable[i].r_lock);
- kmem_free(smbtable, smbtablesize * sizeof (*smbtable));
-
/*
* Destroy the various mutexes and reader/writer locks
*/
@@ -950,43 +1109,42 @@ smbfs_subrfini(void)
* Support functions for smbfs_kmem_reclaim
*/
-static int
+static void
smbfs_node_reclaim(void)
{
- int freed;
+ smbmntinfo_t *mi;
smbnode_t *np;
vnode_t *vp;
- freed = 0;
mutex_enter(&smbfreelist_lock);
while ((np = smbfreelist) != NULL) {
- smb_rmfree(np);
+ sn_rmfree(np);
mutex_exit(&smbfreelist_lock);
if (np->r_flags & RHASHED) {
vp = SMBTOV(np);
- rw_enter(&np->r_hashq->r_lock, RW_WRITER);
+ mi = np->n_mount;
+ rw_enter(&mi->smi_hash_lk, RW_WRITER);
mutex_enter(&vp->v_lock);
if (vp->v_count > 1) {
vp->v_count--;
mutex_exit(&vp->v_lock);
- rw_exit(&np->r_hashq->r_lock);
+ rw_exit(&mi->smi_hash_lk);
mutex_enter(&smbfreelist_lock);
continue;
}
mutex_exit(&vp->v_lock);
- smb_rmhash_locked(np);
- rw_exit(&np->r_hashq->r_lock);
+ sn_rmhash_locked(np);
+ rw_exit(&mi->smi_hash_lk);
}
/*
- * This call to smb_addfree will end up destroying the
+ * This call to smbfs_addfree will end up destroying the
* smbnode, but in a safe way with the appropriate set
* of checks done.
*/
- smb_addfree(np);
+ smbfs_addfree(np);
mutex_enter(&smbfreelist_lock);
}
mutex_exit(&smbfreelist_lock);
- return (freed);
}
/*
@@ -999,7 +1157,7 @@ smbfs_node_reclaim(void)
void
smbfs_kmem_reclaim(void *cdrarg)
{
- (void) smbfs_node_reclaim();
+ smbfs_node_reclaim();
}
/* nfs failover stuff */
diff --git a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_vfsops.c b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_vfsops.c
index b616543a92..d33b0ee0a1 100644
--- a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_vfsops.c
+++ b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_vfsops.c
@@ -39,6 +39,7 @@
#include <sys/systm.h>
#include <sys/cred.h>
+#include <sys/time.h>
#include <sys/vfs.h>
#include <sys/vnode.h>
#include <fs/fs_subr.h>
@@ -173,7 +174,7 @@ static void smbfs_freevfs(vfs_t *);
int
_init(void)
{
- int status;
+ int error;
/*
* Check compiled-in version of "nsmb"
@@ -186,13 +187,30 @@ _init(void)
smbfs_mountcount = 0;
- if ((status = smbfs_clntinit()) != 0) {
+ /*
+ * NFS calls these two in _clntinit
+ * Easier to follow this way.
+ */
+ if ((error = smbfs_subrinit()) != 0) {
+ cmn_err(CE_WARN, "_init: smbfs_subrinit failed");
+ return (error);
+ }
+
+ if ((error = smbfs_vfsinit()) != 0) {
+ cmn_err(CE_WARN, "_init: smbfs_vfsinit failed");
+ smbfs_subrfini();
+ return (error);
+ }
+
+ if ((error = smbfs_clntinit()) != 0) {
cmn_err(CE_WARN, "_init: smbfs_clntinit failed");
- return (status);
+ smbfs_vfsfini();
+ smbfs_subrfini();
+ return (error);
}
- status = mod_install((struct modlinkage *)&modlinkage);
- return (status);
+ error = mod_install((struct modlinkage *)&modlinkage);
+ return (error);
}
/*
@@ -222,6 +240,10 @@ _fini(void)
*/
smbfs_clntfini();
+ /* NFS calls these two in _clntfini */
+ smbfs_vfsfini();
+ smbfs_subrfini();
+
/*
* Free the ops vectors
*/
@@ -298,10 +320,21 @@ smbfsfini()
void
smbfs_free_smi(smbmntinfo_t *smi)
{
- if (smi) {
- smbfs_zonelist_remove(smi);
- kmem_free(smi, sizeof (smbmntinfo_t));
- }
+ if (smi == NULL)
+ return;
+
+ if (smi->smi_zone != NULL)
+ zone_rele(smi->smi_zone);
+
+ if (smi->smi_share != NULL)
+ smb_share_rele(smi->smi_share);
+
+ avl_destroy(&smi->smi_hash_avl);
+ rw_destroy(&smi->smi_hash_lk);
+ cv_destroy(&smi->smi_statvfs_cv);
+ mutex_destroy(&smi->smi_lock);
+
+ kmem_free(smi, sizeof (smbmntinfo_t));
}
/*
@@ -313,7 +346,7 @@ smbfs_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr)
{
char *data = uap->dataptr;
int error;
- vnode_t *rtvp = NULL; /* root of this fs */
+ smbnode_t *rtnp = NULL; /* root of this fs */
smbmntinfo_t *smi = NULL;
dev_t smbfs_dev;
int version;
@@ -322,6 +355,7 @@ smbfs_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr)
zone_t *mntzone = NULL;
smb_share_t *ssp = NULL;
smb_cred_t scred;
+ int flags, sec;
STRUCT_DECL(smbfs_args, args); /* smbfs mount arguments */
@@ -336,8 +370,6 @@ smbfs_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr)
*
* uap->datalen might be different from sizeof (args)
* in a compatible situation.
- *
- * XXX - todo: handle mount options string
*/
STRUCT_INIT(args, get_udatamodel());
bzero(STRUCT_BUF(args), SIZEOF_STRUCT(smbfs_args, DATAMODEL_NATIVE));
@@ -356,6 +388,9 @@ smbfs_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr)
return (EINVAL);
}
+ /*
+ * Deal with re-mount requests.
+ */
if (uap->flags & MS_REMOUNT) {
cmn_err(CE_WARN, "MS_REMOUNT not implemented");
return (ENOTSUP);
@@ -386,11 +421,9 @@ smbfs_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr)
return (error);
}
- smb_credinit(&scred, cr);
-
/*
* Use "goto errout" from here on.
- * See: ssp, smi, rtvp, mntzone
+ * See: ssp, smi, rtnp, mntzone
*/
/*
@@ -437,41 +470,93 @@ smbfs_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr)
}
}
- /*
- * Get root vnode.
- */
-proceed:
+ /* Prevent unload. */
+ atomic_inc_32(&smbfs_mountcount);
/*
* Create a mount record and link it to the vfs struct.
+ * No more possiblities for errors from here on.
+ * Tear-down of this stuff is in smbfs_free_smi()
+ *
* Compare with NFS: nfsrootvp()
*/
- smi = kmem_zalloc(sizeof (smbmntinfo_t), KM_SLEEP);
+ smi = kmem_zalloc(sizeof (*smi), KM_SLEEP);
+
+ mutex_init(&smi->smi_lock, NULL, MUTEX_DEFAULT, NULL);
+ cv_init(&smi->smi_statvfs_cv, NULL, CV_DEFAULT, NULL);
- smi->smi_share = ssp;
- smi->smi_zone = mntzone;
+ rw_init(&smi->smi_hash_lk, NULL, RW_DEFAULT, NULL);
+ smbfs_init_hash_avl(&smi->smi_hash_avl);
+
+ smi->smi_share = ssp;
+ ssp = NULL;
+ smi->smi_zone = mntzone;
+ mntzone = NULL;
+
+ /*
+ * Initialize option defaults
+ */
smi->smi_flags = SMI_LLOCK;
+ smi->smi_acregmin = SEC2HR(SMBFS_ACREGMIN);
+ smi->smi_acregmax = SEC2HR(SMBFS_ACREGMAX);
+ smi->smi_acdirmin = SEC2HR(SMBFS_ACDIRMIN);
+ smi->smi_acdirmax = SEC2HR(SMBFS_ACDIRMAX);
/*
- * Handle mount options. See also XATTR below.
- * XXX: forcedirectio, largefiles (later)
+ * All "generic" mount options have already been
+ * handled in vfs.c:domount() - see mntopts stuff.
+ * Query generic options using vfs_optionisset().
*/
if (vfs_optionisset(vfsp, MNTOPT_INTR, NULL))
smi->smi_flags |= SMI_INT;
/*
- * XXX If not root, get uid/gid from the covered vnode.
+ * Get the mount options that come in as smbfs_args,
+ * starting with args.flags (SMBFS_MF_xxx)
+ */
+ flags = STRUCT_FGET(args, flags);
+ smi->smi_uid = STRUCT_FGET(args, uid);
+ smi->smi_gid = STRUCT_FGET(args, gid);
+ smi->smi_fmode = STRUCT_FGET(args, file_mode) & 0777;
+ smi->smi_dmode = STRUCT_FGET(args, dir_mode) & 0777;
+
+ /*
+ * Hande the SMBFS_MF_xxx flags.
*/
- smi->smi_args.dir_mode = STRUCT_FGET(args, dir_mode);
- smi->smi_args.file_mode = STRUCT_FGET(args, file_mode);
- smi->smi_args.uid = STRUCT_FGET(args, uid);
- smi->smi_args.gid = STRUCT_FGET(args, gid);
+ if (flags & SMBFS_MF_NOAC)
+ smi->smi_flags |= SMI_NOAC;
+ if (flags & SMBFS_MF_ACREGMIN) {
+ sec = STRUCT_FGET(args, acregmin);
+ if (sec < 0 || sec > SMBFS_ACMINMAX)
+ sec = SMBFS_ACMINMAX;
+ smi->smi_acregmin = SEC2HR(sec);
+ }
+ if (flags & SMBFS_MF_ACREGMAX) {
+ sec = STRUCT_FGET(args, acregmax);
+ if (sec < 0 || sec > SMBFS_ACMAXMAX)
+ sec = SMBFS_ACMAXMAX;
+ smi->smi_acregmax = SEC2HR(sec);
+ }
+ if (flags & SMBFS_MF_ACDIRMIN) {
+ sec = STRUCT_FGET(args, acdirmin);
+ if (sec < 0 || sec > SMBFS_ACMINMAX)
+ sec = SMBFS_ACMINMAX;
+ smi->smi_acdirmin = SEC2HR(sec);
+ }
+ if (flags & SMBFS_MF_ACDIRMAX) {
+ sec = STRUCT_FGET(args, acdirmax);
+ if (sec < 0 || sec > SMBFS_ACMAXMAX)
+ sec = SMBFS_ACMAXMAX;
+ smi->smi_acdirmax = SEC2HR(sec);
+ }
/*
* Get attributes of the remote file system,
* i.e. ACL support, named streams, etc.
*/
- error = smbfs_smb_qfsattr(ssp, &smi->smi_fsa, &scred);
+ smb_credinit(&scred, cr);
+ error = smbfs_smb_qfsattr(smi->smi_share, &smi->smi_fsa, &scred);
+ smb_credrele(&scred);
if (error) {
SMBVDEBUG("smbfs_smb_qfsattr error %d\n", error);
}
@@ -503,57 +588,40 @@ proceed:
vfsp->vfs_bcount = 0;
smi->smi_vfsp = vfsp;
- smbfs_zonelist_add(smi);
+ smbfs_zonelist_add(smi); /* undo in smbfs_freevfs */
/*
* Create the root vnode, which we need in unmount
- * for the call to smb_check_table(), etc.
+ * for the call to smbfs_check_table(), etc.
+ * Release this hold in smbfs_unmount.
*/
- rtvp = smbfs_make_node(vfsp, "\\", 1, NULL, 0, 0, NULL);
- if (!rtvp) {
- cmn_err(CE_WARN, "smbfs_mount: make_node failed\n");
- return (ENOENT);
- }
- rtvp->v_type = VDIR;
- rtvp->v_flag |= VROOT;
+ rtnp = smbfs_node_findcreate(smi, "\\", 1, NULL, 0, 0,
+ &smbfs_fattr0);
+ ASSERT(rtnp != NULL);
+ rtnp->r_vnode->v_type = VDIR;
+ rtnp->r_vnode->v_flag |= VROOT;
+ smi->smi_root = rtnp;
/*
- * Could get attributes here, but that can wait
- * until someone does a getattr call.
- *
* NFS does other stuff here too:
* async worker threads
* init kstats
*
* End of code from NFS nfsrootvp()
*/
-
- smb_credrele(&scred);
-
- smi->smi_root = VTOSMB(rtvp);
-
- atomic_inc_32(&smbfs_mountcount);
-
return (0);
errout:
-
- ASSERT(rtvp == NULL);
-
vfsp->vfs_data = NULL;
- if (smi)
+ if (smi != NULL)
smbfs_free_smi(smi);
if (mntzone != NULL)
zone_rele(mntzone);
- if (ssp)
+ if (ssp != NULL)
smb_share_rele(ssp);
- smb_credrele(&scred);
-
- /* args, if we allocated */
-
return (error);
}
@@ -572,16 +640,14 @@ smbfs_unmount(vfs_t *vfsp, int flag, cred_t *cr)
return (EPERM);
if ((flag & MS_FORCE) == 0) {
-#ifdef APPLE
smbfs_rflush(vfsp, cr);
-#endif
/*
* If there are any active vnodes on this file system,
* (other than the root vnode) then the file system is
* busy and can't be umounted.
*/
- if (smb_check_table(vfsp, smi->smi_root))
+ if (smbfs_check_table(vfsp, smi->smi_root))
return (EBUSY);
/*
@@ -625,7 +691,7 @@ smbfs_unmount(vfs_t *vfsp, int flag, cred_t *cr)
/*
* Remove all nodes from the node hash tables.
- * This (indirectly) calls: smb_addfree, smbinactive,
+ * This (indirectly) calls: smbfs_addfree, smbinactive,
* which will try to flush dirty pages, etc. so
* don't destroy the underlying share just yet.
*
@@ -652,10 +718,8 @@ smbfs_unmount(vfs_t *vfsp, int flag, cred_t *cr)
}
/*
- * Note: the smb_share_rele()
- * happens in smbfs_freevfs()
+ * The rest happens in smbfs_freevfs()
*/
-
return (0);
}
@@ -801,12 +865,11 @@ smbfs_sync(vfs_t *vfsp, short flag, cred_t *cr)
* Cross-zone calls are OK here, since this translates to a
* VOP_PUTPAGE(B_ASYNC), which gets picked up by the right zone.
*/
-#ifdef APPLE
if (!(flag & SYNC_ATTR) && mutex_tryenter(&smbfs_syncbusy) != 0) {
smbfs_rflush(vfsp, cr);
mutex_exit(&smbfs_syncbusy);
}
-#endif /* APPLE */
+
return (0);
}
@@ -833,7 +896,6 @@ void
smbfs_freevfs(vfs_t *vfsp)
{
smbmntinfo_t *smi;
- smb_share_t *ssp;
/* free up the resources */
smi = VFTOSMI(vfsp);
@@ -845,15 +907,7 @@ smbfs_freevfs(vfs_t *vfsp)
*/
ASSERT(smi->smi_io_kstats == NULL);
- /*
- * Drop our reference to the share.
- * This usually leads to VC close.
- */
- ssp = smi->smi_share;
- smi->smi_share = NULL;
- smb_share_rele(ssp);
-
- zone_rele(smi->smi_zone);
+ smbfs_zonelist_remove(smi);
smbfs_free_smi(smi);
diff --git a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_vnops.c b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_vnops.c
index a2ba2f9a5e..1ce01a3112 100644
--- a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_vnops.c
+++ b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_vnops.c
@@ -49,7 +49,6 @@
#include <sys/sysmacros.h>
#include <sys/kmem.h>
#include <sys/cmn_err.h>
-#include <sys/dnlc.h>
#include <sys/vfs_opreg.h>
#include <sys/policy.h>
@@ -98,18 +97,17 @@ static const char illegal_chars[] = {
/*
* Turning this on causes nodes to be created in the cache
- * during directory listings. The "fast" claim is debatable,
- * and the effects on the cache can be undesirable.
+ * during directory listings, normally avoiding a second
+ * OtW attribute fetch just after a readdir.
*/
+int smbfs_fastlookup = 1;
/* local static function defines */
-#ifdef USE_DNLC
-static int smbfslookup_dnlc(vnode_t *dvp, char *nm, vnode_t **vpp,
- cred_t *cr);
-#endif
+static int smbfslookup_cache(vnode_t *, char *, int, vnode_t **,
+ cred_t *);
static int smbfslookup(vnode_t *dvp, char *nm, vnode_t **vpp, cred_t *cr,
- int dnlc, caller_context_t *);
+ int cache_ok, caller_context_t *);
static int smbfsrename(vnode_t *odvp, char *onm, vnode_t *ndvp, char *nnm,
cred_t *cr, caller_context_t *);
static int smbfssetattr(vnode_t *, struct vattr *, int, cred_t *);
@@ -240,9 +238,9 @@ const fs_operation_def_t smbfs_vnodeops_template[] = {
static int
smbfs_open(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *ct)
{
- struct vattr va;
smbnode_t *np;
vnode_t *vp;
+ smbfattr_t fa;
u_int32_t rights, rightsrcvd;
u_int16_t fid, oldfid;
int oldgenid;
@@ -250,7 +248,6 @@ smbfs_open(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *ct)
smbmntinfo_t *smi;
smb_share_t *ssp;
cred_t *oldcr;
- int attrcacheupdated = 0;
int tmperror;
int error = 0;
@@ -328,14 +325,10 @@ smbfs_open(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *ct)
int upgrade = 0;
if ((flag & FWRITE) &&
- !(np->n_rights & (SA_RIGHT_FILE_WRITE_DATA |
- GENERIC_RIGHT_ALL_ACCESS |
- GENERIC_RIGHT_WRITE_ACCESS)))
+ !(np->n_rights & SA_RIGHT_FILE_WRITE_DATA))
upgrade = 1;
if ((flag & FREAD) &&
- !(np->n_rights & (SA_RIGHT_FILE_READ_DATA |
- GENERIC_RIGHT_ALL_ACCESS |
- GENERIC_RIGHT_READ_ACCESS)))
+ !(np->n_rights & SA_RIGHT_FILE_READ_DATA))
upgrade = 1;
if (!upgrade) {
/*
@@ -350,20 +343,24 @@ smbfs_open(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *ct)
/*
* we always ask for READ_CONTROL so we can always get the
* owner/group IDs to satisfy a stat. Ditto attributes.
- * XXX: verify that works with "drop boxes"
*/
rights |= (STD_RIGHT_READ_CONTROL_ACCESS |
SA_RIGHT_FILE_READ_ATTRIBUTES);
if ((flag & FREAD))
rights |= SA_RIGHT_FILE_READ_DATA;
if ((flag & FWRITE))
- rights |= SA_RIGHT_FILE_APPEND_DATA | SA_RIGHT_FILE_WRITE_DATA;
-
- /* XXX: open gets the current size, but we don't use it. */
- error = smbfs_smb_open(np, rights, &scred, &attrcacheupdated, &fid,
- NULL, 0, 0, NULL, &rightsrcvd);
+ rights |= SA_RIGHT_FILE_WRITE_DATA |
+ SA_RIGHT_FILE_APPEND_DATA |
+ SA_RIGHT_FILE_WRITE_ATTRIBUTES;
+
+ bzero(&fa, sizeof (fa));
+ error = smbfs_smb_open(np,
+ NULL, 0, 0, /* name nmlen xattr */
+ rights, &scred,
+ &fid, &rightsrcvd, &fa);
if (error)
goto out;
+ smbfs_attrcache_fa(vp, &fa);
/*
* We have a new FID and access rights.
@@ -382,7 +379,7 @@ smbfs_open(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *ct)
* Close old wire-open.
*/
tmperror = smbfs_smb_close(ssp,
- oldfid, &np->n_mtime, &scred);
+ oldfid, NULL, &scred);
if (tmperror)
SMBVDEBUG("error %d closing %s\n",
tmperror, np->n_rpath);
@@ -408,25 +405,6 @@ have_fid:
if (np->n_ovtype == VNON)
np->n_ovtype = vp->v_type;
- /* Get attributes (maybe). */
-
- /* Darwin (derived) code. */
-
- va.va_mask = AT_MTIME;
- if (np->n_flag & NMODIFIED)
- smbfs_attr_cacheremove(np);
-
- /*
- * Try to get attributes, but don't bail on error.
- * We already hold r_lkserlock/reader so note:
- * this call will recursively take r_lkserlock.
- */
- tmperror = smbfsgetattr(vp, &va, cr);
- if (tmperror)
- SMBERROR("getattr failed, error=%d", tmperror);
- else
- np->n_mtime.tv_sec = va.va_mtime.tv_sec;
-
out:
smb_credrele(&scred);
smbfs_rw_exit(&np->r_lkserlock);
@@ -441,6 +419,7 @@ smbfs_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr,
smbnode_t *np;
smbmntinfo_t *smi;
smb_share_t *ssp;
+ cred_t *oldcr;
int error = 0;
struct smb_cred scred;
@@ -492,12 +471,13 @@ smbfs_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr,
cleanshares(vp, pid);
}
- if (count > 1)
- return (0);
/*
- * OK, do "last close" stuff.
+ * This (passed in) count is the ref. count from the
+ * user's file_t before the closef call (fio.c).
+ * We only care when the reference goes away.
*/
-
+ if (count > 1)
+ return (0);
/*
* Do the CIFS close.
@@ -545,15 +525,24 @@ smbfs_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr,
}
}
if (error) {
- SMBERROR("error %d closing %s\n",
+ SMBVDEBUG("error %d closing %s\n",
error, np->n_rpath);
}
/* Allow next open to use any v_type. */
np->n_ovtype = VNON;
+ /*
+ * Other "last close" stuff.
+ */
+ mutex_enter(&np->r_statelock);
if (np->n_flag & NATTRCHANGED)
- smbfs_attr_cacheremove(np);
+ smbfs_attrcache_rm_locked(np);
+ oldcr = np->r_cred;
+ np->r_cred = NULL;
+ mutex_exit(&np->r_statelock);
+ if (oldcr != NULL)
+ crfree(oldcr);
out:
smb_credrele(&scred);
@@ -685,7 +674,7 @@ smbfs_write(vnode_t *vp, struct uio *uiop, int ioflag, cred_t *cr,
*/
if (ioflag & (FAPPEND | FSYNC)) {
if (np->n_flag & NMODIFIED) {
- smbfs_attr_cacheremove(np);
+ smbfs_attrcache_remove(np);
/* XXX: smbfs_vinvalbuf? */
}
}
@@ -730,7 +719,7 @@ smbfs_write(vnode_t *vp, struct uio *uiop, int ioflag, cred_t *cr,
/* Timeout: longer for append. */
timo = smb_timo_write;
- if (endoff > np->n_size)
+ if (endoff > np->r_size)
timo = smb_timo_append;
/* Shared lock for n_fid use in smb_rwuio */
@@ -748,8 +737,8 @@ smbfs_write(vnode_t *vp, struct uio *uiop, int ioflag, cred_t *cr,
if (error == 0) {
mutex_enter(&np->r_statelock);
np->n_flag |= (NFLUSHWIRE | NATTRCHANGED);
- if (uiop->uio_loffset > (offset_t)np->n_size)
- np->n_size = (len_t)uiop->uio_loffset;
+ if (uiop->uio_loffset > (offset_t)np->r_size)
+ np->r_size = (len_t)uiop->uio_loffset;
mutex_exit(&np->r_statelock);
if (ioflag & (FSYNC|FDSYNC)) {
/* Don't error the I/O if this fails. */
@@ -866,62 +855,18 @@ smbfs_getattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr,
if (vap->va_mask | AT_SIZE)
vap->va_size = np->r_size;
if (vap->va_mask | AT_FSID)
- vap->va_fsid = np->r_attr.va_fsid;
+ vap->va_fsid = vp->v_vfsp->vfs_dev;
if (vap->va_mask | AT_RDEV)
- vap->va_rdev = np->r_attr.va_rdev;
+ vap->va_rdev = vp->v_rdev;
mutex_exit(&np->r_statelock);
return (0);
}
}
-
return (smbfsgetattr(vp, vap, cr));
}
-/*
- * Mostly from Darwin smbfs_getattr()
- */
-int
-smbfsgetattr(vnode_t *vp, struct vattr *vap, cred_t *cr)
-{
- int error;
- smbnode_t *np;
- struct smb_cred scred;
- struct smbfattr fattr;
-
- ASSERT(curproc->p_zone == VTOSMI(vp)->smi_zone);
-
- np = VTOSMB(vp);
-
- /*
- * If we've got cached attributes, we're done, otherwise go
- * to the server to get attributes, which will update the cache
- * in the process.
- *
- * This section from Darwin smbfs_getattr,
- * but then modified a lot.
- */
- error = smbfs_attr_cachelookup(vp, vap);
- if (error != ENOENT)
- return (error);
-
- /* Shared lock for (possible) n_fid use. */
- if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
- return (EINTR);
- smb_credinit(&scred, cr);
-
- bzero(&fattr, sizeof (fattr));
- error = smbfs_smb_getfattr(np, &fattr, &scred);
-
- smb_credrele(&scred);
- smbfs_rw_exit(&np->r_lkserlock);
-
- if (!error) {
- smbfs_attr_cacheenter(vp, &fattr);
- error = smbfs_attr_cachelookup(vp, vap);
- }
- return (error);
-}
+/* smbfsgetattr() in smbfs_client.c */
/*
* XXX
@@ -933,23 +878,29 @@ static int
smbfs_setattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr,
caller_context_t *ct)
{
+ vfs_t *vfsp;
+ smbmntinfo_t *smi;
int error;
uint_t mask;
struct vattr oldva;
- smbmntinfo_t *smi;
- smi = VTOSMI(vp);
+ vfsp = vp->v_vfsp;
+ smi = VFTOSMI(vfsp);
if (curproc->p_zone != smi->smi_zone)
return (EIO);
- if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
+ if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED)
return (EIO);
mask = vap->va_mask;
if (mask & AT_NOSET)
return (EINVAL);
+ if (vfsp->vfs_flag & VFS_RDONLY)
+ return (EROFS);
+
+ bzero(&oldva, sizeof (oldva));
oldva.va_mask = AT_TYPE | AT_MODE | AT_UID | AT_GID;
error = smbfsgetattr(vp, &oldva, cr);
if (error)
@@ -973,7 +924,6 @@ smbfssetattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr)
{
int error = 0;
smbnode_t *np = VTOSMB(vp);
- smbmntinfo_t *smi = VTOSMI(vp);
uint_t mask = vap->va_mask;
struct timespec *mtime, *atime;
struct smb_cred scred;
@@ -982,7 +932,7 @@ smbfssetattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr)
int have_fid = 0;
uint32_t rights = 0;
- ASSERT(curproc->p_zone == smi->smi_zone);
+ ASSERT(curproc->p_zone == VTOSMI(vp)->smi_zone);
/*
* There are no settable attributes on the XATTR dir,
@@ -1016,20 +966,21 @@ smbfssetattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr)
*/
if (mask & (AT_ATIME | AT_MTIME)) {
rights |=
- SA_RIGHT_FILE_WRITE_ATTRIBUTES |
- GENERIC_RIGHT_ALL_ACCESS |
- GENERIC_RIGHT_WRITE_ACCESS;
+ SA_RIGHT_FILE_WRITE_ATTRIBUTES;
}
if (mask & AT_SIZE) {
rights |=
SA_RIGHT_FILE_WRITE_DATA |
SA_RIGHT_FILE_APPEND_DATA;
- /*
- * Only SIZE requires a handle.
- * XXX May be more reliable to just
- * always get the file handle here.
- * The tmpopen checks n_vcgenid.
- */
+ }
+
+ /*
+ * Only SIZE really requires a handle, but it's
+ * simpler and more reliable to set via a handle.
+ * Some servers like NT4 won't set times by path.
+ * Also, we're usually setting everything anyway.
+ */
+ if (mask & (AT_SIZE | AT_ATIME | AT_MTIME)) {
error = smbfs_smb_tmpopen(np, rights, &scred, &fid);
if (error) {
SMBVDEBUG("error %d opening %s\n",
@@ -1039,7 +990,6 @@ smbfssetattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr)
have_fid = 1;
}
-
/*
* If the server supports the UNIX extensions, right here is where
* we'd support changes to uid, gid, mode, and possibly va_flags.
@@ -1089,21 +1039,16 @@ smbfssetattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr)
if (mtime || atime) {
/*
- * If file is opened with write-attributes capability,
- * we use handle-based calls. If not, we use path-based ones.
+ * Always use the handle-based set attr call now.
+ * Not trying to set DOS attributes here so pass zero.
*/
- if (have_fid) {
- error = smbfs_smb_setfattr(np, fid,
- np->n_dosattr, mtime, atime, &scred);
- } else {
- error = smbfs_smb_setpattr(np,
- np->n_dosattr, mtime, atime, &scred);
- }
+ ASSERT(have_fid);
+ error = smbfs_smb_setfattr(np, fid,
+ 0, mtime, atime, &scred);
if (error) {
SMBVDEBUG("set times error %d file %s\n",
error, np->n_rpath);
} else {
- /* XXX: set np->n_mtime, etc? */
modified = 1;
}
}
@@ -1111,20 +1056,16 @@ smbfssetattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr)
out:
if (modified) {
/*
- * Invalidate attribute cache in case if server doesn't set
- * required attributes.
- */
- smbfs_attr_cacheremove(np);
- /*
- * XXX Darwin called _getattr here to
- * update the mtime. Should we?
+ * Invalidate attribute cache in case the server
+ * doesn't set exactly the attributes we asked.
*/
+ smbfs_attrcache_remove(np);
}
if (have_fid) {
cerror = smbfs_smb_tmpclose(np, fid, &scred);
if (cerror)
- SMBERROR("error %d closing %s\n",
+ SMBVDEBUG("error %d closing %s\n",
cerror, np->n_rpath);
}
@@ -1188,10 +1129,9 @@ smbfs_access_rwx(vfs_t *vfsp, int vtype, int mode, cred_t *cr)
va.va_mask = AT_TYPE | AT_MODE | AT_UID | AT_GID;
va.va_type = vtype;
va.va_mode = (vtype == VDIR) ?
- smi->smi_args.dir_mode :
- smi->smi_args.file_mode;
- va.va_uid = smi->smi_args.uid;
- va.va_gid = smi->smi_args.gid;
+ smi->smi_dmode : smi->smi_fmode;
+ va.va_uid = smi->smi_uid;
+ va.va_gid = smi->smi_gid;
/*
* Disallow write attempts on read-only file systems,
@@ -1367,7 +1307,7 @@ smbfs_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct)
np->n_dirrefs, fid, np->n_rpath);
}
- smb_addfree(np);
+ smbfs_addfree(np);
}
/*
@@ -1408,37 +1348,29 @@ smbfs_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, struct pathname *pnp,
if ((vfs->vfs_flag & VFS_XATTR) == 0)
return (EINVAL);
- /*
- * We don't allow recursive attributes.
- */
- if (dnp->n_flag & N_XATTR)
- return (EINVAL);
-
error = smbfs_get_xattrdir(dvp, vpp, cr, flags);
return (error);
}
- if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_READER, SMBINTR(dvp))) {
- error = EINTR;
- goto out;
- }
+ if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_READER, SMBINTR(dvp)))
+ return (EINTR);
error = smbfslookup(dvp, nm, vpp, cr, 1, ct);
smbfs_rw_exit(&dnp->r_rwlock);
-out:
return (error);
}
/* ARGSUSED */
static int
-smbfslookup(vnode_t *dvp, char *nm, vnode_t **vpp, cred_t *cr, int dnlc,
- caller_context_t *ct)
+smbfslookup(vnode_t *dvp, char *nm, vnode_t **vpp, cred_t *cr,
+ int cache_ok, caller_context_t *ct)
{
int error;
int supplen; /* supported length */
vnode_t *vp;
+ smbnode_t *np;
smbnode_t *dnp;
smbmntinfo_t *smi;
/* struct smb_vc *vcp; */
@@ -1471,9 +1403,8 @@ smbfslookup(vnode_t *dvp, char *nm, vnode_t **vpp, cred_t *cr, int dnlc,
ASSERT(dnp->r_rwlock.count != 0);
/*
- * If lookup is for "", just return dvp. Don't need
- * to send it over the wire, look it up in the dnlc,
- * or perform any access checks.
+ * If lookup is for "", just return dvp.
+ * No need to perform any access checks.
*/
if (nmlen == 0) {
VN_HOLD(dvp);
@@ -1495,9 +1426,8 @@ smbfslookup(vnode_t *dvp, char *nm, vnode_t **vpp, cred_t *cr, int dnlc,
return (error);
/*
- * If lookup is for ".", just return dvp. Don't need
- * to send it over the wire or look it up in the dnlc,
- * just need to check access (done above).
+ * If lookup is for ".", just return dvp.
+ * Access check was done above.
*/
if (nmlen == 1 && name[0] == '.') {
VN_HOLD(dvp);
@@ -1523,21 +1453,8 @@ smbfslookup(vnode_t *dvp, char *nm, vnode_t **vpp, cred_t *cr, int dnlc,
if (strpbrk(nm, ill))
return (EINVAL);
-#ifdef USE_DNLC
- if (dnlc) {
- /*
- * Lookup this name in the DNLC. If there was a valid entry,
- * then return the results of the lookup.
- */
- error = smbfslookup_dnlc(dvp, nm, vpp, cr);
- if (error || *vpp != NULL)
- return (error);
- }
-#endif /* USE_DNLC */
-
/*
- * Handle lookup of ".." which is quite tricky,
- * because the protocol gives us little help.
+ * Special handling for lookup of ".."
*
* We keep full pathnames (as seen on the server)
* so we can just trim off the last component to
@@ -1570,7 +1487,6 @@ smbfslookup(vnode_t *dvp, char *nm, vnode_t **vpp, cred_t *cr, int dnlc,
*/
if (dvp->v_flag & V_XATTRDIR) {
error = smbfs_xa_parent(dvp, vpp);
- /* Intentionally no dnlc_update */
return (error);
}
@@ -1583,21 +1499,19 @@ smbfslookup(vnode_t *dvp, char *nm, vnode_t **vpp, cred_t *cr, int dnlc,
if (dnp->n_rpath[rplen] == '\\')
break;
}
- if (rplen == 0) {
+ if (rplen <= 0) {
/* Found our way to the root. */
vp = SMBTOV(smi->smi_root);
VN_HOLD(vp);
*vpp = vp;
return (0);
}
- vp = smbfs_make_node(dvp->v_vfsp,
- dnp->n_rpath, rplen,
- NULL, 0, 0, NULL);
- ASSERT(vp);
+ np = smbfs_node_findcreate(smi,
+ dnp->n_rpath, rplen, NULL, 0, 0,
+ &smbfs_fattr0); /* force create */
+ ASSERT(np != NULL);
+ vp = SMBTOV(np);
vp->v_type = VDIR;
-#ifdef USE_DNLC
- dnlc_update(dvp, nm, vp);
-#endif
/* Success! */
*vpp = vp;
@@ -1605,34 +1519,49 @@ smbfslookup(vnode_t *dvp, char *nm, vnode_t **vpp, cred_t *cr, int dnlc,
}
/*
- * Normal lookup of a child node.
- * Note we handled "." and ".." above.
- *
- * First, go over-the-wire to get the
- * node type (and attributes).
+ * Normal lookup of a name under this directory.
+ * Note we handled "", ".", ".." above.
+ */
+ if (cache_ok) {
+ /*
+ * The caller indicated that it's OK to use a
+ * cached result for this lookup, so try to
+ * reclaim a node from the smbfs node cache.
+ */
+ error = smbfslookup_cache(dvp, nm, nmlen, &vp, cr);
+ if (error)
+ return (error);
+ if (vp != NULL) {
+ /* hold taken in lookup_cache */
+ *vpp = vp;
+ return (0);
+ }
+ }
+
+ /*
+ * OK, go over-the-wire to get the attributes,
+ * then create the node.
*/
smb_credinit(&scred, cr);
/* Note: this can allocate a new "name" */
error = smbfs_smb_lookup(dnp, &name, &nmlen, &fa, &scred);
smb_credrele(&scred);
-#ifdef USE_DNLC
- if (error == ENOENT)
- dnlc_enter(dvp, nm, DNLC_NO_VNODE);
-#endif
+ if (error == ENOTDIR) {
+ /*
+ * Lookup failed because this directory was
+ * removed or renamed by another client.
+ * Remove any cached attributes under it.
+ */
+ smbfs_attrcache_remove(dnp);
+ smbfs_attrcache_prune(dnp);
+ }
if (error)
goto out;
- /*
- * Find or create the node.
- */
error = smbfs_nget(dvp, name, nmlen, &fa, &vp);
if (error)
goto out;
-#ifdef USE_DNLC
- dnlc_update(dvp, nm, vp);
-#endif
-
/* Success! */
*vpp = vp;
@@ -1644,83 +1573,98 @@ out:
return (error);
}
-#ifdef USE_DNLC
+/*
+ * smbfslookup_cache
+ *
+ * Try to reclaim a node from the smbfs node cache.
+ * Some statistics for DEBUG.
+ *
+ * This mechanism lets us avoid many of the five (or more)
+ * OtW lookup calls per file seen with "ls -l" if we search
+ * the smbfs node cache for recently inactive(ated) nodes.
+ */
#ifdef DEBUG
-static int smbfs_lookup_dnlc_hits = 0;
-static int smbfs_lookup_dnlc_misses = 0;
-static int smbfs_lookup_dnlc_neg_hits = 0;
-static int smbfs_lookup_dnlc_disappears = 0;
-static int smbfs_lookup_dnlc_lookups = 0;
-#endif
+int smbfs_lookup_cache_calls = 0;
+int smbfs_lookup_cache_error = 0;
+int smbfs_lookup_cache_miss = 0;
+int smbfs_lookup_cache_stale = 0;
+int smbfs_lookup_cache_hits = 0;
+#endif /* DEBUG */
/* ARGSUSED */
static int
-smbfslookup_dnlc(vnode_t *dvp, char *nm, vnode_t **vpp, cred_t *cr)
+smbfslookup_cache(vnode_t *dvp, char *nm, int nmlen,
+ vnode_t **vpp, cred_t *cr)
{
- int error;
- vnode_t *vp;
struct vattr va;
smbnode_t *dnp;
+ smbnode_t *np;
+ vnode_t *vp;
+ int error;
+ char sep;
dnp = VTOSMB(dvp);
+ *vpp = NULL;
- ASSERT(*nm != '\0');
- ASSERT(curproc->p_zone == VTOSMI(dvp)->smi_zone);
+#ifdef DEBUG
+ smbfs_lookup_cache_calls++;
+#endif
/*
- * Lookup this name in the DNLC. If successful, then validate
- * the caches and then recheck the DNLC. The DNLC is rechecked
- * just in case this entry got invalidated during the call
- * to smbfsgetattr().
- * An assumption is being made that it is safe to say that a
- * file exists which may not on the server. Any operations to
- * the server will fail with ESTALE.
+ * First make sure we can get attributes for the
+ * directory. Cached attributes are OK here.
+ * If we removed or renamed the directory, this
+ * will return ENOENT. If someone else removed
+ * this directory or file, we'll find out when we
+ * try to open or get attributes.
*/
-
-#ifdef DEBUG
- smbfs_lookup_dnlc_lookups++;
-#endif
- vp = dnlc_lookup(dvp, nm);
- if (vp != NULL) {
- if (vp == DNLC_NO_VNODE && !vn_is_readonly(dvp))
- smbfs_attr_cacheremove(dnp);
- VN_RELE(vp);
- error = smbfsgetattr(dvp, &va, cr);
- if (error)
- return (error);
- vp = dnlc_lookup(dvp, nm);
- if (vp != NULL) {
- /*
- * NFS checks VEXEC access here,
- * but we've already done that
- * in the caller.
- */
- if (vp == DNLC_NO_VNODE) {
- VN_RELE(vp);
+ va.va_mask = AT_TYPE | AT_MODE;
+ error = smbfsgetattr(dvp, &va, cr);
+ if (error) {
#ifdef DEBUG
- smbfs_lookup_dnlc_neg_hits++;
+ smbfs_lookup_cache_error++;
#endif
- return (ENOENT);
- }
- *vpp = vp;
+ return (error);
+ }
+
+ /*
+ * Passing NULL smbfattr here so we will
+ * just look, not create.
+ */
+ sep = SMBFS_DNP_SEP(dnp);
+ np = smbfs_node_findcreate(dnp->n_mount,
+ dnp->n_rpath, dnp->n_rplen,
+ nm, nmlen, sep, NULL);
+ if (np == NULL) {
#ifdef DEBUG
- smbfs_lookup_dnlc_hits++;
+ smbfs_lookup_cache_miss++;
#endif
- return (0);
- }
+ return (0);
+ }
+
+ /*
+ * Found it. Attributes still valid?
+ */
+ vp = SMBTOV(np);
+ if (np->r_attrtime <= gethrtime()) {
+ /* stale */
#ifdef DEBUG
- smbfs_lookup_dnlc_disappears++;
+ smbfs_lookup_cache_stale++;
#endif
+ VN_RELE(vp);
+ return (0);
}
+
+ /*
+ * Success!
+ * Caller gets hold from smbfs_node_findcreate
+ */
#ifdef DEBUG
- else
- smbfs_lookup_dnlc_misses++;
+ smbfs_lookup_cache_hits++;
#endif
- *vpp = NULL;
-
+ *vpp = vp;
return (0);
}
-#endif /* USE_DNLC */
/*
* XXX
@@ -1805,7 +1749,7 @@ smbfs_create(vnode_t *dvp, char *nm, struct vattr *va, enum vcexcl exclusive,
/*
* NFS needs to go over the wire, just to be sure whether the
- * file exists or not. Using the DNLC can be dangerous in
+ * file exists or not. Using a cached result is dangerous in
* this case when making a decision regarding existence.
*
* The SMB protocol does NOT really need to go OTW here
@@ -1870,9 +1814,6 @@ smbfs_create(vnode_t *dvp, char *nm, struct vattr *va, enum vcexcl exclusive,
if (error)
goto out;
- /* remove possible negative entry from the dnlc */
- dnlc_remove(dvp, nm);
-
/*
* Now the code derived from Darwin,
* but with greater use of NT_CREATE
@@ -1894,7 +1835,9 @@ smbfs_create(vnode_t *dvp, char *nm, struct vattr *va, enum vcexcl exclusive,
disp = NTCREATEX_DISP_OPEN_IF;
}
xattr = (dnp->n_flag & N_XATTR) ? 1 : 0;
- error = smbfs_smb_create(dnp, name, nmlen, &scred, &fid, disp, xattr);
+ error = smbfs_smb_create(dnp,
+ name, nmlen, xattr,
+ disp, &scred, &fid);
if (error)
goto out;
@@ -1935,7 +1878,7 @@ smbfs_create(vnode_t *dvp, char *nm, struct vattr *va, enum vcexcl exclusive,
cerror = smbfs_smb_close(smi->smi_share, fid, NULL, &scred);
if (cerror)
- SMBERROR("error %d closing %s\\%s\n",
+ SMBVDEBUG("error %d closing %s\\%s\n",
cerror, dnp->n_rpath, name);
/*
@@ -1958,10 +1901,6 @@ smbfs_create(vnode_t *dvp, char *nm, struct vattr *va, enum vcexcl exclusive,
if (error)
goto out;
-#ifdef USE_DNLC
- dnlc_update(dvp, nm, vp);
-#endif
-
/* XXX invalidate pages if we truncated? */
/* Success! */
@@ -1970,9 +1909,9 @@ smbfs_create(vnode_t *dvp, char *nm, struct vattr *va, enum vcexcl exclusive,
out:
smb_credrele(&scred);
+ smbfs_rw_exit(&dnp->r_rwlock);
if (name != nm)
smbfs_name_free(name, nmlen);
- smbfs_rw_exit(&dnp->r_rwlock);
return (error);
}
@@ -2005,6 +1944,7 @@ smbfs_remove(vnode_t *dvp, char *nm, cred_t *cr, caller_context_t *ct,
dnp = VTOSMB(dvp);
if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_WRITER, SMBINTR(dvp)))
return (EINTR);
+ smb_credinit(&scred, cr);
/*
* Verify access to the dirctory.
@@ -2031,48 +1971,46 @@ smbfs_remove(vnode_t *dvp, char *nm, cred_t *cr, caller_context_t *ct,
}
/*
- * First just remove the entry from the name cache, as it
- * is most likely the only entry for this vp.
- */
- dnlc_remove(dvp, nm);
-
- /*
- * If the file has a v_count > 1 then there may be more than one
- * entry in the name cache due multiple links or an open file,
- * but we don't have the real reference count so flush all
- * possible entries.
- */
- if (vp->v_count > 1)
- dnlc_purge_vp(vp);
-
- /*
* Now we have the real reference count on the vnode
+ * Do we have the file open?
*/
np = VTOSMB(vp);
mutex_enter(&np->r_statelock);
- if (vp->v_count > 1) {
+ if ((vp->v_count > 1) && (np->n_fidrefs > 0)) {
/*
* NFS does a rename on remove here.
* Probably not applicable for SMB.
* Like Darwin, just return EBUSY.
*
- * XXX: Todo - Ask the server to set the
+ * XXX: Todo - Use Trans2rename, and
+ * if that fails, ask the server to
* set the delete-on-close flag.
*/
mutex_exit(&np->r_statelock);
error = EBUSY;
} else {
+ smbfs_attrcache_rm_locked(np);
mutex_exit(&np->r_statelock);
- smb_credinit(&scred, cr);
error = smbfs_smb_delete(np, &scred, NULL, 0, 0);
- smb_credrele(&scred);
+ /*
+ * If the file should no longer exist, discard
+ * any cached attributes under this node.
+ */
+ switch (error) {
+ case 0:
+ case ENOENT:
+ case ENOTDIR:
+ smbfs_attrcache_prune(np);
+ break;
+ }
}
VN_RELE(vp);
out:
+ smb_credrele(&scred);
smbfs_rw_exit(&dnp->r_rwlock);
return (error);
@@ -2164,6 +2102,7 @@ smbfsrename(vnode_t *odvp, char *onm, vnode_t *ndvp, char *nnm, cred_t *cr,
return (EINTR);
}
}
+ smb_credinit(&scred, cr);
/*
* No returns after this point (goto out)
*/
@@ -2238,35 +2177,6 @@ smbfsrename(vnode_t *odvp, char *onm, vnode_t *ndvp, char *nnm, cred_t *cr,
}
/*
- * Purge the name cache of all references to this vnode
- * so that we can check the reference count to infer
- * whether it is active or not.
- */
- /*
- * First just remove the entry from the name cache, as it
- * is most likely the only entry for this vp.
- */
- dnlc_remove(ndvp, nnm);
- /*
- * If the file has a v_count > 1 then there may be more
- * than one entry in the name cache due multiple links
- * or an open file, but we don't have the real reference
- * count so flush all possible entries.
- */
- if (nvp->v_count > 1)
- dnlc_purge_vp(nvp);
- /*
- * when renaming directories to be a subdirectory of a
- * different parent, the dnlc entry for ".." will no
- * longer be valid, so it must be removed
- */
- if (ndvp != odvp) {
- if (ovp->v_type == VDIR) {
- dnlc_remove(ovp, "..");
- }
- }
-
- /*
* CIFS gives a SHARING_VIOLATION error when
* trying to rename onto an exising object,
* so try to remove the target first.
@@ -2285,7 +2195,7 @@ smbfsrename(vnode_t *odvp, char *onm, vnode_t *ndvp, char *nnm, cred_t *cr,
*/
nnp = VTOSMB(nvp);
mutex_enter(&nnp->r_statelock);
- if (nvp->v_count > 2) {
+ if ((nvp->v_count > 2) && (nnp->n_fidrefs > 0)) {
/*
* The target file exists, is not the same as
* the source file, and is active. Other FS
@@ -2297,14 +2207,26 @@ smbfsrename(vnode_t *odvp, char *onm, vnode_t *ndvp, char *nnm, cred_t *cr,
error = EBUSY;
goto out;
}
- mutex_exit(&nnp->r_statelock);
/*
* Target file is not active. Try to remove it.
*/
- smb_credinit(&scred, cr);
+ smbfs_attrcache_rm_locked(nnp);
+ mutex_exit(&nnp->r_statelock);
+
error = smbfs_smb_delete(nnp, &scred, NULL, 0, 0);
- smb_credrele(&scred);
+
+ /*
+ * Similar to smbfs_remove
+ */
+ switch (error) {
+ case 0:
+ case ENOENT:
+ case ENOTDIR:
+ smbfs_attrcache_prune(nnp);
+ break;
+ }
+
if (error)
goto out;
/*
@@ -2317,14 +2239,17 @@ smbfsrename(vnode_t *odvp, char *onm, vnode_t *ndvp, char *nnm, cred_t *cr,
nvp = NULL;
} /* nvp */
- dnlc_remove(odvp, onm);
- dnlc_remove(ndvp, nnm);
-
onp = VTOSMB(ovp);
- smb_credinit(&scred, cr);
+ smbfs_attrcache_remove(onp);
+
error = smbfs_smb_rename(onp, ndnp, nnm, strlen(nnm), &scred);
- smb_credrele(&scred);
+ /*
+ * If the old name should no longer exist,
+ * discard any cached attributes under it.
+ */
+ if (error == 0)
+ smbfs_attrcache_prune(onp);
out:
if (nvp) {
@@ -2335,6 +2260,7 @@ out:
if (ovp)
VN_RELE(ovp);
+ smb_credrele(&scred);
smbfs_rw_exit(&odnp->r_rwlock);
smbfs_rw_exit(&ndnp->r_rwlock);
@@ -2393,9 +2319,6 @@ smbfs_mkdir(vnode_t *dvp, char *nm, struct vattr *va, vnode_t **vpp,
if (error)
goto out;
- /* remove possible negative entry from the dnlc */
- dnlc_remove(dvp, nm);
-
error = smbfs_smb_mkdir(dnp, name, nmlen, &scred);
if (error)
goto out;
@@ -2410,10 +2333,6 @@ smbfs_mkdir(vnode_t *dvp, char *nm, struct vattr *va, vnode_t **vpp,
if (error)
goto out;
-#ifdef USE_DNLC
- dnlc_update(dvp, nm, vp);
-#endif
-
if (name[0] == '.')
if ((hiderr = smbfs_smb_hideit(VTOSMB(vp), NULL, 0, &scred)))
SMBVDEBUG("hide failure %d\n", hiderr);
@@ -2498,28 +2417,20 @@ smbfs_rmdir(vnode_t *dvp, char *nm, vnode_t *cdir, cred_t *cr,
goto out;
}
- /*
- * First just remove the entry from the name cache, as it
- * is most likely an entry for this vp.
- */
- dnlc_remove(dvp, nm);
+ smbfs_attrcache_remove(np);
+ error = smbfs_smb_rmdir(np, &scred);
/*
- * If there vnode reference count is greater than one, then
- * there may be additional references in the DNLC which will
- * need to be purged. First, trying removing the entry for
- * the parent directory and see if that removes the additional
- * reference(s). If that doesn't do it, then use dnlc_purge_vp
- * to completely remove any references to the directory which
- * might still exist in the DNLC.
+ * Similar to smbfs_remove
*/
- if (vp->v_count > 1) {
- dnlc_remove(vp, "..");
- if (vp->v_count > 1)
- dnlc_purge_vp(vp);
+ switch (error) {
+ case 0:
+ case ENOENT:
+ case ENOTDIR:
+ smbfs_attrcache_prune(np);
+ break;
}
- error = smbfs_smb_rmdir(np, &scred);
if (error)
goto out;
@@ -2527,7 +2438,7 @@ smbfs_rmdir(vnode_t *dvp, char *nm, vnode_t *cdir, cred_t *cr,
dnp->n_flag |= NMODIFIED;
mutex_exit(&np->r_statelock);
smbfs_attr_touchdir(dnp);
- smb_rmhash(np);
+ smbfs_rmhash(np);
out:
if (vp) {
@@ -2636,15 +2547,6 @@ smbfs_readvdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *eofp,
if (uio->uio_resid < dbufsiz)
return (EINVAL);
-#ifdef USE_DNLC
- /*
- * This dnlc_purge_vp ensures that name cache for this dir will be
- * current - it'll only have the items for which the smbfs_nget
- * MAKEENTRY happened.
- */
- if (smbfs_fastlookup)
- dnlc_purge_vp(vp);
-#endif
SMBVDEBUG("dirname='%s'\n", np->n_rpath);
smb_credinit(&scred, cr);
dp = kmem_alloc(dbufsiz, KM_SLEEP);
@@ -2757,20 +2659,19 @@ smbfs_readvdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *eofp,
nmlen = SMB_MAXFNAMELEN;
SMBVDEBUG("Truncating name: %s\n", ctx->f_name);
}
-#ifdef NOT_YET
if (smbfs_fastlookup) {
+ /* See comment at smbfs_fastlookup above. */
if (smbfs_nget(vp, ctx->f_name, nmlen,
&ctx->f_attr, &newvp) == 0)
VN_RELE(newvp);
}
-#endif /* NOT_YET */
reclen = DIRENT64_RECLEN(nmlen);
bzero(dp, reclen);
dp->d_reclen = reclen;
bcopy(ctx->f_name, dp->d_name, nmlen);
dp->d_name[nmlen] = '\0';
- dp->d_ino = ctx->f_attr.fa_ino;
+ dp->d_ino = ctx->f_inum;
dp->d_off = offset + 1; /* See d_off comment above */
error = uiomove(dp, reclen, UIO_READ, uio);
if (error)
@@ -3000,9 +2901,10 @@ smbfs_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr,
case _PC_ACL_ENABLED:
/*
- * Always say "yes" here. Our _getsecattr
- * will build a trivial ACL when needed,
- * i.e. when server does not have ACLs.
+ * Always indicate that ACLs are enabled and
+ * that we support ACE_T format, otherwise
+ * libsec will ask for ACLENT_T format data
+ * which we don't support.
*/
*valp = _ACL_ACE_ENABLED;
break;
@@ -3019,8 +2921,11 @@ smbfs_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr,
return (EINVAL);
case _PC_TIMESTAMP_RESOLUTION:
- /* nanosecond timestamp resolution */
- *valp = 1L;
+ /*
+ * Windows times are tenths of microseconds
+ * (multiples of 100 nanoseconds).
+ */
+ *valp = 100L;
break;
default:
@@ -3036,7 +2941,9 @@ smbfs_getsecattr(vnode_t *vp, vsecattr_t *vsa, int flag, cred_t *cr,
{
vfs_t *vfsp;
smbmntinfo_t *smi;
- int error, uid, gid;
+ uid_t uid;
+ gid_t gid;
+ int error;
uint_t mask;
vfsp = vp->v_vfsp;
@@ -3059,12 +2966,9 @@ smbfs_getsecattr(vnode_t *vp, vsecattr_t *vsa, int flag, cred_t *cr,
if (mask == 0)
return (ENOSYS);
- /* XXX - access check ACE_READ_ACL? */
-
- if (smi->smi_fsattr & FILE_PERSISTENT_ACLS) {
+ if (smi->smi_flags & SMI_ACL)
error = smbfs_getacl(vp, vsa, &uid, &gid, flag, cr);
- /* XXX: Save uid/gid somewhere? */
- } else
+ else
error = ENOSYS;
if (error == ENOSYS)
@@ -3100,21 +3004,20 @@ smbfs_setsecattr(vnode_t *vp, vsecattr_t *vsa, int flag, cred_t *cr,
if (mask == 0)
return (ENOSYS);
- /*
- * If and when smbfs_access is extended, we can
- * check ACE_WRITE_ACL here instead. (XXX todo)
- * For now, in-line parts of smbfs_access,
- * i.e. only allow _setacl by the owner,
- * and check for read-only FS.
- */
if (vfsp->vfs_flag & VFS_RDONLY)
return (EROFS);
- if (crgetuid(cr) != smi->smi_args.uid)
- return (EACCES);
- if (smi->smi_fsattr & FILE_PERSISTENT_ACLS) {
+ /*
+ * Allow only the mount owner to do this.
+ * See comments at smbfs_access_rwx.
+ */
+ error = secpolicy_vnode_setdac(cr, smi->smi_uid);
+ if (error != 0)
+ return (error);
+
+ if (smi->smi_flags & SMI_ACL)
error = smbfs_setacl(vp, vsa, -1, -1, flag, cr);
- } else
+ else
error = ENOSYS;
return (error);
diff --git a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_xattr.c b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_xattr.c
index ad68648d12..83c91fecc0 100644
--- a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_xattr.c
+++ b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_xattr.c
@@ -41,7 +41,6 @@
#include <sys/kmem.h>
#include <sys/stat.h>
#include <sys/cmn_err.h>
-#include <sys/dnlc.h>
#include <sys/u8_textprep.h>
#include <netsmb/smb_osdep.h>
@@ -86,12 +85,20 @@ smbfs_get_xattrdir(vnode_t *pvp, vnode_t **vpp, cred_t *cr, int flags)
pnp = VTOSMB(pvp);
- xvp = smbfs_make_node(pvp->v_vfsp,
- pnp->n_rpath, pnp->n_rplen,
- NULL, 0, ':', NULL);
- ASSERT(xvp);
+ /*
+ * We don't allow recursive extended attributes
+ * (xattr under xattr dir.) so the "parent" node
+ * (pnp) must NOT be an XATTR directory or file.
+ */
+ if (pnp->n_flag & N_XATTR)
+ return (EINVAL);
+
+ xnp = smbfs_node_findcreate(pnp->n_mount,
+ pnp->n_rpath, pnp->n_rplen, NULL, 0, ':',
+ &smbfs_fattr0); /* force create */
+ ASSERT(xnp != NULL);
+ xvp = SMBTOV(xnp);
/* Note: xvp has a VN_HOLD, which our caller expects. */
- xnp = VTOSMB(xvp);
/* If it's a new node, initialize. */
if (xvp->v_type == VNON) {
@@ -122,9 +129,11 @@ int
smbfs_xa_parent(vnode_t *vp, vnode_t **vpp)
{
smbnode_t *np = VTOSMB(vp);
- vnode_t *pvp;
+ smbnode_t *pnp;
int rplen;
+ *vpp = NULL;
+
if ((np->n_flag & N_XATTR) == 0)
return (EINVAL);
@@ -163,13 +172,12 @@ smbfs_xa_parent(vnode_t *vp, vnode_t **vpp)
}
}
- pvp = smbfs_make_node(vp->v_vfsp,
- np->n_rpath, rplen,
- NULL, 0, 0, NULL);
- ASSERT(pvp);
-
- /* Note: pvp has a VN_HOLD from _make_node */
- *vpp = pvp;
+ pnp = smbfs_node_findcreate(np->n_mount,
+ np->n_rpath, rplen, NULL, 0, 0,
+ &smbfs_fattr0); /* force create */
+ ASSERT(pnp != NULL);
+ /* Note: have VN_HOLD from smbfs_node_findcreate */
+ *vpp = SMBTOV(pnp);
return (0);
}
diff --git a/usr/src/uts/common/netsmb/mchain.h b/usr/src/uts/common/netsmb/mchain.h
index bccb9aab7f..c5c8512fd7 100644
--- a/usr/src/uts/common/netsmb/mchain.h
+++ b/usr/src/uts/common/netsmb/mchain.h
@@ -87,8 +87,24 @@
#endif /* (BYTE_ORDER == LITTLE_ENDIAN) */
+/*
+ * Additions for Solaris to replace things that came from
+ * <sys/mbuf.h> in the Darwin code. These are mostly just
+ * wrappers for streams functions. See: subr_mchain.c
+ */
+
#ifdef _KERNEL
+/*
+ * BSD-style mbuf "shim" for kernel code. Note, this
+ * does NOT implement BSD mbufs in the kernel. Rather,
+ * macros and wrapper functions are used so that code
+ * fomerly using mbuf_t now use STREAMS mblk_t instead.
+ */
+
+#include <sys/stream.h> /* mblk_t */
+typedef mblk_t mbuf_t;
+
/* BEGIN CSTYLED */
/*
* BSD-style mbufs, vs SysV-style mblks:
@@ -115,7 +131,42 @@
*/
/* END CSTYLED */
-#include <sys/stream.h> /* mblk_t */
+#define mtod(m, t) ((t)((m)->b_rptr))
+
+/* length arg for m_copym to "copy all" */
+#define M_COPYALL -1
+
+mblk_t *m_copym(mblk_t *, int, int, int);
+mblk_t *m_pullup(mblk_t *, int);
+mblk_t *m_split(mblk_t *, int, int);
+void m_cat(mblk_t *, mblk_t *);
+#define m_freem(x) freemsg(x)
+mblk_t *m_getblk(int, int);
+int m_fixhdr(mblk_t *m);
+
+#else /* _KERNEL */
+
+/*
+ * BSD-style mbuf work-alike, for user-level.
+ * See libsmbfs mbuf.c
+ */
+typedef struct mbuf {
+ int m_len;
+ int m_maxlen;
+ char *m_data;
+ struct mbuf *m_next;
+} mbuf_t;
+
+#define mtod(m, t) ((t)(m)->m_data)
+
+int m_get(int, mbuf_t **);
+void m_freem(mbuf_t *);
+
+#endif /* _KERNEL */
+
+/*
+ * BSD-style mbchain/mdchain work-alike
+ */
/*
* Type of copy for mb_{put|get}_mem()
@@ -126,6 +177,8 @@
#define MB_MZERO 3 /* bzero(), mb_put_mem only */
#define MB_MCUSTOM 4 /* use an user defined function */
+#ifdef _KERNEL
+
struct mbchain {
mblk_t *mb_top;
mblk_t *mb_cur;
@@ -136,65 +189,64 @@ typedef struct mbchain mbchain_t;
struct mdchain {
mblk_t *md_top; /* head of mblk chain */
mblk_t *md_cur; /* current mblk */
- uchar_t *md_pos; /* offset in the current mblk */
+ uchar_t *md_pos; /* position in md_cur */
+ /* NB: md_pos is same type as mblk_t b_rptr, b_wptr members. */
};
typedef struct mdchain mdchain_t;
-int m_fixhdr(mblk_t *m);
+mblk_t *mb_detach(mbchain_t *mbp);
+int mb_fixhdr(mbchain_t *mbp);
+int mb_put_uio(mbchain_t *mbp, uio_t *uiop, size_t size);
-int mb_init(struct mbchain *mbp);
-void mb_initm(struct mbchain *mbp, mblk_t *m);
-void mb_done(struct mbchain *mbp);
-mblk_t *mb_detach(struct mbchain *mbp);
-int mb_fixhdr(struct mbchain *mbp);
-void *mb_reserve(struct mbchain *mbp, int size);
-
-int mb_put_padbyte(struct mbchain *mbp);
-int mb_put_uint8(struct mbchain *mbp, uint8_t x);
-int mb_put_uint16be(struct mbchain *mbp, uint16_t x);
-int mb_put_uint16le(struct mbchain *mbp, uint16_t x);
-int mb_put_uint32be(struct mbchain *mbp, uint32_t x);
-int mb_put_uint32le(struct mbchain *mbp, uint32_t x);
-int mb_put_uint64be(struct mbchain *mbp, uint64_t x);
-int mb_put_uint64le(struct mbchain *mbp, uint64_t x);
-int mb_put_mem(struct mbchain *mbp, const void *src, int size, int type);
-
-int mb_put_mbuf(struct mbchain *mbp, mblk_t *m);
-int mb_put_uio(struct mbchain *mbp, uio_t *uiop, size_t size);
-
-int md_init(struct mdchain *mdp);
-void md_initm(struct mdchain *mbp, mblk_t *m);
-void md_done(struct mdchain *mdp);
-void md_append_record(struct mdchain *mdp, mblk_t *top);
-int md_next_record(struct mdchain *mdp);
-int md_get_uint8(struct mdchain *mdp, uint8_t *x);
-int md_get_uint16le(struct mdchain *mdp, uint16_t *x);
-int md_get_uint16be(struct mdchain *mdp, uint16_t *x);
-int md_get_uint32be(struct mdchain *mdp, uint32_t *x);
-int md_get_uint32le(struct mdchain *mdp, uint32_t *x);
-int md_get_uint64be(struct mdchain *mdp, uint64_t *x);
-int md_get_uint64le(struct mdchain *mdp, uint64_t *x);
-int md_get_mem(struct mdchain *mdp, void *vdst, int size, int type);
-int md_get_mbuf(struct mdchain *mdp, int size, mblk_t **m);
-int md_get_uio(struct mdchain *mdp, uio_t *uiop, size_t size);
+void md_append_record(mdchain_t *mdp, mblk_t *top);
+void md_next_record(mdchain_t *mdp);
+int md_get_uio(mdchain_t *mdp, uio_t *uiop, size_t size);
+
+#else /* _KERNEL */
/*
- * Additions for Solaris to replace things that came from
- * <sys/mbuf.h> in the Darwin code. These are mostly just
- * wrappers for streams functions. See: subr_mchain.c
+ * user-level code uses the same struct for both (MB, MD)
*/
+typedef struct mbdata {
+ mbuf_t *mb_top; /* head of mbuf chain */
+ mbuf_t *mb_cur; /* current mbuf */
+ char *mb_pos; /* position in mb_cur (get) */
+ /* NB: mb_pos is same type as mbuf_t m_data member. */
+ int mb_count; /* bytes marshalled (put) */
+} mbdata_t;
+typedef struct mbdata mbchain_t;
+typedef struct mbdata mdchain_t;
+
+#endif /* _KERNEL */
+
+int mb_init(mbchain_t *);
+void mb_initm(mbchain_t *, mbuf_t *);
+void mb_done(mbchain_t *);
+void *mb_reserve(mbchain_t *, int size);
+
+int mb_put_padbyte(mbchain_t *mbp);
+int mb_put_uint8(mbchain_t *, uint8_t);
+int mb_put_uint16be(mbchain_t *, uint16_t);
+int mb_put_uint16le(mbchain_t *, uint16_t);
+int mb_put_uint32be(mbchain_t *, uint32_t);
+int mb_put_uint32le(mbchain_t *, uint32_t);
+int mb_put_uint64be(mbchain_t *, uint64_t);
+int mb_put_uint64le(mbchain_t *, uint64_t);
+int mb_put_mem(mbchain_t *, const void *, int, int);
+int mb_put_mbuf(mbchain_t *, mbuf_t *);
+
+int md_init(mdchain_t *mdp);
+void md_initm(mdchain_t *mbp, mbuf_t *m);
+void md_done(mdchain_t *mdp);
+
+int md_get_uint8(mdchain_t *, uint8_t *);
+int md_get_uint16be(mdchain_t *, uint16_t *);
+int md_get_uint16le(mdchain_t *, uint16_t *);
+int md_get_uint32be(mdchain_t *, uint32_t *);
+int md_get_uint32le(mdchain_t *, uint32_t *);
+int md_get_uint64be(mdchain_t *, uint64_t *);
+int md_get_uint64le(mdchain_t *, uint64_t *);
+int md_get_mem(mdchain_t *, void *, int, int);
+int md_get_mbuf(mdchain_t *, int, mbuf_t **);
-#define mtod(m, t) ((t)((m)->b_rptr))
-
-/* length to m_copym to copy all */
-#define M_COPYALL -1
-
-mblk_t *m_copym(mblk_t *, int, int, int);
-mblk_t *m_pullup(mblk_t *, int);
-mblk_t *m_split(mblk_t *, int, int);
-void m_cat(mblk_t *, mblk_t *);
-#define m_freem(x) freemsg(x)
-mblk_t *m_getblk(int, int);
-
-#endif /* ifdef _KERNEL */
#endif /* !_MCHAIN_H_ */
diff --git a/usr/src/uts/common/sys/fs/smbfs_mount.h b/usr/src/uts/common/sys/fs/smbfs_mount.h
index 6eeb8f909f..2e4981e02b 100644
--- a/usr/src/uts/common/sys/fs/smbfs_mount.h
+++ b/usr/src/uts/common/sys/fs/smbfs_mount.h
@@ -33,15 +33,13 @@
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _SMBFS_MOUNT_H
#define _SMBFS_MOUNT_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* This file defines the interface used by mount_smbfs.
* Some of this came from the Darwin file:
@@ -49,43 +47,34 @@
*/
#define SMBFS_VERMAJ 1
-#define SMBFS_VERMIN 3200
+#define SMBFS_VERMIN 3300
#define SMBFS_VERSION (SMBFS_VERMAJ*100000 + SMBFS_VERMIN)
-#define SMBFS_VER_STR "1.32"
+#define SMBFS_VER_STR "1.33"
#define SMBFS_VFSNAME "smbfs"
-/* Values for flags */
-#define SMBFS_MOUNT_SOFT 0x0001
-#define SMBFS_MOUNT_INTR 0x0002
-#define SMBFS_MOUNT_STRONG 0x0004
-#define SMBFS_MOUNT_HAVE_NLS 0x0008
-#define SMBFS_MOUNT_NO_LONG 0x0010
-#define SMBFS_MOUNT_HOSTNAME 0x020
-#define SMBFS_MOUNT_SEMISOFT 0x200000 /* read soft, modify hard */
-#define SMBFS_MOUNT_NOPRINT 0x400000 /* don't print messages */
-
-#define MNT_RDONLY 0x0001
-#define MNT_NODEV 0x0002
-#define MNT_NOEXEC 0x0004
-#define MNT_NOSUID 0x0008
-#define MNT_UNION 0x0010
-#define MNT_DONTBROWSE 0x0020
-#define MNT_AUTOMOUNTED 0x0040
+/* Values for smbfs_args.flags */
+#define SMBFS_MF_SOFT 0x0001
+#define SMBFS_MF_INTR 0x0002
+#define SMBFS_MF_NOAC 0x0004
+#define SMBFS_MF_ACREGMIN 0x0100 /* set min secs for file attr cache */
+#define SMBFS_MF_ACREGMAX 0x0200 /* set max secs for file attr cache */
+#define SMBFS_MF_ACDIRMIN 0x0400 /* set min secs for dir attr cache */
+#define SMBFS_MF_ACDIRMAX 0x0800 /* set max secs for dir attr cache */
/* Layout of the mount control block for an smb file system. */
struct smbfs_args {
int version; /* smbfs mount version */
int devfd; /* file descriptor */
- uint_t flags; /* mount options, eg: soft */
- mode_t file_mode; /* octal srwx for files */
- mode_t dir_mode; /* octal srwx for dirs */
- int caseopt; /* convert upper|lower|none */
- caddr_t addr; /* file server address */
- caddr_t hostname; /* server's hostname */
- caddr_t sharename; /* server's sharename */
+ uint_t flags; /* SMBFS_MF_ flags */
uid_t uid; /* octal user id */
gid_t gid; /* octal group id */
+ mode_t file_mode; /* octal srwx for files */
+ mode_t dir_mode; /* octal srwx for dirs */
+ int acregmin; /* attr cache file min secs */
+ int acregmax; /* attr cache file max secs */
+ int acdirmin; /* attr cache dir min secs */
+ int acdirmax; /* attr cache dir max secs */
};
#ifdef _SYSCALL32
@@ -94,15 +83,15 @@ struct smbfs_args {
struct smbfs_args32 {
int32_t version; /* smbfs mount version */
int32_t devfd; /* file descriptor */
- uint_t flags; /* mount options, eg: soft */
- mode_t file_mode; /* octal srwx for files */
- mode_t dir_mode; /* octal srwx for dirs */
- int32_t caseopt; /* convert upper|lower|none */
- caddr32_t addr; /* file server address */
- caddr32_t hostname; /* server's hostname */
- caddr32_t sharename; /* server's sharename */
+ uint32_t flags; /* SMBFS_MF_ flags */
uid32_t uid; /* octal user id */
gid32_t gid; /* octal group id */
+ mode32_t file_mode; /* octal srwx for files */
+ mode32_t dir_mode; /* octal srwx for dirs */
+ int32_t acregmin; /* attr cache file min secs */
+ int32_t acregmax; /* attr cache file max secs */
+ int32_t acdirmin; /* attr cache dir min secs */
+ int32_t acdirmax; /* attr cache dir max secs */
};
#endif /* _SYSCALL32 */
diff --git a/usr/src/uts/intel/nsmb/Makefile b/usr/src/uts/intel/nsmb/Makefile
index ad20178ce4..dbe89e1b9d 100644
--- a/usr/src/uts/intel/nsmb/Makefile
+++ b/usr/src/uts/intel/nsmb/Makefile
@@ -68,14 +68,12 @@ CERRWARN += -erroff=E_STATEMENT_NOT_REACHED
INC_PATH += -I$(UTSBASE)/common/fs/smbclnt
LDFLAGS += -dy -Ncrypto/md4 -Ncrypto/md5 -Nmisc/tlimod
-LINTTAGS += -erroff=E_FUNC_RET_ALWAYS_IGNOR2
-LINTTAGS += -erroff=E_FUNC_RET_MAYBE_IGNORED2
# Until CR 4994570 is fixed...
LINTTAGS += -erroff=E_BAD_FORMAT_ARG_TYPE2
# The mb_put/md_get functions are intentionally used with and without
# return value checks, so filter those out like LGREP.2 does.
-LGREP.nsmb = egrep -v ' ignored: (mb_put|md_get)'
+LGREP.nsmb = egrep -v ' ignored: (mb_init|mb_put|md_get)'
LTAIL += 2>&1 | $(LGREP.2) | $(LGREP.nsmb) || true
#
@@ -107,7 +105,7 @@ $(OBJECTS) : $(IOC_CHECK_H)
$(IOC_CHECK_H): $(OFFSETS_SRC)
$(OFFSETS_CREATE) <$(OFFSETS_SRC) >$@.tmp
cmp -s ioc_check.ref $@.tmp && \
- mv -f $@.tmp $@
+ mv -f $@.tmp $@
#
# Include common targets.
diff --git a/usr/src/uts/intel/smbfs/Makefile b/usr/src/uts/intel/smbfs/Makefile
index 445d40c736..65377ffa1e 100644
--- a/usr/src/uts/intel/smbfs/Makefile
+++ b/usr/src/uts/intel/smbfs/Makefile
@@ -63,16 +63,15 @@ $(MODSTUBS_O) := AS_CPPFLAGS += -DSMBFS_MODULE
CLEANFILES += $(MODSTUBS_O)
C99MODE = $(C99_ENABLE)
INC_PATH += -I$(UTSBASE)/common/fs/smbclnt
+INC_PATH += -I$(COMMONBASE)/smbclnt
LDFLAGS += -dy -Ndrv/nsmb
-LINTTAGS += -erroff=E_FUNC_RET_ALWAYS_IGNOR2
-LINTTAGS += -erroff=E_FUNC_RET_MAYBE_IGNORED2
# Until CR 4994570 is fixed...
LINTTAGS += -erroff=E_BAD_FORMAT_ARG_TYPE2
# The mb_put/md_get functions are intentionally used with and without
# return value checks, so filter those out like LGREP.2 does.
-LGREP.nsmb = egrep -v ' ignored: (mb_put|md_get)'
+LGREP.nsmb = egrep -v ' ignored: (mb_init|mb_put|md_get)'
LTAIL += 2>&1 | $(LGREP.2) | $(LGREP.nsmb) || true
#
diff --git a/usr/src/uts/sparc/nsmb/Makefile b/usr/src/uts/sparc/nsmb/Makefile
index 174d0f77bf..79515e3de4 100644
--- a/usr/src/uts/sparc/nsmb/Makefile
+++ b/usr/src/uts/sparc/nsmb/Makefile
@@ -92,14 +92,12 @@ CERRWARN += -erroff=E_STATEMENT_NOT_REACHED
INC_PATH += -I$(UTSBASE)/common/fs/smbclnt
LDFLAGS += -dy -Ncrypto/md4 -Ncrypto/md5 -Nmisc/tlimod
-LINTTAGS += -erroff=E_FUNC_RET_ALWAYS_IGNOR2
-LINTTAGS += -erroff=E_FUNC_RET_MAYBE_IGNORED2
# Until CR 4994570 is fixed...
LINTTAGS += -erroff=E_BAD_FORMAT_ARG_TYPE2
# The mb_put/md_get functions are intentionally used with and without
# return value checks, so filter those out like LGREP.2 does.
-LGREP.nsmb = egrep -v ' ignored: (mb_put|md_get)'
+LGREP.nsmb = egrep -v ' ignored: (mb_init|mb_put|md_get)'
LTAIL += 2>&1 | $(LGREP.2) | $(LGREP.nsmb) || true
#
diff --git a/usr/src/uts/sparc/smbfs/Makefile b/usr/src/uts/sparc/smbfs/Makefile
index 3f75aa8c83..26be8f8780 100644
--- a/usr/src/uts/sparc/smbfs/Makefile
+++ b/usr/src/uts/sparc/smbfs/Makefile
@@ -63,16 +63,15 @@ $(MODSTUBS_O) := AS_CPPFLAGS += -DSMBFS_MODULE
CLEANFILES += $(MODSTUBS_O)
C99MODE = $(C99_ENABLE)
INC_PATH += -I$(UTSBASE)/common/fs/smbclnt
+INC_PATH += -I$(COMMONBASE)/smbclnt
LDFLAGS += -dy -Ndrv/nsmb
-LINTTAGS += -erroff=E_FUNC_RET_ALWAYS_IGNOR2
-LINTTAGS += -erroff=E_FUNC_RET_MAYBE_IGNORED2
# Until CR 4994570 is fixed...
LINTTAGS += -erroff=E_BAD_FORMAT_ARG_TYPE2
# The mb_put/md_get functions are intentionally used with and without
# return value checks, so filter those out like LGREP.2 does.
-LGREP.nsmb = egrep -v ' ignored: (mb_put|md_get)'
+LGREP.nsmb = egrep -v ' ignored: (mb_init|mb_put|md_get)'
LTAIL += 2>&1 | $(LGREP.2) | $(LGREP.nsmb) || true
#