From 8329232e00f1048795bae53acb230316243aadb5 Mon Sep 17 00:00:00 2001 From: Gordon Ross Date: Sat, 12 Aug 2017 10:54:18 -0400 Subject: 9874 Add fksmbcl development tool Reviewed by: Evan Layton Reviewed by: Matt Barden Approved by: Joshua M. Clulow --- usr/src/lib/Makefile | 2 + usr/src/lib/libfakekernel/Makefile.com | 7 +- usr/src/lib/libfakekernel/common/copy.c | 30 +- usr/src/lib/libfakekernel/common/cred.c | 60 +- usr/src/lib/libfakekernel/common/kmisc.c | 13 +- usr/src/lib/libfakekernel/common/mapfile-vers | 12 +- usr/src/lib/libfakekernel/common/printf.c | 29 +- usr/src/lib/libfakekernel/common/rwlock.c | 1 - usr/src/lib/libfakekernel/common/sys/cmn_err.h | 8 + usr/src/lib/libfakekernel/common/sys/cred.h | 5 +- usr/src/lib/libfakekernel/common/sys/cyclic.h | 87 + usr/src/lib/libfakekernel/common/uio.c | 4 +- usr/src/lib/libsmbfs/Makefile.com | 16 +- usr/src/lib/libsmbfs/netsmb/smb_lib.h | 8 +- usr/src/lib/libsmbfs/smb/acl_api.c | 8 +- usr/src/lib/libsmbfs/smb/ctx.c | 49 +- usr/src/lib/libsmbfs/smb/file.c | 14 +- usr/src/lib/libsmbfs/smb/findvc.c | 6 +- usr/src/lib/libsmbfs/smb/iod_wk.c | 12 +- usr/src/lib/libsmbfs/smb/keychain.c | 6 +- usr/src/lib/libsmbfs/smb/lgrep.awk | 68 - usr/src/lib/libsmbfs/smb/mapfile-vers | 16 +- usr/src/lib/libsmbfs/smb/print.c | 11 +- usr/src/lib/libsmbfs/smb/rcfile.c | 12 +- usr/src/lib/libsmbfs/smb/rq.c | 9 +- usr/src/lib/smbclnt/Makefile | 24 + usr/src/lib/smbclnt/Makefile.lib | 51 + usr/src/lib/smbclnt/Makefile.smbclnt | 66 + usr/src/lib/smbclnt/Makefile.subdirs | 43 + usr/src/lib/smbclnt/Makefile.targ | 50 + usr/src/lib/smbclnt/libfknsmb/Makefile | 16 + usr/src/lib/smbclnt/libfknsmb/Makefile.com | 106 + usr/src/lib/smbclnt/libfknsmb/amd64/Makefile | 21 + usr/src/lib/smbclnt/libfknsmb/common/fake_ddi.c | 133 ++ usr/src/lib/smbclnt/libfknsmb/common/fake_fio.c | 105 + usr/src/lib/smbclnt/libfknsmb/common/fake_kmem.c | 45 + usr/src/lib/smbclnt/libfknsmb/common/fake_ktli.c | 432 ++++ usr/src/lib/smbclnt/libfknsmb/common/fake_pkey.c | 48 + usr/src/lib/smbclnt/libfknsmb/common/fake_policy.c | 90 + usr/src/lib/smbclnt/libfknsmb/common/fake_sdt.c | 50 + usr/src/lib/smbclnt/libfknsmb/common/fake_softc.c | 263 +++ usr/src/lib/smbclnt/libfknsmb/common/fake_stream.c | 1377 +++++++++++++ .../lib/smbclnt/libfknsmb/common/fake_strsubr.c | 160 ++ usr/src/lib/smbclnt/libfknsmb/common/fake_xti.h | 314 +++ .../lib/smbclnt/libfknsmb/common/fksmb_sign_pkcs.c | 163 ++ usr/src/lib/smbclnt/libfknsmb/common/libfknsmb.h | 45 + usr/src/lib/smbclnt/libfknsmb/common/llib-lfknsmb | 19 + usr/src/lib/smbclnt/libfknsmb/common/mapfile-vers | 121 ++ usr/src/lib/smbclnt/libfknsmb/common/sys/ftrace.h | 67 + usr/src/lib/smbclnt/libfknsmb/common/sys/kidmap.h | 183 ++ usr/src/lib/smbclnt/libfknsmb/common/sys/policy.h | 50 + usr/src/lib/smbclnt/libfknsmb/common/sys/sdt.h | 70 + usr/src/lib/smbclnt/libfknsmb/common/sys/strft.h | 65 + usr/src/lib/smbclnt/libfknsmb/common/sys/sunddi.h | 141 ++ usr/src/lib/smbclnt/libfknsmb/common/sys/vfs.h | 622 ++++++ .../lib/smbclnt/libfknsmb/common/sys/vfs_opreg.h | 116 ++ usr/src/lib/smbclnt/libfknsmb/common/sys/vnode.h | 1452 +++++++++++++ usr/src/lib/smbclnt/libfknsmb/i386/Makefile | 18 + usr/src/lib/smbclnt/libfknsmb/sparc/Makefile | 18 + usr/src/lib/smbclnt/libfknsmb/sparcv9/Makefile | 23 + usr/src/lib/smbclnt/libfksmbfs/Makefile | 16 + usr/src/lib/smbclnt/libfksmbfs/Makefile.com | 137 ++ usr/src/lib/smbclnt/libfksmbfs/amd64/Makefile | 23 + usr/src/lib/smbclnt/libfksmbfs/common/fake_fssub.c | 432 ++++ .../lib/smbclnt/libfksmbfs/common/fake_getdents.c | 96 + .../lib/smbclnt/libfksmbfs/common/fake_lookup.c | 173 ++ usr/src/lib/smbclnt/libfksmbfs/common/fake_misc.c | 108 + .../lib/smbclnt/libfksmbfs/common/fake_modconf.c | 195 ++ .../lib/smbclnt/libfksmbfs/common/fake_nbmlock.c | 124 ++ usr/src/lib/smbclnt/libfksmbfs/common/fake_open.c | 340 +++ .../lib/smbclnt/libfksmbfs/common/fake_rename.c | 123 ++ usr/src/lib/smbclnt/libfksmbfs/common/fake_rw.c | 203 ++ usr/src/lib/smbclnt/libfksmbfs/common/fake_stat.c | 96 + .../lib/smbclnt/libfksmbfs/common/fake_unlink.c | 91 + usr/src/lib/smbclnt/libfksmbfs/common/fake_vfs.c | 2155 ++++++++++++++++++++ usr/src/lib/smbclnt/libfksmbfs/common/fake_vnode.c | 2026 ++++++++++++++++++ usr/src/lib/smbclnt/libfksmbfs/common/fake_zone.c | 76 + .../lib/smbclnt/libfksmbfs/common/fksmbfs_rwlock.c | 235 +++ usr/src/lib/smbclnt/libfksmbfs/common/libfksmbfs.h | 73 + .../lib/smbclnt/libfksmbfs/common/llib-lfksmbfs | 19 + usr/src/lib/smbclnt/libfksmbfs/common/mapfile-vers | 68 + usr/src/lib/smbclnt/libfksmbfs/i386/Makefile | 20 + usr/src/lib/smbclnt/libfksmbfs/sparc/Makefile | 20 + usr/src/lib/smbclnt/libfksmbfs/sparcv9/Makefile | 24 + 84 files changed, 13791 insertions(+), 142 deletions(-) create mode 100644 usr/src/lib/libfakekernel/common/sys/cyclic.h delete mode 100644 usr/src/lib/libsmbfs/smb/lgrep.awk create mode 100644 usr/src/lib/smbclnt/Makefile create mode 100644 usr/src/lib/smbclnt/Makefile.lib create mode 100644 usr/src/lib/smbclnt/Makefile.smbclnt create mode 100644 usr/src/lib/smbclnt/Makefile.subdirs create mode 100644 usr/src/lib/smbclnt/Makefile.targ create mode 100644 usr/src/lib/smbclnt/libfknsmb/Makefile create mode 100644 usr/src/lib/smbclnt/libfknsmb/Makefile.com create mode 100644 usr/src/lib/smbclnt/libfknsmb/amd64/Makefile create mode 100644 usr/src/lib/smbclnt/libfknsmb/common/fake_ddi.c create mode 100644 usr/src/lib/smbclnt/libfknsmb/common/fake_fio.c create mode 100644 usr/src/lib/smbclnt/libfknsmb/common/fake_kmem.c create mode 100644 usr/src/lib/smbclnt/libfknsmb/common/fake_ktli.c create mode 100644 usr/src/lib/smbclnt/libfknsmb/common/fake_pkey.c create mode 100644 usr/src/lib/smbclnt/libfknsmb/common/fake_policy.c create mode 100644 usr/src/lib/smbclnt/libfknsmb/common/fake_sdt.c create mode 100644 usr/src/lib/smbclnt/libfknsmb/common/fake_softc.c create mode 100644 usr/src/lib/smbclnt/libfknsmb/common/fake_stream.c create mode 100644 usr/src/lib/smbclnt/libfknsmb/common/fake_strsubr.c create mode 100644 usr/src/lib/smbclnt/libfknsmb/common/fake_xti.h create mode 100644 usr/src/lib/smbclnt/libfknsmb/common/fksmb_sign_pkcs.c create mode 100644 usr/src/lib/smbclnt/libfknsmb/common/libfknsmb.h create mode 100644 usr/src/lib/smbclnt/libfknsmb/common/llib-lfknsmb create mode 100644 usr/src/lib/smbclnt/libfknsmb/common/mapfile-vers create mode 100644 usr/src/lib/smbclnt/libfknsmb/common/sys/ftrace.h create mode 100644 usr/src/lib/smbclnt/libfknsmb/common/sys/kidmap.h create mode 100644 usr/src/lib/smbclnt/libfknsmb/common/sys/policy.h create mode 100644 usr/src/lib/smbclnt/libfknsmb/common/sys/sdt.h create mode 100644 usr/src/lib/smbclnt/libfknsmb/common/sys/strft.h create mode 100644 usr/src/lib/smbclnt/libfknsmb/common/sys/sunddi.h create mode 100644 usr/src/lib/smbclnt/libfknsmb/common/sys/vfs.h create mode 100644 usr/src/lib/smbclnt/libfknsmb/common/sys/vfs_opreg.h create mode 100644 usr/src/lib/smbclnt/libfknsmb/common/sys/vnode.h create mode 100644 usr/src/lib/smbclnt/libfknsmb/i386/Makefile create mode 100644 usr/src/lib/smbclnt/libfknsmb/sparc/Makefile create mode 100644 usr/src/lib/smbclnt/libfknsmb/sparcv9/Makefile create mode 100644 usr/src/lib/smbclnt/libfksmbfs/Makefile create mode 100644 usr/src/lib/smbclnt/libfksmbfs/Makefile.com create mode 100644 usr/src/lib/smbclnt/libfksmbfs/amd64/Makefile create mode 100644 usr/src/lib/smbclnt/libfksmbfs/common/fake_fssub.c create mode 100644 usr/src/lib/smbclnt/libfksmbfs/common/fake_getdents.c create mode 100644 usr/src/lib/smbclnt/libfksmbfs/common/fake_lookup.c create mode 100644 usr/src/lib/smbclnt/libfksmbfs/common/fake_misc.c create mode 100644 usr/src/lib/smbclnt/libfksmbfs/common/fake_modconf.c create mode 100644 usr/src/lib/smbclnt/libfksmbfs/common/fake_nbmlock.c create mode 100644 usr/src/lib/smbclnt/libfksmbfs/common/fake_open.c create mode 100644 usr/src/lib/smbclnt/libfksmbfs/common/fake_rename.c create mode 100644 usr/src/lib/smbclnt/libfksmbfs/common/fake_rw.c create mode 100644 usr/src/lib/smbclnt/libfksmbfs/common/fake_stat.c create mode 100644 usr/src/lib/smbclnt/libfksmbfs/common/fake_unlink.c create mode 100644 usr/src/lib/smbclnt/libfksmbfs/common/fake_vfs.c create mode 100644 usr/src/lib/smbclnt/libfksmbfs/common/fake_vnode.c create mode 100644 usr/src/lib/smbclnt/libfksmbfs/common/fake_zone.c create mode 100644 usr/src/lib/smbclnt/libfksmbfs/common/fksmbfs_rwlock.c create mode 100644 usr/src/lib/smbclnt/libfksmbfs/common/libfksmbfs.h create mode 100644 usr/src/lib/smbclnt/libfksmbfs/common/llib-lfksmbfs create mode 100644 usr/src/lib/smbclnt/libfksmbfs/common/mapfile-vers create mode 100644 usr/src/lib/smbclnt/libfksmbfs/i386/Makefile create mode 100644 usr/src/lib/smbclnt/libfksmbfs/sparc/Makefile create mode 100644 usr/src/lib/smbclnt/libfksmbfs/sparcv9/Makefile (limited to 'usr/src/lib') diff --git a/usr/src/lib/Makefile b/usr/src/lib/Makefile index 8c5142641d..bc68f6fc34 100644 --- a/usr/src/lib/Makefile +++ b/usr/src/lib/Makefile @@ -265,6 +265,7 @@ SUBDIRS += \ rpcsec_gss \ sasl_plugins \ scsi \ + smbclnt \ smbsrv \ smhba \ sun_fc \ @@ -697,6 +698,7 @@ raidcfg_plugins: libraidcfg librcm libcfgadm libpicl libpicltree rpcsec_gss: libgss sasl_plugins: pkcs11 libgss libsasl scsi: libfru libumem libdevid libdevinfo +smbclnt: libfakekernel pkcs11 smbsrv: libxnet libpthread librt libshare libidmap pkcs11 libsqlite \ libcryptoutil libreparse libcmdutils libresolv2 libsmbfs \ libuuid libfakekernel libads libgss libldap5 krb5 libmlrpc diff --git a/usr/src/lib/libfakekernel/Makefile.com b/usr/src/lib/libfakekernel/Makefile.com index ef1abe4072..f9135717e6 100644 --- a/usr/src/lib/libfakekernel/Makefile.com +++ b/usr/src/lib/libfakekernel/Makefile.com @@ -56,10 +56,15 @@ $(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC) CSTD = $(CSTD_GNU99) C99LMODE = -Xc99=%all +CFLAGS += $(CCVERBOSE) + # Note: need our sys includes _before_ ENVCPPFLAGS, proto etc. +# Also Note: intentionally override CPPFLAGS, not += CPPFLAGS.first += -I../common +CPPFLAGS= $(CPPFLAGS.first) + +INCS += -I$(SRC)/uts/common -CFLAGS += $(CCVERBOSE) CPPFLAGS += $(INCS) -D_REENTRANT -D_FAKE_KERNEL CPPFLAGS += -D_FILE_OFFSET_BITS=64 diff --git a/usr/src/lib/libfakekernel/common/copy.c b/usr/src/lib/libfakekernel/common/copy.c index b1eb215b5c..77bf2e8415 100644 --- a/usr/src/lib/libfakekernel/common/copy.c +++ b/usr/src/lib/libfakekernel/common/copy.c @@ -10,7 +10,7 @@ */ /* - * Copyright 2013 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ @@ -19,6 +19,20 @@ #include #include +int +copyin(const void *u, void *k, size_t s) +{ + bcopy(u, k, s); + return (0); +} + +int +copyout(const void *k, void *u, size_t s) +{ + bcopy(k, u, s); + return (0); +} + int copyinstr(const char *src, char *dst, size_t max_len, size_t *copied) { @@ -48,3 +62,17 @@ ovbcopy(const void *src, void *dst, size_t len) { (void) memmove(dst, src, len); } + +/* ARGSUSED */ +int +ddi_copyin(const void *buf, void *kernbuf, size_t size, int flags) +{ + return (copyin(buf, kernbuf, size)); +} + +/* ARGSUSED */ +int +ddi_copyout(const void *buf, void *kernbuf, size_t size, int flags) +{ + return (copyout(buf, kernbuf, size)); +} diff --git a/usr/src/lib/libfakekernel/common/cred.c b/usr/src/lib/libfakekernel/common/cred.c index 1563f02ac9..0920599d0a 100644 --- a/usr/src/lib/libfakekernel/common/cred.c +++ b/usr/src/lib/libfakekernel/common/cred.c @@ -10,28 +10,51 @@ */ /* - * Copyright 2013 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. * Copyright 2017 RackTop Systems. */ - #include #include #include #include +#include +#include + +/* + * This library does not implement real credentials. All contexts + * use an opaque cred_t object, and all activity happens in the + * context of the user who runs the program. + */ + +extern struct zone zone0; struct cred { + uid_t cr_uid; + ksid_t *cr_ksid; uint32_t pad[100]; }; cred_t cred0; cred_t *kcred = &cred0; +/* + * Note that fksmbd uses CRED() for SMB user logons, but uses + * zone_kcred() for operations done internally by the server. + * Let CRED() (_curcred()) return &cred1, so it's different from + * kcred, otherwise tests like: (cred == kcred) are always true. + * Also, only cred1 will have a ksid (not kcred). + * The UID and SID are both "nobody". + */ +ksiddomain_t ksdom1 = {1, 5, "S-1-0", {0}}; +ksid_t ksid1 = { 60001, 0, 0, &ksdom1}; +cred_t cred1 = { 60001, &ksid1 }; + cred_t * _curcred(void) { /* Thread-specific data? */ - return (&cred0); + return (&cred1); } /*ARGSUSED*/ @@ -50,14 +73,14 @@ crhold(cred_t *cr) uid_t crgetuid(const cred_t *cr) { - return (0); + return (cr->cr_uid); } /*ARGSUSED*/ uid_t crgetruid(const cred_t *cr) { - return (0); + return (cr->cr_uid); } /*ARGSUSED*/ @@ -81,8 +104,35 @@ crgetgroups(const cred_t *cr) return (NULL); } +/*ARGSUSED*/ +zoneid_t +crgetzoneid(const cred_t *cr) +{ + return (GLOBAL_ZONEID); +} + +/*ARGSUSED*/ +struct zone * +crgetzone(const cred_t *cr) +{ + return (&zone0); +} + cred_t * zone_kcred(void) { return (kcred); } + +/*ARGSUSED*/ +ksid_t * +crgetsid(const cred_t *cr, int i) +{ + return (cr->cr_ksid); +} + +cred_t * +ddi_get_cred(void) +{ + return (_curcred()); +} diff --git a/usr/src/lib/libfakekernel/common/kmisc.c b/usr/src/lib/libfakekernel/common/kmisc.c index 2849552a66..5feaa66a28 100644 --- a/usr/src/lib/libfakekernel/common/kmisc.c +++ b/usr/src/lib/libfakekernel/common/kmisc.c @@ -30,9 +30,12 @@ #include pri_t minclsyspri = 60; +extern zone_t zone0; /* Some kernel code takes the address of this. */ -proc_t p0; +proc_t p0 = { + .p_zone = &zone0, 0 +}; proc_t * _curproc(void) @@ -99,11 +102,10 @@ ddi_strtoul(const char *str, char **endp, int base, unsigned long *res) } int -ddi_strtoull(const char *str, char **nptr, int base, u_longlong_t *res) +ddi_strtoull(const char *str, char **endp, int base, u_longlong_t *res) { - char *end; - - *res = strtoull(str, &end, base); + errno = 0; + *res = strtoull(str, endp, base); if (*res == 0) return (errno); return (0); @@ -116,6 +118,7 @@ delay(clock_t ticks) (void) poll(0, 0, msec); } +/* ARGSUSED */ int issig(int why) { diff --git a/usr/src/lib/libfakekernel/common/mapfile-vers b/usr/src/lib/libfakekernel/common/mapfile-vers index 42af216580..7f7422c63c 100644 --- a/usr/src/lib/libfakekernel/common/mapfile-vers +++ b/usr/src/lib/libfakekernel/common/mapfile-vers @@ -42,7 +42,9 @@ SYMBOL_VERSION SUNWprivate_1.1 { aok { FLAGS = NODIRECT }; boot_time; cmn_err; + copyin; copyinstr; + copyout; copystr; cyclic_add; @@ -55,6 +57,8 @@ SYMBOL_VERSION SUNWprivate_1.1 { crgetgid; crgetngroups; crgetgroups; + crgetzone; + crgetzoneid; crhold; cv_broadcast; @@ -69,12 +73,16 @@ SYMBOL_VERSION SUNWprivate_1.1 { cv_wait; cv_wait_sig; + ddi_copyin; + ddi_copyout; + ddi_get_cred; ddi_get_lbolt64; ddi_get_lbolt; ddi_get_pid; ddi_strtoul; ddi_strtoull; + debug_enter; delay; fm_panic; @@ -196,7 +204,7 @@ SYMBOL_VERSION SUNWprivate_1.1 { strfree; system_taskq; - system_taskq_fini; + system_taskq_fini; system_taskq_init; taskq_create; taskq_create_proc; @@ -225,8 +233,10 @@ SYMBOL_VERSION SUNWprivate_1.1 { vcmn_err; vmem_qcache_reap; vpanic; + vzprintf; zone0; zone_kcred; + zprintf; zthread_create; zthread_exit; diff --git a/usr/src/lib/libfakekernel/common/printf.c b/usr/src/lib/libfakekernel/common/printf.c index c8f459dd8c..bbf350b75e 100644 --- a/usr/src/lib/libfakekernel/common/printf.c +++ b/usr/src/lib/libfakekernel/common/printf.c @@ -21,7 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012 by Delphix. All rights reserved. - * Copyright 2013 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. * Copyright 2017 RackTop Systems. * Copyright (c) 2018, Joyent, Inc. */ @@ -36,6 +36,7 @@ #include void abort(void) __NORETURN; +void debug_enter(char *); char *volatile panicstr; va_list panicargs; @@ -100,6 +101,24 @@ fakekernel_cprintf(const char *fmt, va_list adx, int flags, fakekernel_putlog(bufp, len, flags); } +/* ARGSUSED */ +void +vzprintf(zoneid_t zoneid, const char *fmt, va_list adx) +{ + fakekernel_cprintf(fmt, adx, SL_CONSOLE | SL_NOTE, "", ""); +} + +/*PRINTFLIKE2*/ +void +zprintf(zoneid_t zoneid, const char *fmt, ...) +{ + va_list adx; + + va_start(adx, fmt); + vzprintf(zoneid, fmt, adx); + va_end(adx); +} + /* * "User-level crash dump", if you will. */ @@ -116,6 +135,7 @@ vpanic(const char *fmt, va_list adx) /* Call libc`assfail() so that mdb ::status works */ (void) vsnprintf(panicbuf, sizeof (panicbuf), fmt, adx); + debug_enter(panicbuf); (void) assfail(panicbuf, "(panic)", 0); abort(); /* avoid "noreturn" warnings */ @@ -164,3 +184,10 @@ cmn_err(int ce, const char *fmt, ...) vcmn_err(ce, fmt, adx); va_end(adx); } + +/* ARGSUSED */ +void +debug_enter(char *str) +{ + /* Just a place for a break point. */ +} diff --git a/usr/src/lib/libfakekernel/common/rwlock.c b/usr/src/lib/libfakekernel/common/rwlock.c index 17b4ca604d..edc9bfd092 100644 --- a/usr/src/lib/libfakekernel/common/rwlock.c +++ b/usr/src/lib/libfakekernel/common/rwlock.c @@ -23,7 +23,6 @@ #include #include #include -#include #include /* avoiding synch.h */ diff --git a/usr/src/lib/libfakekernel/common/sys/cmn_err.h b/usr/src/lib/libfakekernel/common/sys/cmn_err.h index c77b22b868..b9818f58c5 100644 --- a/usr/src/lib/libfakekernel/common/sys/cmn_err.h +++ b/usr/src/lib/libfakekernel/common/sys/cmn_err.h @@ -64,6 +64,10 @@ extern void cmn_err(int, const char *, ...) extern void vcmn_err(int, const char *, __va_list) __KVPRINTFLIKE(2); +/*PRINTFLIKE3*/ +extern void zcmn_err(zoneid_t, int, const char *, ...) + __KPRINTFLIKE(3); + /*PRINTFLIKE1*/ extern void panic(const char *, ...) __KPRINTFLIKE(1) __NORETURN; @@ -71,6 +75,10 @@ extern void panic(const char *, ...) extern void vpanic(const char *, __va_list) __KVPRINTFLIKE(1) __NORETURN; +/*PRINTFLIKE2*/ +extern void zprintf(zoneid_t, const char *, ...) + __KPRINTFLIKE(2); + #endif /* !_ASM && (_KERNEL || _FAKE_KERNEL) */ #ifdef __cplusplus diff --git a/usr/src/lib/libfakekernel/common/sys/cred.h b/usr/src/lib/libfakekernel/common/sys/cred.h index d544e04275..a338214843 100644 --- a/usr/src/lib/libfakekernel/common/sys/cred.h +++ b/usr/src/lib/libfakekernel/common/sys/cred.h @@ -27,7 +27,7 @@ */ /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ -/* All Rights Reserved */ +/* All Rights Reserved */ /* * Portions of this source code were derived from Berkeley 4.3 BSD @@ -66,6 +66,8 @@ extern void cred_init(void); extern void crhold(cred_t *); extern void crfree(cred_t *); +extern int groupmember(gid_t, const cred_t *); + extern cred_t *zone_kcred(void); extern uid_t crgetuid(const cred_t *); @@ -75,6 +77,7 @@ extern gid_t crgetgid(const cred_t *); extern gid_t crgetrgid(const cred_t *); extern gid_t crgetsgid(const cred_t *); extern zoneid_t crgetzoneid(const cred_t *); +extern struct zone *crgetzone(const cred_t *); extern projid_t crgetprojid(const cred_t *); extern const gid_t *crgetgroups(const cred_t *); diff --git a/usr/src/lib/libfakekernel/common/sys/cyclic.h b/usr/src/lib/libfakekernel/common/sys/cyclic.h new file mode 100644 index 0000000000..56589ae7f1 --- /dev/null +++ b/usr/src/lib/libfakekernel/common/sys/cyclic.h @@ -0,0 +1,87 @@ +/* + * 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 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * Copyright 2017 RackTop Systems. + */ + +#ifndef _SYS_CYCLIC_H +#define _SYS_CYCLIC_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ASM +#include +#endif /* !_ASM */ + +#define CY_LOW_LEVEL 0 +#define CY_LOCK_LEVEL 1 +#define CY_HIGH_LEVEL 2 +#define CY_SOFT_LEVELS 2 +#define CY_LEVELS 3 + +#ifndef _ASM + +typedef uintptr_t cyclic_id_t; +typedef int cyc_index_t; +typedef int cyc_cookie_t; +typedef uint16_t cyc_level_t; +typedef void (*cyc_func_t)(void *); +typedef void *cyb_arg_t; + +#define CYCLIC_NONE ((cyclic_id_t)0) + +typedef struct cyc_handler { + cyc_func_t cyh_func; + void *cyh_arg; + cyc_level_t cyh_level; +} cyc_handler_t; + +typedef struct cyc_time { + hrtime_t cyt_when; + hrtime_t cyt_interval; +} cyc_time_t; + +#define CY_INFINITY INT64_MAX + +#if defined(_KERNEL) || defined(_FAKE_KERNEL) + +extern cyclic_id_t cyclic_add(cyc_handler_t *, cyc_time_t *); +extern void cyclic_remove(cyclic_id_t); +extern int cyclic_reprogram(cyclic_id_t, hrtime_t); +extern hrtime_t cyclic_getres(); + +extern void cyclic_suspend(); +extern void cyclic_resume(); + +#endif /* _KERNEL || _FAKE_KERNEL */ + +#endif /* !_ASM */ + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_CYCLIC_H */ diff --git a/usr/src/lib/libfakekernel/common/uio.c b/usr/src/lib/libfakekernel/common/uio.c index 3048faff58..99cb4e04e8 100644 --- a/usr/src/lib/libfakekernel/common/uio.c +++ b/usr/src/lib/libfakekernel/common/uio.c @@ -10,7 +10,7 @@ */ /* - * Copyright 2015 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ #include @@ -42,10 +42,10 @@ uiomove(void *p, size_t n, enum uio_rw rw, struct uio *uio) } switch (uio->uio_segflg) { - case UIO_USERSPACE: case UIO_USERISPACE: return (EINVAL); + case UIO_USERSPACE: case UIO_SYSSPACE: if (rw == UIO_READ) bcopy(p, iov->iov_base, cnt); diff --git a/usr/src/lib/libsmbfs/Makefile.com b/usr/src/lib/libsmbfs/Makefile.com index 160494aff1..3a5c62c46c 100644 --- a/usr/src/lib/libsmbfs/Makefile.com +++ b/usr/src/lib/libsmbfs/Makefile.com @@ -111,23 +111,21 @@ CPPFLAGS += -D__EXTENSIONS__ -D_REENTRANT -DMIA \ -I$(SRC)/uts/common \ -I$(SRC)/common/smbclnt +# This is pretty mature code, so let's just ignore these. +LINTCHECKFLAGS += -erroff=E_INCONS_ARG_DECL2 +LINTCHECKFLAGS += -erroff=E_INCONS_VAL_TYPE_DECL2 +LINTCHECKFLAGS += -erroff=E_FUNC_RET_MAYBE_IGNORED2 +LINTCHECKFLAGS += -erroff=E_FUNC_RET_ALWAYS_IGNOR2 + # Debugging ${NOT_RELEASE_BUILD} CPPFLAGS += -DDEBUG -# Filter out the less important lint. -# See lgrep.awk -LGREP = $(AWK) -f $(SRCDIR)/lgrep.awk -LTAIL += 2>&1 | $(LGREP) - all: $(LIBS) -lint: lintcheck_t +lint: lintcheck include ../../Makefile.targ -lintcheck_t: $$(SRCS) - $(LINT.c) $(LINTCHECKFLAGS) $(SRCS) $(LDLIBS) $(LTAIL) - objs/%.o pics/%.o: $(CMNDIR)/%.c $(COMPILE.c) -o $@ $< $(POST_PROCESS_O) diff --git a/usr/src/lib/libsmbfs/netsmb/smb_lib.h b/usr/src/lib/libsmbfs/netsmb/smb_lib.h index c1dc6886ac..1f6e062e74 100644 --- a/usr/src/lib/libsmbfs/netsmb/smb_lib.h +++ b/usr/src/lib/libsmbfs/netsmb/smb_lib.h @@ -34,7 +34,7 @@ /* * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2013 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ #ifndef _NETSMB_SMB_LIB_H_ @@ -136,8 +136,8 @@ struct smb_ctx { #define ct_owner ct_iod_ssn.iod_ossn.ssn_owner #define ct_srvaddr ct_iod_ssn.iod_ossn.ssn_srvaddr #define ct_domain ct_iod_ssn.iod_ossn.ssn_domain -#define ct_user ct_iod_ssn.iod_ossn.ssn_user -#define ct_srvname ct_iod_ssn.iod_ossn.ssn_srvname +#define ct_user ct_iod_ssn.iod_ossn.ssn_user +#define ct_srvname ct_iod_ssn.iod_ossn.ssn_srvname #define ct_authflags ct_iod_ssn.iod_authflags #define ct_nthash ct_iod_ssn.iod_nthash #define ct_lmhash ct_iod_ssn.iod_lmhash @@ -181,6 +181,8 @@ struct smb_ctx { int smb_ctx_init(struct smb_ctx *); void smb_ctx_done(struct smb_ctx *); int smb_open_driver(void); +int nsmb_ioctl(int, int, void *); +int nsmb_close(int); int smb_ctx_gethandle(struct smb_ctx *); int smb_ctx_findvc(struct smb_ctx *); diff --git a/usr/src/lib/libsmbfs/smb/acl_api.c b/usr/src/lib/libsmbfs/smb/acl_api.c index 052539316b..92a3262f79 100644 --- a/usr/src/lib/libsmbfs/smb/acl_api.c +++ b/usr/src/lib/libsmbfs/smb/acl_api.c @@ -22,6 +22,8 @@ /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ /* @@ -83,6 +85,7 @@ smbfs_acl_iocget(int fd, uint32_t selector, mbdata_t *mbp) return (error); m = mbp->mb_top; + bzero(&iocb, sizeof (iocb)); iocb.addr = mtod(m, uintptr_t); iocb.alloc = m->m_maxlen; iocb.used = 0; @@ -91,7 +94,7 @@ smbfs_acl_iocget(int fd, uint32_t selector, mbdata_t *mbp) /* * This does the OTW Get. */ - if (ioctl(fd, SMBFSIO_GETSD, &iocb) < 0) { + if (nsmb_ioctl(fd, SMBFSIO_GETSD, &iocb) < 0) { error = errno; goto errout; } @@ -120,6 +123,7 @@ smbfs_acl_iocset(int fd, uint32_t selector, mbdata_t *mbp) if (mbp->mb_top != m) mb_initm(mbp, m); + bzero(&iocb, sizeof (iocb)); iocb.addr = mtod(m, uintptr_t); iocb.alloc = m->m_maxlen; iocb.used = m->m_len; @@ -128,7 +132,7 @@ smbfs_acl_iocset(int fd, uint32_t selector, mbdata_t *mbp) /* * This does the OTW Set. */ - if (ioctl(fd, SMBFSIO_SETSD, &iocb) < 0) + if (nsmb_ioctl(fd, SMBFSIO_SETSD, &iocb) < 0) error = errno; return (error); diff --git a/usr/src/lib/libsmbfs/smb/ctx.c b/usr/src/lib/libsmbfs/smb/ctx.c index 9455a92344..e28599e28f 100644 --- a/usr/src/lib/libsmbfs/smb/ctx.c +++ b/usr/src/lib/libsmbfs/smb/ctx.c @@ -34,7 +34,7 @@ /* * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2013 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ #include @@ -333,7 +333,12 @@ smb_ctx_scan_argv(struct smb_ctx *ctx, int argc, char **argv, cf_opt_lock(); /* Careful: no return/goto before cf_opt_unlock! */ while (error == 0) { - opt = cf_getopt(argc, argv, STDPARAM_OPT); + /* + * Leading ':' tells this to skip unknown opts. + * Just get -A and -U here so we know the user + * for config file parsing. + */ + opt = cf_getopt(argc, argv, ":AU:"); if (opt == -1) break; arg = cf_optarg; @@ -398,7 +403,7 @@ smb_ctx_done(struct smb_ctx *ctx) rpc_cleanup_smbctx(ctx); if (ctx->ct_dev_fd != -1) { - close(ctx->ct_dev_fd); + nsmb_close(ctx->ct_dev_fd); ctx->ct_dev_fd = -1; } if (ctx->ct_door_fd != -1) { @@ -1147,6 +1152,10 @@ smb_ctx_resolve(struct smb_ctx *ctx) return (0); } +/* + * Note: The next three have NODIRECT binding so the + * "fksmbcl" development tool can provide its own. + */ int smb_open_driver() { @@ -1163,6 +1172,19 @@ smb_open_driver() return (fd); } +int +nsmb_close(int fd) +{ + return (close(fd)); +} + +int +nsmb_ioctl(int fd, int cmd, void *arg) +{ + return (ioctl(fd, cmd, arg)); +} + + int smb_ctx_gethandle(struct smb_ctx *ctx) { @@ -1171,7 +1193,7 @@ smb_ctx_gethandle(struct smb_ctx *ctx) if (ctx->ct_dev_fd != -1) { rpc_cleanup_smbctx(ctx); - close(ctx->ct_dev_fd); + nsmb_close(ctx->ct_dev_fd); ctx->ct_dev_fd = -1; ctx->ct_flags &= ~SMBCF_SSNACTIVE; } @@ -1187,12 +1209,12 @@ smb_ctx_gethandle(struct smb_ctx *ctx) /* * Check the driver version (paranoia) */ - if (ioctl(fd, SMBIOC_GETVERS, &version) < 0) + if (nsmb_ioctl(fd, SMBIOC_GETVERS, &version) < 0) version = 0; if (version != NSMB_VERSION) { smb_error(dgettext(TEXT_DOMAIN, "incorrect driver version"), 0); - close(fd); + nsmb_close(fd); return (ENODEV); } @@ -1220,6 +1242,15 @@ smb_ctx_get_ssn(struct smb_ctx *ctx) if (err == 0) { DPRINT("found an existing VC"); } else { + /* + * If we're authenticating (real user, not NULL session) + * and we don't yet have a password, return EAUTH and + * the caller will prompt for it and call again. + */ + if (ctx->ct_user[0] != '\0' && + ctx->ct_password[0] == '\0') + return (EAUTH); + /* * This calls the IOD to create a new session. */ @@ -1272,7 +1303,7 @@ smb_ctx_get_tree(struct smb_ctx *ctx) * * The driver does the actual TCON call. */ - if (ioctl(ctx->ct_dev_fd, cmd, tcon) == -1) { + if (nsmb_ioctl(ctx->ct_dev_fd, cmd, tcon) == -1) { err = errno; goto out; } @@ -1303,7 +1334,7 @@ smb_ctx_flags2(struct smb_ctx *ctx) { uint16_t flags2; - if (ioctl(ctx->ct_dev_fd, SMBIOC_FLAGS2, &flags2) == -1) { + if (nsmb_ioctl(ctx->ct_dev_fd, SMBIOC_FLAGS2, &flags2) == -1) { smb_error(dgettext(TEXT_DOMAIN, "can't get flags2 for a session"), errno); return (-1); @@ -1321,7 +1352,7 @@ smb_fh_getssnkey(int dev_fd, uchar_t *key, size_t len) if (len < SMBIOC_HASH_SZ) return (EINVAL); - if (ioctl(dev_fd, SMBIOC_GETSSNKEY, key) == -1) + if (nsmb_ioctl(dev_fd, SMBIOC_GETSSNKEY, key) == -1) return (errno); return (0); diff --git a/usr/src/lib/libsmbfs/smb/file.c b/usr/src/lib/libsmbfs/smb/file.c index 8ca9d2cee1..b104502d9c 100644 --- a/usr/src/lib/libsmbfs/smb/file.c +++ b/usr/src/lib/libsmbfs/smb/file.c @@ -33,7 +33,7 @@ */ /* - * Copyright 2011 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -65,7 +65,7 @@ int smb_fh_close(int fd) { - return (close(fd)); + return (nsmb_close(fd)); } int @@ -96,7 +96,7 @@ smb_fh_ntcreate( goto errout; } from_fd = ctx->ct_dev_fd; - if (ioctl(new_fd, SMBIOC_DUP_DEV, &from_fd) == -1) { + if (nsmb_ioctl(new_fd, SMBIOC_DUP_DEV, &from_fd) == -1) { err = errno; goto errout; } @@ -111,7 +111,7 @@ smb_fh_ntcreate( ioc.ioc_share_acc = share_acc; ioc.ioc_open_disp = open_disp; ioc.ioc_creat_opts = create_opts; - if (ioctl(new_fd, SMBIOC_NTCREATE, &ioc) == -1) { + if (nsmb_ioctl(new_fd, SMBIOC_NTCREATE, &ioc) == -1) { err = errno; goto errout; } @@ -120,7 +120,7 @@ smb_fh_ntcreate( errout: if (new_fd != -1) - close(new_fd); + nsmb_close(new_fd); errno = err; return (-1); } @@ -214,7 +214,7 @@ smb_fh_read(int fd, off64_t offset, size_t count, rwrq.ioc_base = dst; rwrq.ioc_cnt = count; rwrq.ioc_offset = offset; - if (ioctl(fd, SMBIOC_READ, &rwrq) == -1) { + if (nsmb_ioctl(fd, SMBIOC_READ, &rwrq) == -1) { return (-1); } return (rwrq.ioc_cnt); @@ -231,7 +231,7 @@ smb_fh_write(int fd, off64_t offset, size_t count, rwrq.ioc_base = (char *)src; rwrq.ioc_cnt = count; rwrq.ioc_offset = offset; - if (ioctl(fd, SMBIOC_WRITE, &rwrq) == -1) { + if (nsmb_ioctl(fd, SMBIOC_WRITE, &rwrq) == -1) { return (-1); } return (rwrq.ioc_cnt); diff --git a/usr/src/lib/libsmbfs/smb/findvc.c b/usr/src/lib/libsmbfs/smb/findvc.c index 63c6cce242..9d9ccd678c 100644 --- a/usr/src/lib/libsmbfs/smb/findvc.c +++ b/usr/src/lib/libsmbfs/smb/findvc.c @@ -22,6 +22,8 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ /* @@ -76,7 +78,7 @@ findvc(struct smb_ctx *ctx, struct addrinfo *ai) bzero(&ssn->ssn_srvaddr, sizeof (ssn->ssn_srvaddr)); bcopy(ai->ai_addr, &ssn->ssn_srvaddr, ai->ai_addrlen); - if (ioctl(ctx->ct_dev_fd, SMBIOC_SSN_FIND, ssn) == -1) + if (nsmb_ioctl(ctx->ct_dev_fd, SMBIOC_SSN_FIND, ssn) == -1) return (errno); return (0); @@ -137,7 +139,7 @@ int smb_ctx_kill(struct smb_ctx *ctx) { - if (ioctl(ctx->ct_dev_fd, SMBIOC_SSN_KILL, NULL) == -1) + if (nsmb_ioctl(ctx->ct_dev_fd, SMBIOC_SSN_KILL, NULL) == -1) return (errno); return (0); diff --git a/usr/src/lib/libsmbfs/smb/iod_wk.c b/usr/src/lib/libsmbfs/smb/iod_wk.c index 53f3c515be..8b56fdaf18 100644 --- a/usr/src/lib/libsmbfs/smb/iod_wk.c +++ b/usr/src/lib/libsmbfs/smb/iod_wk.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2012 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -69,7 +69,7 @@ smb_iod_work(smb_ctx_t *ctx) DPRINT("server: %s", ctx->ct_srvname); - /* Calle should have opened these */ + /* Caller should have opened these */ if (ctx->ct_tran_fd == -1 || ctx->ct_dev_fd == -1) { err = EINVAL; goto out; @@ -96,7 +96,7 @@ smb_iod_work(smb_ctx_t *ctx) * Next state is normally RECONNECT. */ DPRINT("state: idle"); - if (ioctl(ctx->ct_dev_fd, + if (nsmb_ioctl(ctx->ct_dev_fd, SMBIOC_IOD_IDLE, &vcst) == -1) { err = errno; DPRINT("ioc_idle: err %d", err); @@ -132,7 +132,7 @@ smb_iod_work(smb_ctx_t *ctx) * then get ready to try again. * Next state is normally IDLE. */ - if (ioctl(ctx->ct_dev_fd, + if (nsmb_ioctl(ctx->ct_dev_fd, SMBIOC_IOD_RCFAIL, &vcst) == -1) { err = errno; DPRINT("ioc_rcfail: err %d", err); @@ -142,7 +142,7 @@ smb_iod_work(smb_ctx_t *ctx) case SMBIOD_ST_VCACTIVE: DPRINT("state: active"); - if (ioctl(ctx->ct_dev_fd, + if (nsmb_ioctl(ctx->ct_dev_fd, SMBIOC_IOD_WORK, work) == -1) { err = errno; DPRINT("ioc_work: err %d", err); @@ -176,7 +176,7 @@ out: ctx->ct_tran_fd = -1; } if (ctx->ct_dev_fd != -1) { - close(ctx->ct_dev_fd); + nsmb_close(ctx->ct_dev_fd); ctx->ct_dev_fd = -1; } diff --git a/usr/src/lib/libsmbfs/smb/keychain.c b/usr/src/lib/libsmbfs/smb/keychain.c index fd9bcc9496..3a89fbd550 100644 --- a/usr/src/lib/libsmbfs/smb/keychain.c +++ b/usr/src/lib/libsmbfs/smb/keychain.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2011 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -128,7 +128,7 @@ smbfs_keychain_cmn( } err = 0; - if (ioctl(fd, cmd, &pk) < 0) { + if (nsmb_ioctl(fd, cmd, &pk) < 0) { err = errno; goto out; } @@ -142,7 +142,7 @@ smbfs_keychain_cmn( out: if (fd != -1) - close(fd); + nsmb_close(fd); return (err); } diff --git a/usr/src/lib/libsmbfs/smb/lgrep.awk b/usr/src/lib/libsmbfs/smb/lgrep.awk deleted file mode 100644 index fe6e8fa0b9..0000000000 --- a/usr/src/lib/libsmbfs/smb/lgrep.awk +++ /dev/null @@ -1,68 +0,0 @@ -# -# 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. -# -# Copyright 2012 Milan Jurik. All rights reserved. -# - -# 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. - -# There's no lintlib for krb5 yet (CR 6911968) -/: Warning: -lkrb5 not found/ { next; } -/: Warning: library -lkrb5 not found/ { next; } - -# Kill noise from xti.h with _XOPEN_SOURCE vs not. (CR 6911717) -/: _xti_.* .E_INCONS_ARG_DECL2./ { next; } -/: _xti_.* .E_INCONS_ARG_USED2./ { next; } -/: _xti_.* .E_INCONS_VAL_TYPE_DECL2./ { next; } - -# This is third-party code we'd rather not "fix" -/\/spnego.c.* .E_STMT_NOT_REACHED./ { next; } - -# 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/mapfile-vers b/usr/src/lib/libsmbfs/smb/mapfile-vers index 8f0c3905c6..8d658ab937 100644 --- a/usr/src/lib/libsmbfs/smb/mapfile-vers +++ b/usr/src/lib/libsmbfs/smb/mapfile-vers @@ -19,7 +19,7 @@ # # # Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. -# Copyright 2013 Nexenta Systems, Inc. All rights reserved. +# Copyright 2017 Nexenta Systems, Inc. All rights reserved. # # @@ -36,6 +36,11 @@ # MAPFILE HEADER END # +# +# Note that several things in here are NODIRECT so that the +# "fksmbcl" development tool can provide its own versions. +# + $mapfile_version 2 SYMBOL_VERSION SUNWprivate { @@ -60,6 +65,9 @@ SYMBOL_VERSION SUNWprivate { nls_str_toloc; nls_str_upper; + nsmb_close { FLAGS = NODIRECT }; + nsmb_ioctl { FLAGS = NODIRECT }; + smb_close_rcfile; smb_ctx_alloc; @@ -72,6 +80,7 @@ SYMBOL_VERSION SUNWprivate { smb_ctx_gethandle; smb_ctx_init; smb_ctx_kill; + smb_ctx_newvc { FLAGS = NODIRECT }; smb_ctx_opt; smb_ctx_parseunc; smb_ctx_readrc; @@ -108,10 +117,11 @@ SYMBOL_VERSION SUNWprivate { smb_getprogname; smb_iod_connect; smb_iod_door_path; - smb_iod_open_door; - smb_iod_start; + smb_iod_open_door { FLAGS = NODIRECT }; + smb_iod_start { FLAGS = NODIRECT }; smb_iod_work; smb_lib_init; + smb_open_driver { FLAGS = NODIRECT }; smb_open_printer; smb_open_rcfile; smb_simplecrypt; diff --git a/usr/src/lib/libsmbfs/smb/print.c b/usr/src/lib/libsmbfs/smb/print.c index c59bef81b4..80fcab7d10 100644 --- a/usr/src/lib/libsmbfs/smb/print.c +++ b/usr/src/lib/libsmbfs/smb/print.c @@ -1,5 +1,4 @@ /* - * Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2000, Boris Popov * All rights reserved. * @@ -33,6 +32,10 @@ * $Id: print.c,v 1.1.1.3 2001/07/06 22:38:43 conrad Exp $ */ +/* + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + */ + #include #include #include @@ -75,7 +78,7 @@ smb_open_printer(struct smb_ctx *ctx, const char *title, if (new_fd < 0) return (errno); from_fd = ctx->ct_dev_fd; - if (ioctl(new_fd, SMBIOC_DUP_DEV, &from_fd) == -1) { + if (nsmb_ioctl(new_fd, SMBIOC_DUP_DEV, &from_fd) == -1) { err = errno; goto errout; } @@ -88,7 +91,7 @@ smb_open_printer(struct smb_ctx *ctx, const char *title, ioc.ioc_prmode = mode; strlcpy(ioc.ioc_title, title, SMBIOC_MAX_NAME); - if (ioctl(new_fd, SMBIOC_PRINTJOB, &ioc) == -1) { + if (nsmb_ioctl(new_fd, SMBIOC_PRINTJOB, &ioc) == -1) { err = errno; goto errout; } @@ -96,7 +99,7 @@ smb_open_printer(struct smb_ctx *ctx, const char *title, return (new_fd); errout: - close(new_fd); + nsmb_close(new_fd); errno = err; return (-1); } diff --git a/usr/src/lib/libsmbfs/smb/rcfile.c b/usr/src/lib/libsmbfs/smb/rcfile.c index 22ca0fc420..56335d0954 100644 --- a/usr/src/lib/libsmbfs/smb/rcfile.c +++ b/usr/src/lib/libsmbfs/smb/rcfile.c @@ -31,6 +31,9 @@ * * $Id: rcfile.c,v 1.1.1.2 2001/07/06 22:38:43 conrad Exp $ */ +/* + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + */ #include #include @@ -343,11 +346,10 @@ set_value(struct rcfile *rcp, struct rcsection *rsp, struct rckey *rkp, { int now, new; #ifdef DEBUG - char *from; + char *from = "SMF"; - if (smb_debug) - from = (home_nsmbrc) ? - "user file" : "SMF"; + if (home_nsmbrc != 0) + from = "user file"; #endif if (strcmp(rkp->rk_name, "minauth") == 0) { @@ -485,7 +487,7 @@ rc_parse(struct rcfile *rcp) set_value(rcp, rsp, rkp, buf); state = stNewLine; rkp = NULL; - } /* while */ + } /* while */ if (c == EOF && state == stGetValue) { *next = 0; set_value(rcp, rsp, rkp, buf); diff --git a/usr/src/lib/libsmbfs/smb/rq.c b/usr/src/lib/libsmbfs/smb/rq.c index c4e929eff9..f6004dfa06 100644 --- a/usr/src/lib/libsmbfs/smb/rq.c +++ b/usr/src/lib/libsmbfs/smb/rq.c @@ -1,5 +1,4 @@ /* - * Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2000, Boris Popov * All rights reserved. * @@ -33,6 +32,10 @@ * $Id: rq.c,v 1.4 2004/12/13 00:25:23 lindak Exp $ */ +/* + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + */ + #include #include #include @@ -266,7 +269,7 @@ smb_rq_simple(struct smb_rq *rqp) /* * Call the driver */ - if (ioctl(rqp->rq_ctx->ct_dev_fd, SMBIOC_REQUEST, &krq) == -1) + if (nsmb_ioctl(rqp->rq_ctx->ct_dev_fd, SMBIOC_REQUEST, &krq) == -1) return (errno); /* @@ -312,7 +315,7 @@ smb_t2_request(int dev_fd, int setupcount, uint16_t *setup, krq->ioc_rparam = rparam; krq->ioc_rdata = rdata; - if (ioctl(dev_fd, SMBIOC_T2RQ, krq) == -1) { + if (nsmb_ioctl(dev_fd, SMBIOC_T2RQ, krq) == -1) { return (errno); } diff --git a/usr/src/lib/smbclnt/Makefile b/usr/src/lib/smbclnt/Makefile new file mode 100644 index 0000000000..4425611834 --- /dev/null +++ b/usr/src/lib/smbclnt/Makefile @@ -0,0 +1,24 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2017 Nexenta Systems, Inc. All rights reserved. +# + +include ../Makefile.lib + +SUBDIRS = \ + libfknsmb \ + libfksmbfs + +libfksmbfs: libfknsmb + +include ./Makefile.subdirs diff --git a/usr/src/lib/smbclnt/Makefile.lib b/usr/src/lib/smbclnt/Makefile.lib new file mode 100644 index 0000000000..67528308d3 --- /dev/null +++ b/usr/src/lib/smbclnt/Makefile.lib @@ -0,0 +1,51 @@ +# +# 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 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# Copyright 2017 Nexenta Systems, Inc. All rights reserved. +# + +# +# Common Makefile definitions for smbclnt +# + +# We reset the Makefile.lib macros ROOTLIBDIR to refer to usr/lib/smbfs. +# For 64 bit, we reset ROOTLIBDIR64 to refer to usr/lib/smbfs/$(MACH64). +# Install the userland library header files under /usr/include/netsmb +ROOTSMBHDRDIR= $(ROOTHDRDIR)/netsmb +ROOTSMBHDRS= $(HDRS:%=$(ROOTSMBHDRDIR)/%) + +ROOTLIBDIR = $(ROOT)/usr/lib/smbfs +ROOTLIBDIR64 = $(ROOT)/usr/lib/smbfs/$(MACH64) + +SRCDIR= ../common +LIBS= $(DYNLIB) $(LINTLIB) + +CSTD = $(CSTD_GNU99) + +CPPFLAGS += -I$(SRCDIR) -I. +LDLIBS32 += -L$(ROOT)/usr/lib/smbfs +LDLIBS64 += -L$(ROOT)/usr/lib/smbfs/$(MACH64) +$(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC) + +CLEANFILES += $(OBJECTS:%_ndr.o=%_ndr.c) diff --git a/usr/src/lib/smbclnt/Makefile.smbclnt b/usr/src/lib/smbclnt/Makefile.smbclnt new file mode 100644 index 0000000000..4df97c6daa --- /dev/null +++ b/usr/src/lib/smbclnt/Makefile.smbclnt @@ -0,0 +1,66 @@ +# +# 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 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# Copyright 2017 Nexenta Systems, Inc. All rights reserved. +# + +# +# Toplevel Makefile included by each subdirectory. Responsible for the 'check' +# and 'install_h' targets, as well as descending into the architecture directory +# to actually build the library. +# + +include ../../Makefile.lib +include ../Makefile.lib + +SUBDIRS= $(MACH) +$(BUILD64)SUBDIRS += $(MACH64) + +HDRDIR= common + +all := TARGET = all +clean := TARGET = clean +clobber := TARGET = clobber +install := TARGET = install +lint := TARGET = lint + +.KEEP_STATE: + +all clean clobber lint: $(SUBDIRS) + +install: install_h $(SUBDIRS) + +check: $(CHECKHDRS) + +install_h: $(ROOTSMBHDRS) + +$(SUBDIRS): FRC + @cd $@; pwd; VERSION='$(VERSION)' $(MAKE) $(TARGET) + +FRC: + +$(ROOTSMBHDRDIR)/%: common/% + $(INS.file) + +include ../../Makefile.targ diff --git a/usr/src/lib/smbclnt/Makefile.subdirs b/usr/src/lib/smbclnt/Makefile.subdirs new file mode 100644 index 0000000000..66720e53ee --- /dev/null +++ b/usr/src/lib/smbclnt/Makefile.subdirs @@ -0,0 +1,43 @@ +# +# 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 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# Copyright 2017 Nexenta Systems, Inc. All rights reserved. +# + +.KEEP_STATE: + +all := TARGET = all +check := TARGET = check +clean := TARGET = clean +clobber := TARGET = clobber +install := TARGET = install +install_h := TARGET = install_h +lint := TARGET = lint + +all check clean clobber install install_h lint: $(SUBDIRS) + +$(SUBDIRS): FRC + @cd $@; pwd; VERSION='$(VERSION)' $(MAKE) $(TARGET) + +FRC: diff --git a/usr/src/lib/smbclnt/Makefile.targ b/usr/src/lib/smbclnt/Makefile.targ new file mode 100644 index 0000000000..4c910e3565 --- /dev/null +++ b/usr/src/lib/smbclnt/Makefile.targ @@ -0,0 +1,50 @@ +# +# 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 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# Copyright 2017 Nexenta Systems, Inc. All rights reserved. +# + +# +# Common targets for smbclnt Makefiles +# + +pics/%.o: $(SRC)/common/smbclnt/%.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) + +.KEEP_STATE: + +all: $(LIBS) + +lint: # skip + +$(ROOTLIBS): $(ROOTLIBDIR) + +$(ROOTLIBDIR): + $(INS.dir) + +$(ROOTLIBS64): $(ROOTLIBDIR64) + +$(ROOTLIBDIR64): + $(INS.dir) diff --git a/usr/src/lib/smbclnt/libfknsmb/Makefile b/usr/src/lib/smbclnt/libfknsmb/Makefile new file mode 100644 index 0000000000..ee4ab9faf7 --- /dev/null +++ b/usr/src/lib/smbclnt/libfknsmb/Makefile @@ -0,0 +1,16 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2017 Nexenta Systems, Inc. All rights reserved. +# + +include ../Makefile.smbclnt diff --git a/usr/src/lib/smbclnt/libfknsmb/Makefile.com b/usr/src/lib/smbclnt/libfknsmb/Makefile.com new file mode 100644 index 0000000000..3c79d72974 --- /dev/null +++ b/usr/src/lib/smbclnt/libfknsmb/Makefile.com @@ -0,0 +1,106 @@ +# +# 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 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# Copyright 2017 Nexenta Systems, Inc. All rights reserved. +# + +LIBRARY = libfknsmb.a +VERS = .1 + +OBJS_LOCAL = \ + fksmb_sign_pkcs.o \ + fake_ddi.o \ + fake_fio.o \ + fake_kmem.o \ + fake_ktli.o \ + fake_pkey.o \ + fake_policy.o \ + fake_sdt.o \ + fake_softc.o \ + fake_stream.o \ + fake_strsubr.o + +# See also: $SRC/uts/common/Makefile.files +# NB: Intentionally ommitted, compared w/ the above: +# smb_dev.o smb_pass.o smb_sign_kcf.o +# +OBJS_NSMB = \ + smb_dev.o \ + smb_conn.o \ + smb_iod.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 + +OBJECTS = \ + $(OBJS_LOCAL) \ + $(OBJS_NSMB) + +include ../../../Makefile.lib +include ../../Makefile.lib + +# Force SOURCEDEBUG +CSOURCEDEBUGFLAGS = -g +CCSOURCEDEBUGFLAGS = -g +STRIP_STABS = : + +# Note: need our sys includes _before_ ENVCPPFLAGS, proto etc. +# Also, like Makefile.uts, reset CPPFLAGS +CPPFLAGS.first += -I../../../libfakekernel/common +CPPFLAGS.first += -I../common +CPPFLAGS= $(CPPFLAGS.first) + +INCS += -I$(SRC)/uts/common/fs/smbclnt +INCS += -I$(SRC)/uts/common + +CPPFLAGS += $(INCS) -D_REENTRANT -D_FAKE_KERNEL +CPPFLAGS += -D_FILE_OFFSET_BITS=64 +# Always want DEBUG here +CPPFLAGS += -DDEBUG + +CERRWARN += -_gcc=-Wno-switch + +LDLIBS += $(MACH_LDLIBS) +LDLIBS += -lfakekernel -lpkcs11 -lnsl -lc + +NSMB_DIR=$(SRC)/uts/common/fs/smbclnt/netsmb +SRCS= $(OBJS_LOCAL:%.o=$(SRCDIR)/%.c) \ + $(OBJS_NSMB:%.o=$(NSMB_DIR)/%.c) + +all: + +pics/%.o: $(NSMB_DIR)/%.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) + +.KEEP_STATE: + +include ../../Makefile.targ +include ../../../Makefile.targ diff --git a/usr/src/lib/smbclnt/libfknsmb/amd64/Makefile b/usr/src/lib/smbclnt/libfknsmb/amd64/Makefile new file mode 100644 index 0000000000..441f9285b5 --- /dev/null +++ b/usr/src/lib/smbclnt/libfknsmb/amd64/Makefile @@ -0,0 +1,21 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2017 Nexenta Systems, Inc. All rights reserved. +# + +MACH_LDLIBS += -L$(ROOT)/usr/lib/smbfs/$(MACH64) + +include ../Makefile.com +include ../../../Makefile.lib.64 + +install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64) diff --git a/usr/src/lib/smbclnt/libfknsmb/common/fake_ddi.c b/usr/src/lib/smbclnt/libfknsmb/common/fake_ddi.c new file mode 100644 index 0000000000..4dc0faf984 --- /dev/null +++ b/usr/src/lib/smbclnt/libfknsmb/common/fake_ddi.c @@ -0,0 +1,133 @@ +/* + * 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 (c) 1984, 1986, 1987, 1988, 1989 AT&T */ +/* All Rights Reserved */ + + +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + */ + +/* + * UNIX Device Driver Interface functions + * (excerpts) + */ + +#include +#include +#include +#include +#include +#include + +#ifndef NODEV32 +#define NODEV32 (dev32_t)(-1) +#endif /* NODEV32 */ + +/* + * return internal major number corresponding to device + * number (new format) argument + */ +major_t +getmajor(dev_t dev) +{ +#ifdef _LP64 + return ((major_t)((dev >> NBITSMINOR64) & MAXMAJ64)); +#else + return ((major_t)((dev >> NBITSMINOR) & MAXMAJ)); +#endif +} + +/* + * return internal minor number corresponding to device + * number (new format) argument + */ +minor_t +getminor(dev_t dev) +{ +#ifdef _LP64 + return ((minor_t)(dev & MAXMIN64)); +#else + return ((minor_t)(dev & MAXMIN)); +#endif +} + +/* + * encode external major and minor number arguments into a + * new format device number + */ +dev_t +makedevice(major_t maj, minor_t minor) +{ +#ifdef _LP64 + return (((dev_t)maj << NBITSMINOR64) | (minor & MAXMIN64)); +#else + return (((dev_t)maj << NBITSMINOR) | (minor & MAXMIN)); +#endif +} + +/* + * Compress 'long' device number encoding to 32-bit device number + * encoding. If it won't fit, we return failure, but set the + * device number to 32-bit NODEV for the sake of our callers. + */ +int +cmpldev(dev32_t *dst, dev_t dev) +{ +#if defined(_LP64) + if (dev == NODEV) { + *dst = NODEV32; + } else { + major_t major = dev >> L_BITSMINOR; + minor_t minor = dev & L_MAXMIN; + + if (major > L_MAXMAJ32 || minor > L_MAXMIN32) { + *dst = NODEV32; + return (0); + } + + *dst = (dev32_t)((major << L_BITSMINOR32) | minor); + } +#else + *dst = (dev32_t)dev; +#endif + return (1); +} + +/* + * Expand 32-bit dev_t's to long dev_t's. Expansion always "fits" + * into the return type, but we're careful to expand NODEV explicitly. + */ +dev_t +expldev(dev32_t dev32) +{ +#ifdef _LP64 + if (dev32 == NODEV32) + return (NODEV); + return (makedevice((dev32 >> L_BITSMINOR32) & L_MAXMAJ32, + dev32 & L_MAXMIN32)); +#else + return ((dev_t)dev32); +#endif +} diff --git a/usr/src/lib/smbclnt/libfknsmb/common/fake_fio.c b/usr/src/lib/smbclnt/libfknsmb/common/fake_fio.c new file mode 100644 index 0000000000..18f8fa2255 --- /dev/null +++ b/usr/src/lib/smbclnt/libfknsmb/common/fake_fio.c @@ -0,0 +1,105 @@ +/* + * 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 (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2015, Joyent Inc. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + */ + +/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ +/* All Rights Reserved */ + +/* + * The kTLI "shim" over in ./fake_ktli.c uses getf(), releasef() to + * represent an open socket FD in "fake" vnode_t and file_t objects. + * This implements minimal getf()/releasef() shims for that purpose. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define FAKEFDS 256 + +kmutex_t ftlock; +file_t *ftab[FAKEFDS]; + +file_t * +getf(int fd) +{ + file_t *fp; + vnode_t *vp; + + if (fd >= FAKEFDS) + return (NULL); + + mutex_enter(&ftlock); + if ((fp = ftab[fd]) != NULL) { + fp->f_count++; + mutex_exit(&ftlock); + return (fp); + } + + fp = kmem_zalloc(sizeof (*fp), KM_SLEEP); + vp = kmem_zalloc(sizeof (*vp), KM_SLEEP); + vp->v_fd = fd; + fp->f_vnode = vp; + fp->f_count = 1; + ftab[fd] = fp; + + mutex_exit(&ftlock); + + return (fp); +} + +void +releasef(int fd) +{ + file_t *fp; + vnode_t *vp; + + mutex_enter(&ftlock); + if ((fp = ftab[fd]) == NULL) { + mutex_exit(&ftlock); + return; + } + fp->f_count--; + if (fp->f_count > 0) { + mutex_exit(&ftlock); + return; + } + ftab[fd] = NULL; + mutex_exit(&ftlock); + + vp = fp->f_vnode; + kmem_free(vp, sizeof (*vp)); + kmem_free(fp, sizeof (*fp)); +} diff --git a/usr/src/lib/smbclnt/libfknsmb/common/fake_kmem.c b/usr/src/lib/smbclnt/libfknsmb/common/fake_kmem.c new file mode 100644 index 0000000000..21453f410d --- /dev/null +++ b/usr/src/lib/smbclnt/libfknsmb/common/fake_kmem.c @@ -0,0 +1,45 @@ +/* + * 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 (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017 by Delphix. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include + +static size_t availmem = (1<<24); + +size_t +kmem_avail(void) +{ + return (availmem); +} + +size_t +kmem_maxavail(void) +{ + return (availmem); +} diff --git a/usr/src/lib/smbclnt/libfknsmb/common/fake_ktli.c b/usr/src/lib/smbclnt/libfknsmb/common/fake_ktli.c new file mode 100644 index 0000000000..3011de2e77 --- /dev/null +++ b/usr/src/lib/smbclnt/libfknsmb/common/fake_ktli.c @@ -0,0 +1,432 @@ +/* + * 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 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ +/* All Rights Reserved */ + +/* + * University Copyright- Copyright (c) 1982, 1986, 1988 + * The Regents of the University of California + * All Rights Reserved + * + * University Acknowledgment- Portions of this document are derived from + * software developed by the University of California, Berkeley, and its + * contributors. + */ +/* + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + */ + +/* + * Kernel TLI-like functions + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "fake_xti.h" + +/* Size of mblks for tli_recv */ +#define FKTLI_RCV_SZ 4096 + +/* + * Translate a TLI error into a system error as best we can. + */ +static const int tli_errs[] = { + 0, /* no error */ + EADDRNOTAVAIL, /* TBADADDR */ + ENOPROTOOPT, /* TBADOPT */ + EACCES, /* TACCES */ + EBADF, /* TBADF */ + EADDRNOTAVAIL, /* TNOADDR */ + EPROTO, /* TOUTSTATE */ + EPROTO, /* TBADSEQ */ + ENOSYS, /* TSYSERR */ + EPROTO, /* TLOOK */ + EMSGSIZE, /* TBADDATA */ + EMSGSIZE, /* TBUFOVFLW */ + EPROTO, /* TFLOW */ + EWOULDBLOCK, /* TNODATA */ + EPROTO, /* TNODIS */ + EPROTO, /* TNOUDERR */ + EINVAL, /* TBADFLAG */ + EPROTO, /* TNOREL */ + EOPNOTSUPP, /* TNOTSUPPORT */ + EPROTO, /* TSTATECHNG */ +}; + +static int +tlitosyserr(int terr) +{ + if (terr < 0 || (terr >= (sizeof (tli_errs) / sizeof (tli_errs[0])))) + return (EPROTO); + else + return (tli_errs[terr]); +} + +/* + * Note: This implementation is specific to the needs of the callers in + * uts/common/fs/smbclnt/netsmb/smb_trantcp.c + */ +/* ARGSUSED */ +int +t_kopen(file_t *fp, dev_t rdev, int flags, TIUSER **tiptr, cred_t *cr) +{ + boolean_t madefp = B_FALSE; + vnode_t *vp; + TIUSER *tiu; + int fd; + int rc; + + *tiptr = NULL; + + if (fp == NULL) { + /* + * create a socket endpoint + * dev is actualy AF + */ + char *devnm; + switch (rdev) { + case AF_INET: + devnm = "/dev/tcp"; + break; + case AF_INET6: + devnm = "/dev/tcp6"; + break; + default: + cmn_err(CE_NOTE, "t_kopen: bad device"); + return (EINVAL); + } + + fd = t_open(devnm, O_RDWR, NULL); + if (fd < 0) { + rc = t_errno; + cmn_err(CE_NOTE, "t_kopen: t_open terr=%d", rc); + return (tlitosyserr(rc)); + } + + /* + * allocate a file pointer... + */ + fp = getf(fd); + madefp = B_TRUE; + } + vp = fp->f_vnode; + fd = vp->v_fd; + + tiu = kmem_zalloc(sizeof (*tiu), KM_SLEEP); + rc = t_getinfo(fd, &tiu->tp_info); + if (rc < 0) { + rc = t_errno; + cmn_err(CE_NOTE, "t_kopen: t_getinfo terr=%d", rc); + kmem_free(tiu, sizeof (*tiu)); + if (madefp) { + releasef(fd); + (void) t_close(fd); + } + return (tlitosyserr(rc)); + } + + tiu->fp = fp; + tiu->flags = madefp ? MADE_FP : 0; + *tiptr = tiu; + + return (0); +} + +/* ARGSUSED */ +int +t_kclose(TIUSER *tiptr, int callclosef) +{ + file_t *fp; + + fp = (tiptr->flags & MADE_FP) ? tiptr->fp : NULL; + + kmem_free(tiptr, TIUSERSZ); + + if (fp != NULL) { + vnode_t *vp = fp->f_vnode; + int fd = vp->v_fd; + releasef(fd); + (void) t_close(fd); + } + + return (0); +} + +int +t_kbind(TIUSER *tiptr, struct t_bind *req, struct t_bind *ret) +{ + file_t *fp = tiptr->fp; + vnode_t *vp = fp->f_vnode; + int rc; + + if (t_bind(vp->v_fd, req, ret) < 0) { + rc = t_errno; + cmn_err(CE_NOTE, "t_kbind: t_bind terr=%d", rc); + return (tlitosyserr(rc)); + } + return (0); +} + +int +t_kunbind(TIUSER *tiptr) +{ + file_t *fp = tiptr->fp; + vnode_t *vp = fp->f_vnode; + int rc; + + if (t_unbind(vp->v_fd) < 0) { + rc = t_errno; + cmn_err(CE_NOTE, "t_kunbind: t_unbind terr=%d", rc); + return (tlitosyserr(rc)); + } + return (0); +} + +int +t_kconnect(TIUSER *tiptr, struct t_call *sndcall, struct t_call *rcvcall) +{ + file_t *fp = tiptr->fp; + vnode_t *vp = fp->f_vnode; + int rc; + + if (t_connect(vp->v_fd, sndcall, rcvcall) < 0) { + rc = t_errno; + cmn_err(CE_NOTE, "t_kconnect: t_connect terr=%d", rc); + if (rc == TLOOK) { + /* Probably got a RST. */ + rc = ECONNREFUSED; + } else { + rc = tlitosyserr(rc); + } + return (rc); + } + return (0); +} + +int +t_koptmgmt(TIUSER *tiptr, struct t_optmgmt *req, struct t_optmgmt *ret) +{ + file_t *fp = tiptr->fp; + vnode_t *vp = fp->f_vnode; + int rc; + + if (t_optmgmt(vp->v_fd, req, ret) < 0) { + rc = t_errno; + cmn_err(CE_NOTE, "t_koptmgmt: t_optmgmt terr=%d", rc); + return (tlitosyserr(rc)); + } + return (0); +} + +/* + * Poll for an input event. + * + * timo is measured in ticks + */ +int +t_kspoll(TIUSER *tiptr, int timo, int waitflg, int *events) +{ + struct pollfd pfds[1]; + file_t *fp; + vnode_t *vp; + clock_t timout; /* milliseconds */ + int n; + + fp = tiptr->fp; + vp = fp->f_vnode; + + if (events == NULL || ((waitflg & READWAIT) == 0)) + return (EINVAL); + + /* Convert from ticks to milliseconds */ + if (timo < 0) + timout = -1; + else + timout = TICK_TO_MSEC(timo); + + pfds[0].fd = vp->v_fd; + pfds[0].events = POLLIN; + pfds[0].revents = 0; + + errno = 0; + n = poll(pfds, 1, timout); + if (n < 0) + return (errno); + if (n == 0) + return (ETIME); + *events = pfds[0].revents; + return (0); +} + +/* + * Send the message, return zero or errno. + * Always free's the message, even on error. + */ +int +tli_send(TIUSER *tiptr, mblk_t *bp, int fmode) +{ + struct strbuf ctlbuf; + struct strbuf databuf; + mblk_t *m; + int flg, n, rc; + vnode_t *vp; + + if (bp == NULL) + return (0); + vp = tiptr->fp->f_vnode; + + switch (bp->b_datap->db_type) { + case M_DATA: + for (m = bp; m != NULL; m = m->b_cont) { + n = MBLKL(m); + flg = (m->b_cont != NULL) ? T_MORE : 0; + rc = t_snd(vp->v_fd, (void *) m->b_rptr, n, flg); + if (rc != n) { + rc = EIO; + goto out; + } + } + rc = 0; + break; + + /* + * May get M_PROTO/T_DISCON_REQ from nb_snddis() + */ + case M_PROTO: + case M_PCPROTO: + ctlbuf.len = MBLKL(bp); + ctlbuf.maxlen = MBLKL(bp); + ctlbuf.buf = (char *)bp->b_rptr; + if (bp->b_cont == NULL) { + bzero(&databuf, sizeof (databuf)); + } else { + m = bp->b_cont; + databuf.len = MBLKL(m); + databuf.maxlen = MBLKL(m); + databuf.buf = (char *)m->b_rptr; + } + if (putmsg(vp->v_fd, &ctlbuf, &databuf, 0) < 0) { + rc = errno; + cmn_err(CE_NOTE, "tli_send: putmsg err=%d", rc); + } else { + rc = 0; + } + break; + + default: + rc = EIO; + break; + } + +out: + freemsg(bp); + return (rc); +} + +int +tli_recv(TIUSER *tiptr, mblk_t **bp, int fmode) +{ + mblk_t *mtop = NULL; + mblk_t *m; + vnode_t *vp; + int error; + int flags; + int nread; + int n; + + vp = tiptr->fp->f_vnode; + + + + /* + * Get an mblk for the data + */ + nread = FKTLI_RCV_SZ; + m = allocb_wait(nread, 0, 0, &error); + ASSERT(m != NULL); + + if (mtop == NULL) + mtop = m; + +again: + flags = 0; + n = t_rcv(vp->v_fd, (void *) m->b_rptr, nread, &flags); + if (n < 0) { + n = t_errno; + cmn_err(CE_NOTE, "tli_recv: t_rcv terr=%d", n); + error = tlitosyserr(n); + goto errout; + } + if (n == 0) { + error = ENOTCONN; + goto errout; + } + ASSERT(n > 0 && n <= nread); + m->b_wptr = m->b_rptr + n; + + if (flags & T_MORE) { + mblk_t *mtail = m; + m = allocb_wait(nread, 0, 0, &error); + ASSERT(m != NULL); + mtail->b_cont = m; + goto again; + } + + *bp = mtop; + return (0); + +errout: + if (m == mtop) { + freemsg(mtop); + return (error); + } + + /* got some data, so return it. */ + return (0); +} diff --git a/usr/src/lib/smbclnt/libfknsmb/common/fake_pkey.c b/usr/src/lib/smbclnt/libfknsmb/common/fake_pkey.c new file mode 100644 index 0000000000..b7944f8dca --- /dev/null +++ b/usr/src/lib/smbclnt/libfknsmb/common/fake_pkey.c @@ -0,0 +1,48 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + */ + +/* + * pkey stubs + */ + +#include +#include +#include + +#include +#include + +void +smb_pkey_init() +{ +} + +void +smb_pkey_fini() +{ +} + +int +smb_pkey_idle() +{ + return (0); +} + +/* ARGSUSED */ +int +smb_pkey_ioctl(int cmd, intptr_t arg, int flags, cred_t *cr) +{ + return (ENOTTY); +} diff --git a/usr/src/lib/smbclnt/libfknsmb/common/fake_policy.c b/usr/src/lib/smbclnt/libfknsmb/common/fake_policy.c new file mode 100644 index 0000000000..4531e86bae --- /dev/null +++ b/usr/src/lib/smbclnt/libfknsmb/common/fake_policy.c @@ -0,0 +1,90 @@ +/* + * 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 (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2016 Joyent, Inc. + * Copyright (c) 2016 by Delphix. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + */ + +#include +#include +#include +#include + +/* ARGSUSED */ +int +secpolicy_fs_allowed_mount(const char *fsname) +{ + return (0); +} + +int +secpolicy_vnode_access2(const cred_t *cr, vnode_t *vp, uid_t owner, + mode_t curmode, mode_t wantmode) +{ + mode_t mode; + + mode = ~curmode & wantmode; + + if (mode == 0) + return (0); + return (EACCES); +} + +int +secpolicy_vnode_owner(const cred_t *cr, uid_t owner) +{ + /* cr->cr_uid */ + if (owner == crgetruid(cr)) + return (0); + + return (EPERM); +} + +int +secpolicy_vnode_setattr(cred_t *cr, struct vnode *vp, struct vattr *vap, + const struct vattr *ovap, int flags, + int unlocked_access(void *, int, cred_t *), + void *node) +{ + int mask = vap->va_mask; + + if (mask & AT_SIZE) { + if (vp->v_type == VDIR) + return (EISDIR); + } + if (mask & AT_MODE) + return (EACCES); + if (mask & (AT_UID|AT_GID)) + return (EACCES); + + return (0); +} + +int +secpolicy_vnode_setdac(const cred_t *cred, uid_t owner) +{ + if (owner == crgetuid(cred)) + return (0); + + return (EPERM); +} diff --git a/usr/src/lib/smbclnt/libfknsmb/common/fake_sdt.c b/usr/src/lib/smbclnt/libfknsmb/common/fake_sdt.c new file mode 100644 index 0000000000..bc88864843 --- /dev/null +++ b/usr/src/lib/smbclnt/libfknsmb/common/fake_sdt.c @@ -0,0 +1,50 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + */ + +#include +#include + +/* + * See: DTRACE_PROBE... in sys/sdt.h + */ + +int fknsmb_dtrace_log = 0; + +void +smb_dtrace1(const char *n, long v1) +{ + if (fknsmb_dtrace_log) { + cmn_err(CE_CONT, "dtrace1: %s," + " 0x%lx\n", n, v1); + } +} + +void +smb_dtrace2(const char *n, long v1, long v2) +{ + if (fknsmb_dtrace_log) { + cmn_err(CE_CONT, "dtrace2: %s," + " 0x%lx, 0x%lx\n", n, v1, v2); + } +} + +void +smb_dtrace3(const char *n, long v1, long v2, long v3) +{ + if (fknsmb_dtrace_log) { + cmn_err(CE_CONT, "dtrace3: %s," + " 0x%lx, 0x%lx, 0x%lx\n", n, v1, v2, v3); + } +} diff --git a/usr/src/lib/smbclnt/libfknsmb/common/fake_softc.c b/usr/src/lib/smbclnt/libfknsmb/common/fake_softc.c new file mode 100644 index 0000000000..2d990ed3f8 --- /dev/null +++ b/usr/src/lib/smbclnt/libfknsmb/common/fake_softc.c @@ -0,0 +1,263 @@ + +/* + * 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 (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2014 Garrett D'Amore + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + */ + +#include +#include +#include + +#define MIN_N_ITEMS 8 + +typedef struct i_ddi_soft_state { + void **array; /* the array of pointers */ + kmutex_t lock; /* serialize access to this struct */ + size_t size; /* how many bytes per state struct */ + size_t n_items; /* how many structs herein */ + void *next; /* unused */ +} i_ddi_soft_state; + + +void * +ddi_get_soft_state(void *state, int item) +{ + i_ddi_soft_state *ss = (i_ddi_soft_state *)state; + void *ret = NULL; + + ASSERT((ss != NULL) && (item >= 0)); + + mutex_enter(&ss->lock); + + if (item < ss->n_items && ss->array != NULL) + ret = ss->array[item]; + + mutex_exit(&ss->lock); + + return (ret); +} + + +int +ddi_soft_state_init(void **state_p, size_t size, size_t n_items) +{ + i_ddi_soft_state *ss; + + if (state_p == NULL || size == 0) + return (EINVAL); + + ss = kmem_zalloc(sizeof (*ss), KM_SLEEP); + mutex_init(&ss->lock, NULL, MUTEX_DRIVER, NULL); + ss->size = size; + + if (n_items < MIN_N_ITEMS) + ss->n_items = MIN_N_ITEMS; + else { + ss->n_items = n_items; + } + + ASSERT(ss->n_items >= n_items); + + ss->array = kmem_zalloc(ss->n_items * sizeof (void *), KM_SLEEP); + + *state_p = ss; + return (0); +} + +/* + * Allocate a state structure of size 'size' to be associated + * with item 'item'. + * + * In this implementation, the array is extended to + * allow the requested offset, if needed. + */ +int +ddi_soft_state_zalloc(void *state, int item) +{ + i_ddi_soft_state *ss = (i_ddi_soft_state *)state; + void **array; + void *new_element; + + if ((state == NULL) || (item < 0)) + return (DDI_FAILURE); + + mutex_enter(&ss->lock); + if (ss->size == 0) { + mutex_exit(&ss->lock); + cmn_err(CE_WARN, "ddi_soft_state_zalloc: bad handle: %s", + "fake"); + return (DDI_FAILURE); + } + + array = ss->array; /* NULL if ss->n_items == 0 */ + ASSERT(ss->n_items != 0 && array != NULL); + + /* + * refuse to tread on an existing element + */ + if (item < ss->n_items && array[item] != NULL) { + mutex_exit(&ss->lock); + return (DDI_FAILURE); + } + + /* + * Allocate a new element to plug in + */ + new_element = kmem_zalloc(ss->size, KM_SLEEP); + + /* + * Check if the array is big enough, if not, grow it. + */ + if (item >= ss->n_items) { + void **new_array; + size_t new_n_items; + + /* + * Allocate a new array of the right length, copy + * all the old pointers to the new array, then + * if it exists at all, put the old array on the + * dirty list. + * + * Note that we can't kmem_free() the old array. + * + * Why -- well the 'get' operation is 'mutex-free', so we + * can't easily catch a suspended thread that is just about + * to dereference the array we just grew out of. So we + * cons up a header and put it on a list of 'dirty' + * pointer arrays. (Dirty in the sense that there may + * be suspended threads somewhere that are in the middle + * of referencing them). Fortunately, we -can- garbage + * collect it all at ddi_soft_state_fini time. + */ + new_n_items = ss->n_items; + while (new_n_items < (1 + item)) + new_n_items <<= 1; /* double array size .. */ + + ASSERT(new_n_items >= (1 + item)); /* sanity check! */ + + new_array = kmem_zalloc(new_n_items * sizeof (void *), + KM_SLEEP); + /* + * Copy the pointers into the new array + */ + bcopy(array, new_array, ss->n_items * sizeof (void *)); + + /* + * Free the old array now. Note that + * ddi_get_soft_state takes the mutex. + */ + kmem_free(ss->array, ss->n_items * sizeof (void *)); + + ss->array = (array = new_array); + ss->n_items = new_n_items; + } + + ASSERT(array != NULL && item < ss->n_items && array[item] == NULL); + + array[item] = new_element; + + mutex_exit(&ss->lock); + return (DDI_SUCCESS); +} + +void +ddi_soft_state_free(void *state, int item) +{ + i_ddi_soft_state *ss = (i_ddi_soft_state *)state; + void **array; + void *element; + static char msg[] = "ddi_soft_state_free:"; + + if (ss == NULL) { + cmn_err(CE_WARN, "%s null handle: %s", + msg, "fake"); + return; + } + + element = NULL; + + mutex_enter(&ss->lock); + + if ((array = ss->array) == NULL || ss->size == 0) { + cmn_err(CE_WARN, "%s bad handle: %s", + msg, "fake"); + } else if (item < 0 || item >= ss->n_items) { + cmn_err(CE_WARN, "%s item %d not in range [0..%lu]: %s", + msg, item, (ulong_t)ss->n_items - 1, "fake"); + } else if (array[item] != NULL) { + element = array[item]; + array[item] = NULL; + } + + mutex_exit(&ss->lock); + + if (element) + kmem_free(element, ss->size); +} + +/* + * Free the entire set of pointers, and any + * soft state structures contained therein. + * + * Note that we don't grab the ss->lock mutex, even though + * we're inspecting the various fields of the data structure. + * + * There is an implicit assumption that this routine will + * never run concurrently with any of the above on this + * particular state structure i.e. by the time the driver + * calls this routine, there should be no other threads + * running in the driver. + */ +void +ddi_soft_state_fini(void **state_p) +{ + i_ddi_soft_state *ss; + int item; + static char msg[] = "ddi_soft_state_fini:"; + + if (state_p == NULL || + (ss = (i_ddi_soft_state *)(*state_p)) == NULL) { + cmn_err(CE_WARN, "%s null handle: %s", + msg, "fake"); + return; + } + + if (ss->size == 0) { + cmn_err(CE_WARN, "%s bad handle: %s", + msg, "fake"); + return; + } + + if (ss->n_items > 0) { + for (item = 0; item < ss->n_items; item++) + ddi_soft_state_free(ss, item); + kmem_free(ss->array, ss->n_items * sizeof (void *)); + } + + mutex_destroy(&ss->lock); + kmem_free(ss, sizeof (*ss)); + + *state_p = NULL; +} diff --git a/usr/src/lib/smbclnt/libfknsmb/common/fake_stream.c b/usr/src/lib/smbclnt/libfknsmb/common/fake_stream.c new file mode 100644 index 0000000000..d89a732d69 --- /dev/null +++ b/usr/src/lib/smbclnt/libfknsmb/common/fake_stream.c @@ -0,0 +1,1377 @@ +/* + * 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 (c) 1984, 1986, 1987, 1988, 1989 AT&T */ +/* All Rights Reserved */ + +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * This file contains selected functions from io/stream.c + * needed by this library, mostly unmodified. + */ + +/* + * STREAMS message allocator: principles of operation + * (See usr/src/uts/common/io/stream.c) + */ +#define DBLK_MAX_CACHE 73728 +#define DBLK_CACHE_ALIGN 64 +#define DBLK_MIN_SIZE 8 +#define DBLK_SIZE_SHIFT 3 + +#ifdef _BIG_ENDIAN +#define DBLK_RTFU_SHIFT(field) \ + (8 * (&((dblk_t *)0)->db_struioflag - &((dblk_t *)0)->field)) +#else +#define DBLK_RTFU_SHIFT(field) \ + (8 * (&((dblk_t *)0)->field - &((dblk_t *)0)->db_ref)) +#endif + +#define DBLK_RTFU(ref, type, flags, uioflag) \ + (((ref) << DBLK_RTFU_SHIFT(db_ref)) | \ + ((type) << DBLK_RTFU_SHIFT(db_type)) | \ + (((flags) | (ref - 1)) << DBLK_RTFU_SHIFT(db_flags)) | \ + ((uioflag) << DBLK_RTFU_SHIFT(db_struioflag))) +#define DBLK_RTFU_REF_MASK (DBLK_REFMAX << DBLK_RTFU_SHIFT(db_ref)) +#define DBLK_RTFU_WORD(dbp) (*((uint32_t *)&(dbp)->db_ref)) +#define MBLK_BAND_FLAG_WORD(mp) (*((uint32_t *)&(mp)->b_band)) + +static size_t dblk_sizes[] = { +#ifdef _LP64 + 16, 80, 144, 208, 272, 336, 528, 1040, 1488, 1936, 2576, 3856, + 8192, 12048, 16384, 20240, 24576, 28432, 32768, 36624, + 40960, 44816, 49152, 53008, 57344, 61200, 65536, 69392, +#else + 64, 128, 320, 576, 1088, 1536, 1984, 2624, 3904, + 8192, 12096, 16384, 20288, 24576, 28480, 32768, 36672, + 40960, 44864, 49152, 53056, 57344, 61248, 65536, 69440, +#endif + DBLK_MAX_CACHE, 0 +}; + +static struct kmem_cache *dblk_cache[DBLK_MAX_CACHE / DBLK_MIN_SIZE]; +static struct kmem_cache *mblk_cache; +static struct kmem_cache *dblk_esb_cache; + +static void dblk_lastfree(mblk_t *mp, dblk_t *dbp); +static mblk_t *allocb_oversize(size_t size, int flags); +static int allocb_tryhard_fails; +static void frnop_func(void *arg); +frtn_t frnop = { frnop_func }; +static void bcache_dblk_lastfree(mblk_t *mp, dblk_t *dbp); + +/* + * Patchable mblk/dblk kmem_cache flags. + */ +int dblk_kmem_flags = 0; +int mblk_kmem_flags = 0; + +static int +dblk_constructor(void *buf, void *cdrarg, int kmflags) +{ + dblk_t *dbp = buf; + ssize_t msg_size = (ssize_t)cdrarg; + size_t index; + + ASSERT(msg_size != 0); + + index = (msg_size - 1) >> DBLK_SIZE_SHIFT; + + ASSERT(index < (DBLK_MAX_CACHE >> DBLK_SIZE_SHIFT)); + + if ((dbp->db_mblk = kmem_cache_alloc(mblk_cache, kmflags)) == NULL) + return (-1); + if ((msg_size & PAGEOFFSET) == 0) { + dbp->db_base = kmem_alloc(msg_size, kmflags); + if (dbp->db_base == NULL) { + kmem_cache_free(mblk_cache, dbp->db_mblk); + return (-1); + } + } else { + dbp->db_base = (unsigned char *)&dbp[1]; + } + + dbp->db_mblk->b_datap = dbp; + dbp->db_cache = dblk_cache[index]; + dbp->db_lim = dbp->db_base + msg_size; + dbp->db_free = dbp->db_lastfree = dblk_lastfree; + dbp->db_frtnp = NULL; + dbp->db_fthdr = NULL; + dbp->db_credp = NULL; + dbp->db_cpid = -1; + dbp->db_struioflag = 0; + dbp->db_struioun.cksum.flags = 0; + return (0); +} + +/*ARGSUSED*/ +static int +dblk_esb_constructor(void *buf, void *cdrarg, int kmflags) +{ + dblk_t *dbp = buf; + + if ((dbp->db_mblk = kmem_cache_alloc(mblk_cache, kmflags)) == NULL) + return (-1); + dbp->db_mblk->b_datap = dbp; + dbp->db_cache = dblk_esb_cache; + dbp->db_fthdr = NULL; + dbp->db_credp = NULL; + dbp->db_cpid = -1; + dbp->db_struioflag = 0; + dbp->db_struioun.cksum.flags = 0; + return (0); +} + +static int +bcache_dblk_constructor(void *buf, void *cdrarg, int kmflags) +{ + dblk_t *dbp = buf; + bcache_t *bcp = cdrarg; + + if ((dbp->db_mblk = kmem_cache_alloc(mblk_cache, kmflags)) == NULL) + return (-1); + + dbp->db_base = kmem_cache_alloc(bcp->buffer_cache, kmflags); + if (dbp->db_base == NULL) { + kmem_cache_free(mblk_cache, dbp->db_mblk); + return (-1); + } + + dbp->db_mblk->b_datap = dbp; + dbp->db_cache = (void *)bcp; + dbp->db_lim = dbp->db_base + bcp->size; + dbp->db_free = dbp->db_lastfree = bcache_dblk_lastfree; + dbp->db_frtnp = NULL; + dbp->db_fthdr = NULL; + dbp->db_credp = NULL; + dbp->db_cpid = -1; + dbp->db_struioflag = 0; + dbp->db_struioun.cksum.flags = 0; + return (0); +} + +/*ARGSUSED*/ +static void +dblk_destructor(void *buf, void *cdrarg) +{ + dblk_t *dbp = buf; + ssize_t msg_size = (ssize_t)cdrarg; + + ASSERT(dbp->db_mblk->b_datap == dbp); + ASSERT(msg_size != 0); + ASSERT(dbp->db_struioflag == 0); + ASSERT(dbp->db_struioun.cksum.flags == 0); + + if ((msg_size & PAGEOFFSET) == 0) { + kmem_free(dbp->db_base, msg_size); + } + + kmem_cache_free(mblk_cache, dbp->db_mblk); +} + +static void +bcache_dblk_destructor(void *buf, void *cdrarg) +{ + dblk_t *dbp = buf; + bcache_t *bcp = cdrarg; + + kmem_cache_free(bcp->buffer_cache, dbp->db_base); + + ASSERT(dbp->db_mblk->b_datap == dbp); + ASSERT(dbp->db_struioflag == 0); + ASSERT(dbp->db_struioun.cksum.flags == 0); + + kmem_cache_free(mblk_cache, dbp->db_mblk); +} + +/* Needed in the ASSERT below */ +#ifdef DEBUG +#ifdef _KERNEL +#define KMEM_SLAB_T_SZ sizeof (kmem_slab_t) +#else /* _KERNEL */ +#define KMEM_SLAB_T_SZ 64 /* fakekernel */ +#endif /* _KERNEL */ +#endif /* DEBUG */ + +void +streams_msg_init(void) +{ + char name[40]; + size_t size; + size_t lastsize = DBLK_MIN_SIZE; + size_t *sizep; + struct kmem_cache *cp; + size_t tot_size; + int offset; + + mblk_cache = kmem_cache_create("streams_mblk", sizeof (mblk_t), 32, + NULL, NULL, NULL, NULL, NULL, mblk_kmem_flags); + + for (sizep = dblk_sizes; (size = *sizep) != 0; sizep++) { + + if ((offset = (size & PAGEOFFSET)) != 0) { + /* + * We are in the middle of a page, dblk should + * be allocated on the same page + */ + tot_size = size + sizeof (dblk_t); + ASSERT((offset + sizeof (dblk_t) + KMEM_SLAB_T_SZ) + < PAGESIZE); + ASSERT((tot_size & (DBLK_CACHE_ALIGN - 1)) == 0); + + } else { + + /* + * buf size is multiple of page size, dblk and + * buffer are allocated separately. + */ + + ASSERT((size & (DBLK_CACHE_ALIGN - 1)) == 0); + tot_size = sizeof (dblk_t); + } + + (void) sprintf(name, "streams_dblk_%ld", (long)size); + cp = kmem_cache_create(name, tot_size, DBLK_CACHE_ALIGN, + dblk_constructor, dblk_destructor, NULL, (void *)(size), + NULL, dblk_kmem_flags); + + while (lastsize <= size) { + dblk_cache[(lastsize - 1) >> DBLK_SIZE_SHIFT] = cp; + lastsize += DBLK_MIN_SIZE; + } + } + + dblk_esb_cache = kmem_cache_create("streams_dblk_esb", sizeof (dblk_t), + DBLK_CACHE_ALIGN, dblk_esb_constructor, dblk_destructor, NULL, + (void *)sizeof (dblk_t), NULL, dblk_kmem_flags); + + /* fthdr_cache, ftblk_cache, mmd_init... */ +} + +/*ARGSUSED*/ +mblk_t * +allocb(size_t size, uint_t pri) +{ + dblk_t *dbp; + mblk_t *mp; + size_t index; + + index = (size - 1) >> DBLK_SIZE_SHIFT; + + if (index >= (DBLK_MAX_CACHE >> DBLK_SIZE_SHIFT)) { + if (size != 0) { + mp = allocb_oversize(size, KM_NOSLEEP); + goto out; + } + index = 0; + } + + if ((dbp = kmem_cache_alloc(dblk_cache[index], KM_NOSLEEP)) == NULL) { + mp = NULL; + goto out; + } + + mp = dbp->db_mblk; + DBLK_RTFU_WORD(dbp) = DBLK_RTFU(1, M_DATA, 0, 0); + mp->b_next = mp->b_prev = mp->b_cont = NULL; + mp->b_rptr = mp->b_wptr = dbp->db_base; + mp->b_queue = NULL; + MBLK_BAND_FLAG_WORD(mp) = 0; + STR_FTALLOC(&dbp->db_fthdr, FTEV_ALLOCB, size); +out: + FTRACE_1("allocb(): mp=0x%p", (uintptr_t)mp); + + return (mp); +} + +/* + * Allocate an mblk taking db_credp and db_cpid from the template. + * Allow the cred to be NULL. + */ +mblk_t * +allocb_tmpl(size_t size, const mblk_t *tmpl) +{ + mblk_t *mp = allocb(size, 0); + + if (mp != NULL) { + dblk_t *src = tmpl->b_datap; + dblk_t *dst = mp->b_datap; + cred_t *cr; + pid_t cpid; + + cr = msg_getcred(tmpl, &cpid); + if (cr != NULL) + crhold(dst->db_credp = cr); + dst->db_cpid = cpid; + dst->db_type = src->db_type; + } + return (mp); +} + +mblk_t * +allocb_cred(size_t size, cred_t *cr, pid_t cpid) +{ + mblk_t *mp = allocb(size, 0); + + ASSERT(cr != NULL); + if (mp != NULL) { + dblk_t *dbp = mp->b_datap; + + crhold(dbp->db_credp = cr); + dbp->db_cpid = cpid; + } + return (mp); +} + +mblk_t * +allocb_cred_wait(size_t size, uint_t flags, int *error, cred_t *cr, pid_t cpid) +{ + mblk_t *mp = allocb_wait(size, 0, flags, error); + + ASSERT(cr != NULL); + if (mp != NULL) { + dblk_t *dbp = mp->b_datap; + + crhold(dbp->db_credp = cr); + dbp->db_cpid = cpid; + } + + return (mp); +} + +/* + * Extract the db_cred (and optionally db_cpid) from a message. + * We find the first mblk which has a non-NULL db_cred and use that. + * If none found we return NULL. + * Does NOT get a hold on the cred. + */ +cred_t * +msg_getcred(const mblk_t *mp, pid_t *cpidp) +{ + cred_t *cr = NULL; + + while (mp != NULL) { + dblk_t *dbp = mp->b_datap; + + cr = dbp->db_credp; + if (cr == NULL) { + mp = mp->b_cont; + continue; + } + if (cpidp != NULL) + *cpidp = dbp->db_cpid; + + /* DEBUG check for only one db_credp */ + return (cr); + } + if (cpidp != NULL) + *cpidp = NOPID; + return (NULL); +} + +/* + * Variant of msg_getcred which, when a cred is found + * 1. Returns with a hold on the cred + * 2. Clears the first cred in the mblk. + * This is more efficient to use than a msg_getcred() + crhold() when + * the message is freed after the cred has been extracted. + * + * The caller is responsible for ensuring that there is no other reference + * on the message since db_credp can not be cleared when there are other + * references. + */ +cred_t * +msg_extractcred(mblk_t *mp, pid_t *cpidp) +{ + cred_t *cr = NULL; + + while (mp != NULL) { + dblk_t *dbp = mp->b_datap; + + cr = dbp->db_credp; + if (cr == NULL) { + mp = mp->b_cont; + continue; + } + ASSERT(dbp->db_ref == 1); + dbp->db_credp = NULL; + if (cpidp != NULL) + *cpidp = dbp->db_cpid; + + /* DEBUG check for only one db_credp */ + return (cr); + } + return (NULL); +} + +/* _KERNEL msg_getlabel() */ + +void +freeb(mblk_t *mp) +{ + dblk_t *dbp = mp->b_datap; + + ASSERT(dbp->db_ref > 0); + ASSERT(mp->b_next == NULL && mp->b_prev == NULL); + FTRACE_1("freeb(): mp=0x%lx", (uintptr_t)mp); + + STR_FTEVENT_MBLK(mp, caller(), FTEV_FREEB, dbp->db_ref); + + dbp->db_free(mp, dbp); +} + +void +freemsg(mblk_t *mp) +{ + FTRACE_1("freemsg(): mp=0x%lx", (uintptr_t)mp); + while (mp) { + dblk_t *dbp = mp->b_datap; + mblk_t *mp_cont = mp->b_cont; + + ASSERT(dbp->db_ref > 0); + ASSERT(mp->b_next == NULL && mp->b_prev == NULL); + + STR_FTEVENT_MBLK(mp, caller(), FTEV_FREEB, dbp->db_ref); + + dbp->db_free(mp, dbp); + mp = mp_cont; + } +} + +/* + * Reallocate a block for another use. Try hard to use the old block. + * If the old data is wanted (copy), leave b_wptr at the end of the data, + * otherwise return b_wptr = b_rptr. + * + * This routine is private and unstable. + */ +mblk_t * +reallocb(mblk_t *mp, size_t size, uint_t copy) +{ + mblk_t *mp1; + unsigned char *old_rptr; + ptrdiff_t cur_size; + + if (mp == NULL) + return (allocb(size, BPRI_HI)); + + cur_size = mp->b_wptr - mp->b_rptr; + old_rptr = mp->b_rptr; + + ASSERT(mp->b_datap->db_ref != 0); + + if (mp->b_datap->db_ref == 1 && MBLKSIZE(mp) >= size) { + /* + * If the data is wanted and it will fit where it is, no + * work is required. + */ + if (copy && mp->b_datap->db_lim - mp->b_rptr >= size) + return (mp); + + mp->b_wptr = mp->b_rptr = mp->b_datap->db_base; + mp1 = mp; + } else if ((mp1 = allocb_tmpl(size, mp)) != NULL) { + /* XXX other mp state could be copied too, db_flags ... ? */ + mp1->b_cont = mp->b_cont; + } else { + return (NULL); + } + + if (copy) { + bcopy(old_rptr, mp1->b_rptr, cur_size); + mp1->b_wptr = mp1->b_rptr + cur_size; + } + + if (mp != mp1) + freeb(mp); + + return (mp1); +} + +static void +dblk_lastfree(mblk_t *mp, dblk_t *dbp) +{ + ASSERT(dbp->db_mblk == mp); + if (dbp->db_fthdr != NULL) + str_ftfree(dbp); + + /* set credp and projid to be 'unspecified' before returning to cache */ + if (dbp->db_credp != NULL) { + crfree(dbp->db_credp); + dbp->db_credp = NULL; + } + dbp->db_cpid = -1; + + /* Reset the struioflag and the checksum flag fields */ + dbp->db_struioflag = 0; + dbp->db_struioun.cksum.flags = 0; + + /* and the COOKED and/or UIOA flag(s) */ + dbp->db_flags &= ~(DBLK_COOKED | DBLK_UIOA); + + kmem_cache_free(dbp->db_cache, dbp); +} + +static void +dblk_decref(mblk_t *mp, dblk_t *dbp) +{ + if (dbp->db_ref != 1) { + uint32_t rtfu = atomic_add_32_nv(&DBLK_RTFU_WORD(dbp), + -(1 << DBLK_RTFU_SHIFT(db_ref))); + /* + * atomic_add_32_nv() just decremented db_ref, so we no longer + * have a reference to the dblk, which means another thread + * could free it. Therefore we cannot examine the dblk to + * determine whether ours was the last reference. Instead, + * we extract the new and minimum reference counts from rtfu. + * Note that all we're really saying is "if (ref != refmin)". + */ + if (((rtfu >> DBLK_RTFU_SHIFT(db_ref)) & DBLK_REFMAX) != + ((rtfu >> DBLK_RTFU_SHIFT(db_flags)) & DBLK_REFMIN)) { + kmem_cache_free(mblk_cache, mp); + return; + } + } + dbp->db_mblk = mp; + dbp->db_free = dbp->db_lastfree; + dbp->db_lastfree(mp, dbp); +} + +mblk_t * +dupb(mblk_t *mp) +{ + dblk_t *dbp = mp->b_datap; + mblk_t *new_mp; + uint32_t oldrtfu, newrtfu; + + if ((new_mp = kmem_cache_alloc(mblk_cache, KM_NOSLEEP)) == NULL) + goto out; + + new_mp->b_next = new_mp->b_prev = new_mp->b_cont = NULL; + new_mp->b_rptr = mp->b_rptr; + new_mp->b_wptr = mp->b_wptr; + new_mp->b_datap = dbp; + new_mp->b_queue = NULL; + MBLK_BAND_FLAG_WORD(new_mp) = MBLK_BAND_FLAG_WORD(mp); + + STR_FTEVENT_MBLK(mp, caller(), FTEV_DUPB, dbp->db_ref); + + dbp->db_free = dblk_decref; + do { + ASSERT(dbp->db_ref > 0); + oldrtfu = DBLK_RTFU_WORD(dbp); + newrtfu = oldrtfu + (1 << DBLK_RTFU_SHIFT(db_ref)); + /* + * If db_ref is maxed out we can't dup this message anymore. + */ + if ((oldrtfu & DBLK_RTFU_REF_MASK) == DBLK_RTFU_REF_MASK) { + kmem_cache_free(mblk_cache, new_mp); + new_mp = NULL; + goto out; + } + } while (atomic_cas_32(&DBLK_RTFU_WORD(dbp), oldrtfu, newrtfu) != + oldrtfu); + +out: + FTRACE_1("dupb(): new_mp=0x%lx", (uintptr_t)new_mp); + return (new_mp); +} + +/*ARGSUSED*/ +static void +frnop_func(void *arg) +{ +} + +/* + * Generic esballoc used to implement the four flavors: [d]esballoc[a]. + * and allocb_oversize + */ +static mblk_t * +gesballoc(unsigned char *base, size_t size, uint32_t db_rtfu, frtn_t *frp, + void (*lastfree)(mblk_t *, dblk_t *), int kmflags) +{ + dblk_t *dbp; + mblk_t *mp; + + ASSERT(base != NULL && frp != NULL); + + if ((dbp = kmem_cache_alloc(dblk_esb_cache, kmflags)) == NULL) { + mp = NULL; + goto out; + } + + mp = dbp->db_mblk; + dbp->db_base = base; + dbp->db_lim = base + size; + dbp->db_free = dbp->db_lastfree = lastfree; + dbp->db_frtnp = frp; + DBLK_RTFU_WORD(dbp) = db_rtfu; + mp->b_next = mp->b_prev = mp->b_cont = NULL; + mp->b_rptr = mp->b_wptr = base; + mp->b_queue = NULL; + MBLK_BAND_FLAG_WORD(mp) = 0; + +out: + FTRACE_1("gesballoc(): mp=0x%lx", (uintptr_t)mp); + return (mp); +} + +static void +bcache_dblk_lastfree(mblk_t *mp, dblk_t *dbp) +{ + bcache_t *bcp = dbp->db_cache; + + ASSERT(dbp->db_mblk == mp); + if (dbp->db_fthdr != NULL) + str_ftfree(dbp); + + /* set credp and projid to be 'unspecified' before returning to cache */ + if (dbp->db_credp != NULL) { + crfree(dbp->db_credp); + dbp->db_credp = NULL; + } + dbp->db_cpid = -1; + dbp->db_struioflag = 0; + dbp->db_struioun.cksum.flags = 0; + + mutex_enter(&bcp->mutex); + kmem_cache_free(bcp->dblk_cache, dbp); + bcp->alloc--; + + if (bcp->alloc == 0 && bcp->destroy != 0) { + kmem_cache_destroy(bcp->dblk_cache); + kmem_cache_destroy(bcp->buffer_cache); + mutex_exit(&bcp->mutex); + mutex_destroy(&bcp->mutex); + kmem_free(bcp, sizeof (bcache_t)); + } else { + mutex_exit(&bcp->mutex); + } +} + +bcache_t * +bcache_create(char *name, size_t size, uint_t align) +{ + bcache_t *bcp; + char buffer[255]; + + ASSERT((align & (align - 1)) == 0); + + if ((bcp = kmem_alloc(sizeof (bcache_t), KM_NOSLEEP)) == NULL) + return (NULL); + + bcp->size = size; + bcp->align = align; + bcp->alloc = 0; + bcp->destroy = 0; + + mutex_init(&bcp->mutex, NULL, MUTEX_DRIVER, NULL); + + (void) sprintf(buffer, "%s_buffer_cache", name); + bcp->buffer_cache = kmem_cache_create(buffer, size, align, NULL, NULL, + NULL, NULL, NULL, 0); + (void) sprintf(buffer, "%s_dblk_cache", name); + bcp->dblk_cache = kmem_cache_create(buffer, sizeof (dblk_t), + DBLK_CACHE_ALIGN, bcache_dblk_constructor, bcache_dblk_destructor, + NULL, (void *)bcp, NULL, 0); + + return (bcp); +} + +void +bcache_destroy(bcache_t *bcp) +{ + ASSERT(bcp != NULL); + + mutex_enter(&bcp->mutex); + if (bcp->alloc == 0) { + kmem_cache_destroy(bcp->dblk_cache); + kmem_cache_destroy(bcp->buffer_cache); + mutex_exit(&bcp->mutex); + mutex_destroy(&bcp->mutex); + kmem_free(bcp, sizeof (bcache_t)); + } else { + bcp->destroy++; + mutex_exit(&bcp->mutex); + } +} + +/*ARGSUSED*/ +mblk_t * +bcache_allocb(bcache_t *bcp, uint_t pri) +{ + dblk_t *dbp; + mblk_t *mp = NULL; + + ASSERT(bcp != NULL); + + mutex_enter(&bcp->mutex); + if (bcp->destroy != 0) { + mutex_exit(&bcp->mutex); + goto out; + } + + if ((dbp = kmem_cache_alloc(bcp->dblk_cache, KM_NOSLEEP)) == NULL) { + mutex_exit(&bcp->mutex); + goto out; + } + bcp->alloc++; + mutex_exit(&bcp->mutex); + + ASSERT(((uintptr_t)(dbp->db_base) & (bcp->align - 1)) == 0); + + mp = dbp->db_mblk; + DBLK_RTFU_WORD(dbp) = DBLK_RTFU(1, M_DATA, 0, 0); + mp->b_next = mp->b_prev = mp->b_cont = NULL; + mp->b_rptr = mp->b_wptr = dbp->db_base; + mp->b_queue = NULL; + MBLK_BAND_FLAG_WORD(mp) = 0; + STR_FTALLOC(&dbp->db_fthdr, FTEV_BCALLOCB, bcp->size); +out: + FTRACE_1("bcache_allocb(): mp=0x%p", (uintptr_t)mp); + + return (mp); +} + +static void +dblk_lastfree_oversize(mblk_t *mp, dblk_t *dbp) +{ + ASSERT(dbp->db_mblk == mp); + if (dbp->db_fthdr != NULL) + str_ftfree(dbp); + + /* set credp and projid to be 'unspecified' before returning to cache */ + if (dbp->db_credp != NULL) { + crfree(dbp->db_credp); + dbp->db_credp = NULL; + } + dbp->db_cpid = -1; + dbp->db_struioflag = 0; + dbp->db_struioun.cksum.flags = 0; + + kmem_free(dbp->db_base, dbp->db_lim - dbp->db_base); + kmem_cache_free(dbp->db_cache, dbp); +} + +static mblk_t * +allocb_oversize(size_t size, int kmflags) +{ + mblk_t *mp; + void *buf; + + size = P2ROUNDUP(size, DBLK_CACHE_ALIGN); + if ((buf = kmem_alloc(size, kmflags)) == NULL) + return (NULL); + if ((mp = gesballoc(buf, size, DBLK_RTFU(1, M_DATA, 0, 0), + &frnop, dblk_lastfree_oversize, kmflags)) == NULL) + kmem_free(buf, size); + + if (mp != NULL) + STR_FTALLOC(&DB_FTHDR(mp), FTEV_ALLOCBIG, size); + + return (mp); +} + +mblk_t * +allocb_tryhard(size_t target_size) +{ + size_t size; + mblk_t *bp; + + for (size = target_size; size < target_size + 512; + size += DBLK_CACHE_ALIGN) + if ((bp = allocb(size, BPRI_HI)) != NULL) + return (bp); + allocb_tryhard_fails++; + return (NULL); +} + +/* + * This routine is consolidation private for STREAMS internal use + * This routine may only be called from sync routines (i.e., not + * from put or service procedures). It is located here (rather + * than strsubr.c) so that we don't have to expose all of the + * allocb() implementation details in header files. + */ +mblk_t * +allocb_wait(size_t size, uint_t pri, uint_t flags, int *error) +{ + dblk_t *dbp; + mblk_t *mp; + size_t index; + + index = (size -1) >> DBLK_SIZE_SHIFT; + + if (flags & STR_NOSIG) { + if (index >= (DBLK_MAX_CACHE >> DBLK_SIZE_SHIFT)) { + if (size != 0) { + mp = allocb_oversize(size, KM_SLEEP); + FTRACE_1("allocb_wait (NOSIG): mp=0x%lx", + (uintptr_t)mp); + return (mp); + } + index = 0; + } + + dbp = kmem_cache_alloc(dblk_cache[index], KM_SLEEP); + mp = dbp->db_mblk; + DBLK_RTFU_WORD(dbp) = DBLK_RTFU(1, M_DATA, 0, 0); + mp->b_next = mp->b_prev = mp->b_cont = NULL; + mp->b_rptr = mp->b_wptr = dbp->db_base; + mp->b_queue = NULL; + MBLK_BAND_FLAG_WORD(mp) = 0; + STR_FTALLOC(&DB_FTHDR(mp), FTEV_ALLOCBW, size); + + FTRACE_1("allocb_wait (NOSIG): mp=0x%lx", (uintptr_t)mp); + + } else { + while ((mp = allocb(size, pri)) == NULL) { + if ((*error = strwaitbuf(size, BPRI_HI)) != 0) + return (NULL); + } + } + + return (mp); +} + +/* + * Call function 'func' with 'arg' when a class zero block can + * be allocated with priority 'pri'. + */ +bufcall_id_t +esbbcall(uint_t pri, void (*func)(void *), void *arg) +{ + return (bufcall(1, pri, func, arg)); +} + +/* + * Allocates an iocblk (M_IOCTL) block. Properly sets the credentials + * ioc_id, rval and error of the struct ioctl to set up an ioctl call. + * This provides consistency for all internal allocators of ioctl. + */ +mblk_t * +mkiocb(uint_t cmd) +{ + struct iocblk *ioc; + mblk_t *mp; + + /* + * Allocate enough space for any of the ioctl related messages. + */ + if ((mp = allocb(sizeof (union ioctypes), BPRI_MED)) == NULL) + return (NULL); + + bzero(mp->b_rptr, sizeof (union ioctypes)); + + /* + * Set the mblk_t information and ptrs correctly. + */ + mp->b_wptr += sizeof (struct iocblk); + mp->b_datap->db_type = M_IOCTL; + + /* + * Fill in the fields. + */ + ioc = (struct iocblk *)mp->b_rptr; + ioc->ioc_cmd = cmd; + ioc->ioc_cr = kcred; + ioc->ioc_id = getiocseqno(); + ioc->ioc_flag = IOC_NATIVE; + return (mp); +} + +/* + * test if block of given size can be allocated with a request of + * the given priority. + * 'pri' is no longer used, but is retained for compatibility. + */ +/* ARGSUSED */ +int +testb(size_t size, uint_t pri) +{ + return ((size + sizeof (dblk_t)) <= kmem_avail()); +} + +/* _KERNEL: bufcall, unbufcall */ + +/* + * Duplicate a message block by block (uses dupb), returning + * a pointer to the duplicate message. + * Returns a non-NULL value only if the entire message + * was dup'd. + */ +mblk_t * +dupmsg(mblk_t *bp) +{ + mblk_t *head, *nbp; + + if (!bp || !(nbp = head = dupb(bp))) + return (NULL); + + while (bp->b_cont) { + if (!(nbp->b_cont = dupb(bp->b_cont))) { + freemsg(head); + return (NULL); + } + nbp = nbp->b_cont; + bp = bp->b_cont; + } + return (head); +} + +#define DUPB_NOLOAN(bp) \ + ((((bp)->b_datap->db_struioflag & STRUIO_ZC) != 0) ? \ + copyb((bp)) : dupb((bp))) + +mblk_t * +dupmsg_noloan(mblk_t *bp) +{ + mblk_t *head, *nbp; + + if (bp == NULL || DB_TYPE(bp) != M_DATA || + ((nbp = head = DUPB_NOLOAN(bp)) == NULL)) + return (NULL); + + while (bp->b_cont) { + if ((nbp->b_cont = DUPB_NOLOAN(bp->b_cont)) == NULL) { + freemsg(head); + return (NULL); + } + nbp = nbp->b_cont; + bp = bp->b_cont; + } + return (head); +} + +/* + * Copy data from message and data block to newly allocated message and + * data block. Returns new message block pointer, or NULL if error. + * The alignment of rptr (w.r.t. word alignment) will be the same in the copy + * as in the original even when db_base is not word aligned. (bug 1052877) + */ +mblk_t * +copyb(mblk_t *bp) +{ + mblk_t *nbp; + dblk_t *dp, *ndp; + uchar_t *base; + size_t size; + size_t unaligned; + + ASSERT(bp->b_wptr >= bp->b_rptr); + + dp = bp->b_datap; + if (dp->db_fthdr != NULL) + STR_FTEVENT_MBLK(bp, caller(), FTEV_COPYB, 0); + + /* + * Special handling for Multidata message; this should be + * removed once a copy-callback routine is made available. + */ + if (dp->db_type == M_MULTIDATA) { + /* _KERNEL mmd_copy stuff */ + return (NULL); + } + + size = dp->db_lim - dp->db_base; + unaligned = P2PHASE((uintptr_t)dp->db_base, sizeof (uint_t)); + if ((nbp = allocb_tmpl(size + unaligned, bp)) == NULL) + return (NULL); + nbp->b_flag = bp->b_flag; + nbp->b_band = bp->b_band; + ndp = nbp->b_datap; + + /* + * Well, here is a potential issue. If we are trying to + * trace a flow, and we copy the message, we might lose + * information about where this message might have been. + * So we should inherit the FT data. On the other hand, + * a user might be interested only in alloc to free data. + * So I guess the real answer is to provide a tunable. + */ + STR_FTEVENT_MBLK(nbp, caller(), FTEV_COPYB, 1); + + base = ndp->db_base + unaligned; + bcopy(dp->db_base, ndp->db_base + unaligned, size); + + nbp->b_rptr = base + (bp->b_rptr - dp->db_base); + nbp->b_wptr = nbp->b_rptr + MBLKL(bp); + + return (nbp); +} + +/* + * Copy data from message to newly allocated message using new + * data blocks. Returns a pointer to the new message, or NULL if error. + */ +mblk_t * +copymsg(mblk_t *bp) +{ + mblk_t *head, *nbp; + + if (!bp || !(nbp = head = copyb(bp))) + return (NULL); + + while (bp->b_cont) { + if (!(nbp->b_cont = copyb(bp->b_cont))) { + freemsg(head); + return (NULL); + } + nbp = nbp->b_cont; + bp = bp->b_cont; + } + return (head); +} + +/* + * link a message block to tail of message + */ +void +linkb(mblk_t *mp, mblk_t *bp) +{ + ASSERT(mp && bp); + + for (; mp->b_cont; mp = mp->b_cont) + ; + mp->b_cont = bp; +} + +/* + * unlink a message block from head of message + * return pointer to new message. + * NULL if message becomes empty. + */ +mblk_t * +unlinkb(mblk_t *bp) +{ + mblk_t *bp1; + + bp1 = bp->b_cont; + bp->b_cont = NULL; + return (bp1); +} + +/* + * remove a message block "bp" from message "mp" + * + * Return pointer to new message or NULL if no message remains. + * Return -1 if bp is not found in message. + */ +mblk_t * +rmvb(mblk_t *mp, mblk_t *bp) +{ + mblk_t *tmp; + mblk_t *lastp = NULL; + + ASSERT(mp && bp); + for (tmp = mp; tmp; tmp = tmp->b_cont) { + if (tmp == bp) { + if (lastp) + lastp->b_cont = tmp->b_cont; + else + mp = tmp->b_cont; + tmp->b_cont = NULL; + return (mp); + } + lastp = tmp; + } + return ((mblk_t *)-1); +} + +/* + * Concatenate and align first len bytes of common + * message type. Len == -1, means concat everything. + * Returns 1 on success, 0 on failure + * After the pullup, mp points to the pulled up data. + */ +int +pullupmsg(mblk_t *mp, ssize_t len) +{ + mblk_t *bp, *b_cont; + dblk_t *dbp; + ssize_t n; + + ASSERT(mp->b_datap->db_ref > 0); + ASSERT(mp->b_next == NULL && mp->b_prev == NULL); + + /* + * We won't handle Multidata message, since it contains + * metadata which this function has no knowledge of; we + * assert on DEBUG, and return failure otherwise. + */ + ASSERT(mp->b_datap->db_type != M_MULTIDATA); + if (mp->b_datap->db_type == M_MULTIDATA) + return (0); + + if (len == -1) { + if (mp->b_cont == NULL && str_aligned(mp->b_rptr)) + return (1); + len = xmsgsize(mp); + } else { + ssize_t first_mblk_len = mp->b_wptr - mp->b_rptr; + ASSERT(first_mblk_len >= 0); + /* + * If the length is less than that of the first mblk, + * we want to pull up the message into an aligned mblk. + * Though not part of the spec, some callers assume it. + */ + if (len <= first_mblk_len) { + if (str_aligned(mp->b_rptr)) + return (1); + len = first_mblk_len; + } else if (xmsgsize(mp) < len) + return (0); + } + + if ((bp = allocb_tmpl(len, mp)) == NULL) + return (0); + + dbp = bp->b_datap; + *bp = *mp; /* swap mblks so bp heads the old msg... */ + mp->b_datap = dbp; /* ... and mp heads the new message */ + mp->b_datap->db_mblk = mp; + bp->b_datap->db_mblk = bp; + mp->b_rptr = mp->b_wptr = dbp->db_base; + + do { + ASSERT(bp->b_datap->db_ref > 0); + ASSERT(bp->b_wptr >= bp->b_rptr); + n = MIN(bp->b_wptr - bp->b_rptr, len); + ASSERT(n >= 0); /* allow zero-length mblk_t's */ + if (n > 0) + bcopy(bp->b_rptr, mp->b_wptr, (size_t)n); + mp->b_wptr += n; + bp->b_rptr += n; + len -= n; + if (bp->b_rptr != bp->b_wptr) + break; + b_cont = bp->b_cont; + freeb(bp); + bp = b_cont; + } while (len && bp); + + mp->b_cont = bp; /* tack on whatever wasn't pulled up */ + + return (1); +} + +/* + * Concatenate and align at least the first len bytes of common message + * type. Len == -1 means concatenate everything. The original message is + * unaltered. Returns a pointer to a new message on success, otherwise + * returns NULL. + */ +mblk_t * +msgpullup(mblk_t *mp, ssize_t len) +{ + mblk_t *newmp; + ssize_t totlen; + ssize_t n; + + /* + * We won't handle Multidata message, since it contains + * metadata which this function has no knowledge of; we + * assert on DEBUG, and return failure otherwise. + */ + ASSERT(mp->b_datap->db_type != M_MULTIDATA); + if (mp->b_datap->db_type == M_MULTIDATA) + return (NULL); + + totlen = xmsgsize(mp); + + if ((len > 0) && (len > totlen)) + return (NULL); + + /* + * Copy all of the first msg type into one new mblk, then dupmsg + * and link the rest onto this. + */ + + len = totlen; + + if ((newmp = allocb_tmpl(len, mp)) == NULL) + return (NULL); + + newmp->b_flag = mp->b_flag; + newmp->b_band = mp->b_band; + + while (len > 0) { + n = mp->b_wptr - mp->b_rptr; + ASSERT(n >= 0); /* allow zero-length mblk_t's */ + if (n > 0) + bcopy(mp->b_rptr, newmp->b_wptr, n); + newmp->b_wptr += n; + len -= n; + mp = mp->b_cont; + } + + if (mp != NULL) { + newmp->b_cont = dupmsg(mp); + if (newmp->b_cont == NULL) { + freemsg(newmp); + return (NULL); + } + } + + return (newmp); +} + +/* + * Trim bytes from message + * len > 0, trim from head + * len < 0, trim from tail + * Returns 1 on success, 0 on failure. + */ +int +adjmsg(mblk_t *mp, ssize_t len) +{ + mblk_t *bp; + mblk_t *save_bp = NULL; + mblk_t *prev_bp; + mblk_t *bcont; + unsigned char type; + ssize_t n; + int fromhead; + int first; + + ASSERT(mp != NULL); + /* + * We won't handle Multidata message, since it contains + * metadata which this function has no knowledge of; we + * assert on DEBUG, and return failure otherwise. + */ + ASSERT(mp->b_datap->db_type != M_MULTIDATA); + if (mp->b_datap->db_type == M_MULTIDATA) + return (0); + + if (len < 0) { + fromhead = 0; + len = -len; + } else { + fromhead = 1; + } + + if (xmsgsize(mp) < len) + return (0); + + if (fromhead) { + first = 1; + while (len) { + ASSERT(mp->b_wptr >= mp->b_rptr); + n = MIN(mp->b_wptr - mp->b_rptr, len); + mp->b_rptr += n; + len -= n; + + /* + * If this is not the first zero length + * message remove it + */ + if (!first && (mp->b_wptr == mp->b_rptr)) { + bcont = mp->b_cont; + freeb(mp); + mp = save_bp->b_cont = bcont; + } else { + save_bp = mp; + mp = mp->b_cont; + } + first = 0; + } + } else { + type = mp->b_datap->db_type; + while (len) { + bp = mp; + save_bp = NULL; + + /* + * Find the last message of same type + */ + while (bp && bp->b_datap->db_type == type) { + ASSERT(bp->b_wptr >= bp->b_rptr); + prev_bp = save_bp; + save_bp = bp; + bp = bp->b_cont; + } + if (save_bp == NULL) + break; + n = MIN(save_bp->b_wptr - save_bp->b_rptr, len); + save_bp->b_wptr -= n; + len -= n; + + /* + * If this is not the first message + * and we have taken away everything + * from this message, remove it + */ + + if ((save_bp != mp) && + (save_bp->b_wptr == save_bp->b_rptr)) { + bcont = save_bp->b_cont; + freeb(save_bp); + prev_bp->b_cont = bcont; + } + } + } + return (1); +} + +/* + * get number of data bytes in message + */ +size_t +msgdsize(mblk_t *bp) +{ + size_t count = 0; + + for (; bp; bp = bp->b_cont) + if (bp->b_datap->db_type == M_DATA) { + ASSERT(bp->b_wptr >= bp->b_rptr); + count += bp->b_wptr - bp->b_rptr; + } + return (count); +} + +/* getq() etc to EOF removed */ diff --git a/usr/src/lib/smbclnt/libfknsmb/common/fake_strsubr.c b/usr/src/lib/smbclnt/libfknsmb/common/fake_strsubr.c new file mode 100644 index 0000000000..e49313c37c --- /dev/null +++ b/usr/src/lib/smbclnt/libfknsmb/common/fake_strsubr.c @@ -0,0 +1,160 @@ +/* + * 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 (c) 1984, 1986, 1987, 1988, 1989 AT&T */ +/* All Rights Reserved */ + +/* + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * Copyright (c) 2016 by Delphix. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + */ + +#include +#include + +#include +#include +#include +#include + +#include + +int str_ftnever = 0; + +static void mblk_free(mblk_t *); +static void esballoc_mblk_free(mblk_t *); + +/* + * A few things from os/strsubr.c + */ + +int +strwaitbuf(size_t size, int pri) +{ + return (0); +} + +/* + * Return size of message of block type (bp->b_datap->db_type) + */ +size_t +xmsgsize(mblk_t *bp) +{ + unsigned char type; + size_t count = 0; + + type = bp->b_datap->db_type; + + for (; bp; bp = bp->b_cont) { + if (type != bp->b_datap->db_type) + break; + ASSERT(bp->b_wptr >= bp->b_rptr); + count += bp->b_wptr - bp->b_rptr; + } + return (count); +} + +/* ARGSUSED */ +bufcall_id_t +bufcall(size_t size, uint_t pri, void (*func)(void *), void *arg) +{ + cmn_err(CE_NOTE, "bufcall() called!"); + return ("fake bufcall id"); +} + +/* ARGSUSED */ +void +unbufcall(bufcall_id_t id) +{ +} + +/* ARGSUSED */ +void +freebs_enqueue(mblk_t *mp, dblk_t *dbp) +{ + /* + * Won't bother with esb_queue_t async free here. + * Rather just free this mblk directly. + */ + esballoc_mblk_free(mp); +} + +static void +esballoc_mblk_free(mblk_t *mp) +{ + mblk_t *nextmp; + + for (; mp != NULL; mp = nextmp) { + nextmp = mp->b_next; + mp->b_next = NULL; + mblk_free(mp); + } +} + +static void +mblk_free(mblk_t *mp) +{ + dblk_t *dbp = mp->b_datap; + frtn_t *frp = dbp->db_frtnp; + + mp->b_next = NULL; + if (dbp->db_fthdr != NULL) + str_ftfree(dbp); + + ASSERT(dbp->db_fthdr == NULL); + frp->free_func(frp->free_arg); + ASSERT(dbp->db_mblk == mp); + + if (dbp->db_credp != NULL) { + crfree(dbp->db_credp); + dbp->db_credp = NULL; + } + dbp->db_cpid = -1; + dbp->db_struioflag = 0; + dbp->db_struioun.cksum.flags = 0; + + kmem_cache_free(dbp->db_cache, dbp); +} + +/* ARGSUSED */ +mblk_t * +mmd_copy(mblk_t *bp, int flags) +{ + return (NULL); +} + +/* + * A little bit from os/streamio.c + */ + +static volatile uint32_t ioc_id; + +int +getiocseqno(void) +{ + uint32_t i; + + i = atomic_inc_32_nv(&ioc_id); + + return ((int)i); +} diff --git a/usr/src/lib/smbclnt/libfknsmb/common/fake_xti.h b/usr/src/lib/smbclnt/libfknsmb/common/fake_xti.h new file mode 100644 index 0000000000..d58b5454c4 --- /dev/null +++ b/usr/src/lib/smbclnt/libfknsmb/common/fake_xti.h @@ -0,0 +1,314 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2014 Garrett D'Amore + */ +/* Copyright (c) 1996 Sun Microsystems, Inc. */ +/* All Rights Reserved */ +/* + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + */ + +#ifndef _XTI_H +#define _XTI_H + +#include + +/* + * The following include file has declarations needed by both the kernel + * level transport providers and the user level library. This file includes + * it to expose its namespaces to XTI user level interface. + */ +#include + +/* + * Include XTI interface level options management declarations + */ +#include + +#if !defined(_XPG5) + +/* + * Include declarations related to OSI transport and management data + * structures, and the Internet Protocol Suite. + * Note: The older Unix95/XNS4 XTI spec required these to be + * exposed through the generic interface header. + */ +#include +#include + +#endif /* !defined(_XPG5) */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The following t_errno error codes are included in the namespace by + * inclusion of above. The english language error strings + * associated with the error values are reproduced here for easy reference. + * + * Error Value Error message string + * ---- ----- -------------------- + * TBADADDR 1 Incorrect address format + * TBADOPT 2 Incorrect options format + * TACCES 3 Illegal permissions + * TBADF 4 Illegal file descriptor + * TNOADDR 5 Couldn't allocate address + * TOUTSTATE 6 Routine will place interface out of state + * TBADSEQ 7 Illegal called/calling sequence number + * TSYSERR 8 System error + * TLOOK 9 An event requires attention + * TBADDATA 10 Illegal amount of data + * TBUFOVFLW 11 Buffer not large enough + * TFLOW 12 Can't send message - (blocked) + * TNODATA 13 No message currently available + * TNODIS 14 Disconnect message not found + * TNOUDERR 15 Unitdata error message not found + * TBADFLAG 16 Incorrect flags specified + * TNOREL 17 Orderly release message not found + * TNOTSUPPORT 18 Primitive not supported by provider + * TSTATECHNG 19 State is in process of changing + * TNOSTRUCTYPE 20 Unsupported structure type requested + * TBADNAME 21 Invalid transport provider name + * TBADQLEN 22 Listener queue length limit is zero + * TADDRBUSY 23 Transport address is in use + * TINDOUT 24 Outstanding connection indications + * TPROVMISMATCH 25 Listener-acceptor transport provider mismatch + * TRESQLEN 26 Connection acceptor has listen queue length + * limit greater than zero + * TRESADDR 27 Connection acceptor-listener addresses not + * same but required by transport + * TQFULL 28 Incoming connection queue is full + * TPROTO 29 Protocol error on transport primitive + * + */ + +/* + * The following are the events returned by t_look + */ +#define T_LISTEN 0x0001 /* connection indication received */ +#define T_CONNECT 0x0002 /* connect confirmation received */ +#define T_DATA 0x0004 /* normal data received */ +#define T_EXDATA 0x0008 /* expedited data received */ +#define T_DISCONNECT 0x0010 /* disconnect received */ +#define T_UDERR 0x0040 /* data gram error indication */ +#define T_ORDREL 0x0080 /* orderly release indication */ +#define T_GODATA 0x0100 /* sending normal data is again possible */ +#define T_GOEXDATA 0x0200 /* sending expedited data is again possible */ + +/* + * Flags for data primitives + */ +#define T_MORE 0x001 /* more data */ +#define T_EXPEDITED 0x002 /* expedited data */ +#define T_PUSH 0x004 /* send data immediately */ + +/* + * XTI error return + */ +#if defined(_REENTRANT) || defined(_TS_ERRNO) +extern int *__t_errno(); +#define t_errno (*(__t_errno())) +#else +#error "extern int t_errno?" +#endif /* defined(_REENTRANT) || defined(_TS_ERRNO) */ + + +/* + * The following are for t_sysconf() + */ +#ifndef T_IOV_MAX +#define T_IOV_MAX 16 /* Maximum number of scatter/gather buffers */ +#endif /* Should be <= IOV_MAX */ + +#ifndef _SC_T_IOV_MAX +#define _SC_T_IOV_MAX 79 /* Should be same in for use by */ +#endif /* sysconf() */ + +struct t_iovec { + void *iov_base; + size_t iov_len; +}; + +/* + * Translate source level interface to binary entry point names. + * + * Note: This is done to maintain co-existence of TLI and XTI + * interfaces which have identical names for most functions but + * different semantics. The XTI names are moved to the different + * prefix space in the ABI. The #ifdef is required to make use of + * of the compiler feature to allow redefinition of external names + * where available. Otherwise a simple #define is used when this + * header is used with other compilers. + * The use of #define also has the effect of renaming all names (not + * just function names) to the new name. The TLI function names + * (e.g. t_bind) can have identical names for structure names + * (e.g struct t_bind). Therefore, this redefinition of names needs + * to be before all structure and function name declarations in the header. + */ + +#ifdef __PRAGMA_REDEFINE_EXTNAME + +#if defined(_XOPEN_SOURCE) && !defined(_XPG5) +#pragma redefine_extname t_accept _xti_accept +#else +#pragma redefine_extname t_accept _xti_xns5_accept +#endif +#pragma redefine_extname t_alloc _xti_alloc +#pragma redefine_extname t_bind _xti_bind +#pragma redefine_extname t_close _xti_close +#pragma redefine_extname t_connect _xti_connect +#pragma redefine_extname t_error _xti_error +#pragma redefine_extname t_free _xti_free +#pragma redefine_extname t_getinfo _xti_getinfo +#pragma redefine_extname t_getstate _xti_getstate +#pragma redefine_extname t_getprotaddr _xti_getprotaddr +#pragma redefine_extname t_listen _xti_listen +#pragma redefine_extname t_look _xti_look +#pragma redefine_extname t_open _xti_open +#pragma redefine_extname t_optmgmt _xti_optmgmt +#pragma redefine_extname t_rcv _xti_rcv +#pragma redefine_extname t_rcvconnect _xti_rcvconnect +#pragma redefine_extname t_rcvdis _xti_rcvdis +#pragma redefine_extname t_rcvrel _xti_rcvrel +#pragma redefine_extname t_rcvreldata _xti_rcvreldata +#pragma redefine_extname t_rcvudata _xti_rcvudata +#pragma redefine_extname t_rcvuderr _xti_rcvuderr +#pragma redefine_extname t_rcvv _xti_rcvv +#pragma redefine_extname t_rcvvudata _xti_rcvvudata +#if defined(_XOPEN_SOURCE) && !defined(_XPG5) +#pragma redefine_extname t_snd _xti_snd +#else +#pragma redefine_extname t_snd _xti_xns5_snd +#endif +#pragma redefine_extname t_snddis _xti_snddis +#pragma redefine_extname t_sndrel _xti_sndrel +#pragma redefine_extname t_sndreldata _xti_sndreldata +#pragma redefine_extname t_sndudata _xti_sndudata +#pragma redefine_extname t_sndv _xti_sndv +#pragma redefine_extname t_sndvudata _xti_sndvudata +#pragma redefine_extname t_strerror _xti_strerror +#pragma redefine_extname t_sync _xti_sync +#pragma redefine_extname t_sysconf _xti_sysconf +#pragma redefine_extname t_unbind _xti_unbind + +#else /* __PRAGMA_REDEFINE_EXTNAME */ + +#if defined(_XOPEN_SOURCE) && !defined(_XPG5) +#define t_accept _xti_accept +#else +#define t_accept _xti_xns5_accept +#endif +#define t_alloc _xti_alloc +#define t_bind(a,b,c) _xti_bind(a,b,c) +#define t_close _xti_close +#define t_connect _xti_connect +#define t_error _xti_error +#define t_free _xti_free +#define t_getinfo _xti_getinfo +#define t_getstate _xti_getstate +#define t_getprotaddr _xti_getprotaddr +#define t_listen _xti_listen +#define t_look _xti_look +#define t_open _xti_open +#define t_optmgmt(a,b,c) _xti_optmgmt(a,b,c) +#define t_rcv _xti_rcv +#define t_rcvconnect _xti_rcvconnect +#define t_rcvdis _xti_rcvdis +#define t_rcvrel _xti_rcvrel +#define t_rcvreldata _xti_rcvreldata +#define t_rcvudata _xti_rcvudata +#define t_rcvuderr _xti_rcvuderr +#define t_rcvv _xti_rcvv +#define t_rcvvudata _xti_rcvvudata +#if defined(_XOPEN_SOURCE) && !defined(_XPG5) +#define t_snd _xti_snd +#else +#define t_snd _xti_xns5_snd +#endif +#define t_snddis _xti_snddis +#define t_sndrel _xti_sndrel +#define t_sndreldata _xti_sndreldata +#define t_sndudata _xti_sndudata +#define t_sndv _xti_sndv +#define t_sndvudata _xti_sndvudata +#define t_strerror _xti_strerror +#define t_sync _xti_sync +#define t_sysconf _xti_sysconf +#define t_unbind _xti_unbind + +#endif /* __PRAGMA_REDEFINE_EXTNAME */ + +/* + * All the rest of the standard xti.h removed because the structs: + * netbuf, t_info, t_opthdr, t_optmgmt, t_bind, t_call, ... + * all conflict with definitions in tiuser.h which we need + * for the (simulated) kernel interfaces in fake_ktli.c. + * + * The XTI library functions below would normally be defined by + * including tiuser.h after the defines above, which we can't. + */ + +int _xti_accept(int, int, struct t_call *); +int _xti_xns5_accept(int, int, struct t_call *); +char *_xti_alloc(int, int, int); +int _xti_bind(int, struct t_bind *, struct t_bind *); +int _xti_close(int); +int _xti_connect(int, struct t_call *, struct t_call *); +int _xti_error(char *); +int _xti_free(char *, int); +int _xti_getinfo(int, struct t_info *); +int _xti_getprotaddr(int, struct t_bind *, struct t_bind *); +int _xti_getstate(int); +int _xti_listen(int, struct t_call *); +int _xti_look(int); +int _xti_open(char *, int, struct t_info *); +int _xti_optmgmt(int, struct t_optmgmt *, struct t_optmgmt *); +int _xti_rcv(int, char *, unsigned int, int *); +int _xti_rcvconnect(int, struct t_call *); +int _xti_rcvdis(int, struct t_discon *); +int _xti_rcvrel(int); +int _xti_rcvreldata(int, struct t_discon *); +int _xti_rcvudata(int, struct t_unitdata *, int *); +int _xti_rcvuderr(int, struct t_uderr *); +int _xti_rcvv(int, struct t_iovec *, unsigned int, int *); +int _xti_rcvvudata(int, struct t_unitdata *, struct t_iovec *, + unsigned int, int *); +int _xti_snd(int, char *, unsigned int, int); +int _xti_xns5_snd(int, char *, unsigned int, int); +int _xti_snddis(int, struct t_call *); +int _xti_sndrel(int); +int _xti_sndreldata(int, struct t_discon *); +int _xti_sndudata(int, struct t_unitdata *); +int _xti_sndv(int, const struct t_iovec *, unsigned int, int); +int _xti_sndvudata(int, struct t_unitdata *, struct t_iovec *, unsigned int); +char *_xti_strerror(int); +int _xti_sync(int); +int _xti_sysconf(int); +int _xti_unbind(int); + +#ifdef __cplusplus +} +#endif + +#endif /* _XTI_H */ diff --git a/usr/src/lib/smbclnt/libfknsmb/common/fksmb_sign_pkcs.c b/usr/src/lib/smbclnt/libfknsmb/common/fksmb_sign_pkcs.c new file mode 100644 index 0000000000..24bb8fccbc --- /dev/null +++ b/usr/src/lib/smbclnt/libfknsmb/common/fksmb_sign_pkcs.c @@ -0,0 +1,163 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + */ + +/* + * Helper functions for SMB signing using PKCS#11 + * + * There are two implementations of these functions: + * This one (for user space) and another for kernel. + * See: uts/common/fs/smbclnt/netsmb/smb_sign_kcf.c + */ + +#include +#include +#include +#include +#include + +/* + * SMB1 signing helpers: + * (getmech, init, update, final) + */ + +int +smb_md5_getmech(smb_sign_mech_t *mech) +{ + mech->mechanism = CKM_MD5; + mech->pParameter = NULL; + mech->ulParameterLen = 0; + return (0); +} + +/* + * Start PKCS#11 session. + */ +int +smb_md5_init(smb_sign_ctx_t *ctxp, smb_sign_mech_t *mech) +{ + CK_RV rv; + + rv = SUNW_C_GetMechSession(mech->mechanism, ctxp); + if (rv != CKR_OK) + return (-1); + + rv = C_DigestInit(*ctxp, mech); + + return (rv == CKR_OK ? 0 : -1); +} + +/* + * Digest one segment + */ +int +smb_md5_update(smb_sign_ctx_t ctx, void *buf, size_t len) +{ + CK_RV rv; + + rv = C_DigestUpdate(ctx, buf, len); + if (rv != CKR_OK) + (void) C_CloseSession(ctx); + + return (rv == CKR_OK ? 0 : -1); +} + +/* + * Get the final digest. + */ +int +smb_md5_final(smb_sign_ctx_t ctx, uint8_t *digest16) +{ + CK_ULONG len = MD5_DIGEST_LENGTH; + CK_RV rv; + + rv = C_DigestFinal(ctx, digest16, &len); + (void) C_CloseSession(ctx); + + return (rv == CKR_OK ? 0 : -1); +} + +/* + * SMB2 signing helpers: + * (getmech, init, update, final) + */ + +int +smb2_hmac_getmech(smb_sign_mech_t *mech) +{ + mech->mechanism = CKM_SHA256_HMAC; + mech->pParameter = NULL; + mech->ulParameterLen = 0; + return (0); +} + +/* + * Start PKCS#11 session, load the key. + */ +int +smb2_hmac_init(smb_sign_ctx_t *ctxp, smb_sign_mech_t *mech, + uint8_t *key, size_t key_len) +{ + CK_OBJECT_HANDLE hkey = 0; + CK_RV rv; + + rv = SUNW_C_GetMechSession(mech->mechanism, ctxp); + if (rv != CKR_OK) + return (-1); + + rv = SUNW_C_KeyToObject(*ctxp, mech->mechanism, + key, key_len, &hkey); + if (rv != CKR_OK) + return (-1); + + rv = C_SignInit(*ctxp, mech, hkey); + (void) C_DestroyObject(*ctxp, hkey); + + return (rv == CKR_OK ? 0 : -1); +} + +/* + * Digest one segment + */ +int +smb2_hmac_update(smb_sign_ctx_t ctx, uint8_t *in, size_t len) +{ + CK_RV rv; + + rv = C_SignUpdate(ctx, in, len); + if (rv != CKR_OK) + (void) C_CloseSession(ctx); + + return (rv == CKR_OK ? 0 : -1); +} + +/* + * Note, the SMB2 signature is the first 16 bytes of the + * 32-byte SHA256 HMAC digest. + */ +int +smb2_hmac_final(smb_sign_ctx_t ctx, uint8_t *digest16) +{ + uint8_t full_digest[SHA256_DIGEST_LENGTH]; + CK_ULONG len = SHA256_DIGEST_LENGTH; + CK_RV rv; + + rv = C_SignFinal(ctx, full_digest, &len); + if (rv == CKR_OK) + bcopy(full_digest, digest16, 16); + + (void) C_CloseSession(ctx); + + return (rv == CKR_OK ? 0 : -1); +} diff --git a/usr/src/lib/smbclnt/libfknsmb/common/libfknsmb.h b/usr/src/lib/smbclnt/libfknsmb/common/libfknsmb.h new file mode 100644 index 0000000000..b3d15510be --- /dev/null +++ b/usr/src/lib/smbclnt/libfknsmb/common/libfknsmb.h @@ -0,0 +1,45 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + */ + +#ifndef _LIBFKNSMB_H_ +#define _LIBFKNSMB_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct smb_share; + +extern const uint32_t nsmb_version; +extern void streams_msg_init(void); + +int nsmb_drv_init(void); +int nsmb_drv_fini(void); +/* These are dev32_t because they're cast to int in user code. */ +int nsmb_drv_ioctl(dev32_t dev, int cmd, intptr_t arg, int flags); +int nsmb_drv_open(dev32_t *dev, int flags, int otyp); +int nsmb_drv_close(dev32_t dev, int flags, int otyp); +int smb_dev2share(int fd, struct smb_share **sspp); +void nsmb_drv_load(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBFKNSMB_H_ */ diff --git a/usr/src/lib/smbclnt/libfknsmb/common/llib-lfknsmb b/usr/src/lib/smbclnt/libfknsmb/common/llib-lfknsmb new file mode 100644 index 0000000000..8ba9f62607 --- /dev/null +++ b/usr/src/lib/smbclnt/libfknsmb/common/llib-lfknsmb @@ -0,0 +1,19 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + */ + +/*LINTLIBRARY*/ +/*PROTOLIB1*/ + +#include diff --git a/usr/src/lib/smbclnt/libfknsmb/common/mapfile-vers b/usr/src/lib/smbclnt/libfknsmb/common/mapfile-vers new file mode 100644 index 0000000000..1123cc1e85 --- /dev/null +++ b/usr/src/lib/smbclnt/libfknsmb/common/mapfile-vers @@ -0,0 +1,121 @@ +# +# 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 (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2017 Nexenta Systems, Inc. All rights reserved. +# + +# +# MAPFILE HEADER START +# +# WARNING: STOP NOW. DO NOT MODIFY THIS FILE. +# Object versioning must comply with the rules detailed in +# +# usr/src/lib/README.mapfiles +# +# You should not be making modifications here until you've read the most current +# copy of that file. If you need help, contact a gatekeeper for guidance. +# +# MAPFILE HEADER END +# + +$mapfile_version 2 + +SYMBOL_VERSION SUNWprivate { + global: + kmem_avail; + kmem_maxavail; + + nsmb_drv_close; + nsmb_drv_fini; + nsmb_drv_init; + nsmb_drv_ioctl; + nsmb_drv_load; + nsmb_drv_open; + + nsmb_version; + + m_fixhdr; + mb_done; + mb_init; + mb_initm; + mb_put_mem; + mb_put_padbyte; + mb_put_uint16le; + mb_put_uint32le; + mb_put_uint64le; + mb_put_uint8; + mb_reserve; + + md_done; + md_get_mbuf; + md_get_mem; + md_get_uint16le; + md_get_uint32le; + md_get_uint64le; + md_get_uint8; + md_initm; + + secpolicy_fs_allowed_mount; + secpolicy_vnode_access2; + secpolicy_vnode_owner; + secpolicy_vnode_setattr; + secpolicy_vnode_setdac; + + smb_credinit; + smb_credrele; + smb_dev2share; + smb_dos2unixtime; + smb_errmsg; + smb_nt_alloc; + smb_nt_done; + smb_nt_request; + smb_put_dmem; + smb_rq_alloc; + smb_rq_bend; + smb_rq_bstart; + smb_rq_done; + smb_rq_init; + smb_rq_simple; + smb_rq_simple_timed; + smb_rq_wend; + smb_rq_wstart; + smb_rwuio; + smb_share_kill; + smb_share_rele; + smb_smb_close; + smb_smb_ntcreate; + smb_t2_alloc; + smb_t2_done; + smb_t2_request; + smb_time_NT2local; + smb_time_local2NT; + smb_time_local2server; + smb_time_server2local; + smb_time_unix2dos; + smb_timo_append; + smb_timo_open; + smb_timo_read; + smb_timo_write; + + local: + *; +}; diff --git a/usr/src/lib/smbclnt/libfknsmb/common/sys/ftrace.h b/usr/src/lib/smbclnt/libfknsmb/common/sys/ftrace.h new file mode 100644 index 0000000000..68979ca9d4 --- /dev/null +++ b/usr/src/lib/smbclnt/libfknsmb/common/sys/ftrace.h @@ -0,0 +1,67 @@ +/* + * 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 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + */ + +#ifndef _SYS_FTRACE_H +#define _SYS_FTRACE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Constants used by both asm and non-asm code. + */ + +/* + * Flags determining the state of tracing - + * both for the "ftrace_state" variable, and for the per-CPU variable + * "cpu[N]->cpu_ftrace_state". + */ +#define FTRACE_READY 0x00000001 +#define FTRACE_ENABLED 0x00000002 + +#include +#include + +/* + * The record of a single event. + * ftrace_record_t; + */ + +#define FTRACE_0(fmt) \ + DTRACE_PROBE1(ftrace0, char *, fmt) +#define FTRACE_1(fmt, d1) \ + DTRACE_PROBE2(ftrace1, char *, fmt, uintptr_t, d1) + +// #define FTRACE_START() ftrace_start() +// #define FTRACE_STOP() ftrace_stop() + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_FTRACE_H */ diff --git a/usr/src/lib/smbclnt/libfknsmb/common/sys/kidmap.h b/usr/src/lib/smbclnt/libfknsmb/common/sys/kidmap.h new file mode 100644 index 0000000000..64a48897c3 --- /dev/null +++ b/usr/src/lib/smbclnt/libfknsmb/common/sys/kidmap.h @@ -0,0 +1,183 @@ +/* + * 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 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + */ + +/* + * Windows to Solaris Identity Mapping kernel API + * This header defines an API to map Windows SIDs to + * Solaris UID and GIDs and versa visa. + */ + +#ifndef _SYS_KIDMAP_H +#define _SYS_KIDMAP_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The ifdef's for these two accomodate duplicate definitions in + * lib/libidmap/common/idmap.h (the real one). In this code we + * simulate a kernel environment in user space using the real + * idmap library, so need to be able to use both headers. + */ + +/* Return status */ +#ifndef _IDMAP_STAT_TYPE +#define _IDMAP_STAT_TYPE +typedef int32_t idmap_stat; +#endif /* _IDMAP_STAT_TYPE */ + +/* Opaque get handle */ +#ifndef _IDMAP_GET_HANDLE_T +#define _IDMAP_GET_HANDLE_T +typedef struct idmap_get_handle idmap_get_handle_t; +#endif /* _IDMAP_GET_HANDLE_T */ + +/* + * In all the routines a Windows SID is handled as a + * string SID prefix plus a RID. For example + * + * S-1-5-5-12-34-568 will be passed as SID prefix + * S-1-5-5-12-34 and RID 568 + * + * Certain routines returns pointers to a SID prefix string. + * These strings are stored internally and should not be modified + * or freed. + */ + + +/* + * The following routines are simple get ID mapping routines. + */ + + +idmap_stat +kidmap_getuidbysid(zone_t *zone, const char *sid_prefix, uint32_t rid, + uid_t *uid); + +idmap_stat +kidmap_getgidbysid(zone_t *zone, const char *sid_prefix, uint32_t rid, + gid_t *gid); + +idmap_stat +kidmap_getpidbysid(zone_t *zone, const char *sid_prefix, uint32_t rid, + uid_t *pid, int *is_user); + +idmap_stat +kidmap_getsidbyuid(zone_t *zone, uid_t uid, const char **sid_prefix, + uint32_t *rid); + +idmap_stat +kidmap_getsidbygid(zone_t *zone, gid_t gid, const char **sid_prefix, + uint32_t *rid); + + + +/* + * The following routines provide a batch interface for mapping IDs. + */ + +/* + * Create a batch "get mapping" handle for batch mappings. + */ +idmap_get_handle_t * +kidmap_get_create(zone_t *zone); + +/* + * These routines queue the request to the "get mapping" handle + */ + +idmap_stat +kidmap_batch_getuidbysid(idmap_get_handle_t *get_handle, + const char *sid_prefix, uint32_t rid, + uid_t *uid, idmap_stat *stat); + +idmap_stat +kidmap_batch_getgidbysid(idmap_get_handle_t *get_handle, + const char *sid_prefix, uint32_t rid, + gid_t *gid, idmap_stat *stat); + +idmap_stat +kidmap_batch_getpidbysid(idmap_get_handle_t *get_handle, + const char *sid_prefix, uint32_t rid, + uid_t *pid, int *is_user, idmap_stat *stat); + +idmap_stat +kidmap_batch_getsidbyuid(idmap_get_handle_t *get_handle, uid_t uid, + const char **sid_prefix, uint32_t *rid, idmap_stat *stat); + +idmap_stat +kidmap_batch_getsidbygid(idmap_get_handle_t *get_handle, gid_t gid, + const char **sid_prefix, uint32_t *rid, idmap_stat *stat); + +/* + * Process the queued "get mapping" requests. The results (i.e. + * status and identity) will be available in the data areas + * provided by individual requests. + */ +idmap_stat +kidmap_get_mappings(idmap_get_handle_t *get_handle); + +/* + * Destroy the "get mapping" handle + */ +void +kidmap_get_destroy(idmap_get_handle_t *get_handle); + +#ifdef _KERNEL +/* + * Functions that do the hard part of door registration/unregistration + * for the idmap_reg()/idmap_unreg() syscalls + */ +int idmap_reg_dh(zone_t *zone, door_handle_t dh); +int idmap_unreg_dh(zone_t *zone, door_handle_t dh); + +/* + * Function needed by allocids() to ensure only the daemon that owns + * the door gets ephemeral IDS + */ +door_handle_t idmap_get_door(zone_t *zone); + +/* + * Function used by system call allocids() to purge the + * ID mapping cache + */ +void idmap_purge_cache(zone_t *zone); + +#endif /* _KERNEL */ + + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_KIDMAP_H */ diff --git a/usr/src/lib/smbclnt/libfknsmb/common/sys/policy.h b/usr/src/lib/smbclnt/libfknsmb/common/sys/policy.h new file mode 100644 index 0000000000..7ca0d9c3fa --- /dev/null +++ b/usr/src/lib/smbclnt/libfknsmb/common/sys/policy.h @@ -0,0 +1,50 @@ +/* + * 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 (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2015, Joyent, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + */ + +#ifndef _SYS_POLICY_H +#define _SYS_POLICY_H + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int secpolicy_fs_allowed_mount(const char *); +int secpolicy_vnode_owner(const cred_t *, uid_t); +int secpolicy_vnode_access2(const cred_t *, vnode_t *, uid_t, mode_t, mode_t); +int secpolicy_vnode_setattr(cred_t *, struct vnode *, struct vattr *, + const struct vattr *, int, int (void *, int, cred_t *), void *); +int secpolicy_vnode_setdac(const cred_t *, uid_t); + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_POLICY_H */ diff --git a/usr/src/lib/smbclnt/libfknsmb/common/sys/sdt.h b/usr/src/lib/smbclnt/libfknsmb/common/sys/sdt.h new file mode 100644 index 0000000000..c79ea68cec --- /dev/null +++ b/usr/src/lib/smbclnt/libfknsmb/common/sys/sdt.h @@ -0,0 +1,70 @@ +/* + * 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 (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013 by Delphix. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + */ + +#ifndef _SYS_SDT_H +#define _SYS_SDT_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * DTrace SDT probes have different signatures in userland than they do in + * kernel. If we're compiling for user mode (libfksmbsrv) define them as + * either no-op (for the SMB dtrace provider) or libfksmbsrv functions for + * the other SDT probe sites. + */ +#ifndef _KERNEL + +extern void smb_dtrace1(const char *, long); +extern void smb_dtrace2(const char *, long, long); +extern void smb_dtrace3(const char *, long, long, long); + +/* + * These are for the few (specialized) dtrace SDT probes sprinkled + * through the smbclnt code. In libfknsmb map these to functions. + */ + +#undef DTRACE_PROBE1 +#define DTRACE_PROBE1(n, t1, a1) \ + smb_dtrace1(#n, (long)a1) + +#undef DTRACE_PROBE2 +#define DTRACE_PROBE2(n, t1, a1, t2, a2) \ + smb_dtrace2(#n, (long)a1, (long)a2) + +#undef DTRACE_PROBE3 +#define DTRACE_PROBE3(n, t1, a1, t2, a2, t3, a3) \ + smb_dtrace3(#n, (long)a1, (long)a2, (long)a3) + +#endif /* _KERNEL */ + +#ifdef __cplusplus +} +#endif +#endif /* _SYS_SDT_H */ diff --git a/usr/src/lib/smbclnt/libfknsmb/common/sys/strft.h b/usr/src/lib/smbclnt/libfknsmb/common/sys/strft.h new file mode 100644 index 0000000000..a293118e9d --- /dev/null +++ b/usr/src/lib/smbclnt/libfknsmb/common/sys/strft.h @@ -0,0 +1,65 @@ +/* + * 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. + * + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + */ + +#ifndef _SYS_STRFT_H +#define _SYS_STRFT_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +#define FTEV_ALLOCB 0x0000 +#define FTEV_ESBALLOC 0x0001 +#define FTEV_DESBALLOC 0x0002 +#define FTEV_ESBALLOCA 0x0003 +#define FTEV_DESBALLOCA 0x0004 +#define FTEV_ALLOCBIG 0x0005 +#define FTEV_ALLOCBW 0x0006 +#define FTEV_BCALLOCB 0x0007 +#define FTEV_FREEB 0x0008 +#define FTEV_DUPB 0x0009 +#define FTEV_COPYB 0x000A + +#define STR_FTALLOC(hpp, e, d) \ + DTRACE_PROBE3(str__ftalloc, void *, hpp, ushort_t, e, ushort_t, d) + +/* Skip the 2nd arg (p) which is: caller() */ +#define STR_FTEVENT_MBLK(mp, p, e, d) \ + DTRACE_PROBE3(str__ftevent, void *, mp, ushort_t, e, ushort_t, d) + +#define str_ftfree(dbp) ((void)(dbp)) + +extern int str_ftnever, str_ftstack; + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_STRFT_H */ diff --git a/usr/src/lib/smbclnt/libfknsmb/common/sys/sunddi.h b/usr/src/lib/smbclnt/libfknsmb/common/sys/sunddi.h new file mode 100644 index 0000000000..f901e79566 --- /dev/null +++ b/usr/src/lib/smbclnt/libfknsmb/common/sys/sunddi.h @@ -0,0 +1,141 @@ +/* + * 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 (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + */ + +#ifndef _SYS_SUNDDI_H +#define _SYS_SUNDDI_H + +/* + * Sun Specific DDI definitions (fakekernel version) + * The real sunddi.h has become a "kitchen sink" full of + * includes we don't want, and lots of places include it. + * Rather than fight that battle now, provide this one + * with just the str*, mem*, and kiconv* functions. + * Some day, re-factor: sunddi.h, systm.h + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define DDI_SUCCESS (0) /* successful return */ +#define DDI_FAILURE (-1) /* unsuccessful return */ + +#if defined(_KERNEL) || defined(_FAKE_KERNEL) + +extern char *ddi_strdup(const char *str, int flag); +extern char *strdup(const char *str); +extern void strfree(char *str); + +extern size_t strlen(const char *) __PURE; +extern size_t strnlen(const char *, size_t) __PURE; +extern char *strcpy(char *, const char *); +extern char *strncpy(char *, const char *, size_t); + +/* Need to be consistent with C++ definition for strchr() */ +#if __cplusplus >= 199711L +extern const char *strchr(const char *, int); +#else +extern char *strchr(const char *, int); +#endif /* __cplusplus >= 199711L */ + +#define DDI_STRSAME(s1, s2) ((*(s1) == *(s2)) && (strcmp((s1), (s2)) == 0)) +extern int strcmp(const char *, const char *) __PURE; +extern int strncmp(const char *, const char *, size_t) __PURE; +extern char *strncat(char *, const char *, size_t); +extern size_t strlcat(char *, const char *, size_t); +extern size_t strlcpy(char *, const char *, size_t); +extern size_t strspn(const char *, const char *); +extern size_t strcspn(const char *, const char *); +extern int bcmp(const void *, const void *, size_t) __PURE; +extern int stoi(char **); +extern void numtos(ulong_t, char *); +extern void bcopy(const void *, void *, size_t); +extern void bzero(void *, size_t); + +extern void *memcpy(void *, const void *, size_t); +extern void *memset(void *, int, size_t); +extern void *memmove(void *, const void *, size_t); +extern int memcmp(const void *, const void *, size_t) __PURE; + +/* Need to be consistent with C++ definition for memchr() */ +#if __cplusplus >= 199711L +extern const void *memchr(const void *, int, size_t); +#else +extern void *memchr(const void *, int, size_t); +#endif /* __cplusplus >= 199711L */ + +extern int ddi_strtol(const char *, char **, int, long *); +extern int ddi_strtoul(const char *, char **, int, unsigned long *); +extern int ddi_strtoll(const char *, char **, int, longlong_t *); +extern int ddi_strtoull(const char *, char **, int, u_longlong_t *); + +extern int ddi_copyin(const void *, void *, size_t, int); +extern int ddi_copyout(const void *, void *, size_t, int); + +/* + * kiconv functions and their macros. + */ +#define KICONV_IGNORE_NULL (0x0001) +#define KICONV_REPLACE_INVALID (0x0002) + +extern kiconv_t kiconv_open(const char *, const char *); +extern size_t kiconv(kiconv_t, char **, size_t *, char **, size_t *, int *); +extern int kiconv_close(kiconv_t); +extern size_t kiconvstr(const char *, const char *, char *, size_t *, char *, + size_t *, int, int *); + +int +ddi_soft_state_init(void **state_p, size_t size, size_t n_items); +int +ddi_soft_state_zalloc(void *state, int item); +void * +ddi_get_soft_state(void *state, int item); +void +ddi_soft_state_free(void *state, int item); +void +ddi_soft_state_fini(void **state_p); + + +#endif /* _KERNEL */ + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_SUNDDI_H */ diff --git a/usr/src/lib/smbclnt/libfknsmb/common/sys/vfs.h b/usr/src/lib/smbclnt/libfknsmb/common/sys/vfs.h new file mode 100644 index 0000000000..9906f94a12 --- /dev/null +++ b/usr/src/lib/smbclnt/libfknsmb/common/sys/vfs.h @@ -0,0 +1,622 @@ +/* + * 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 (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2016 Toomas Soome + * Copyright (c) 2016, 2017 by Delphix. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. + */ + +/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ +/* All Rights Reserved */ + +/* + * Portions of this source code were derived from Berkeley 4.3 BSD + * under license from the Regents of the University of California. + */ + +#ifndef _SYS_VFS_H +#define _SYS_VFS_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Data associated with mounted file systems. + */ + +/* + * Operations vector. This is used internal to the kernel; file systems + * supply their list of operations via vfs_setfsops(). + */ + +typedef struct vfsops vfsops_t; + +/* + * File system identifier. Should be unique (at least per machine). + */ +typedef struct { + int val[2]; /* file system id type */ +} fsid_t; + +/* + * File identifier. Should be unique per filesystem on a single + * machine. This is typically called by a stateless file server + * in order to generate "file handles". + * + * Many underlying file systems cast a struct fid into other + * file system dependent structures which may require 4 byte alignment. + * Because a fid starts with a short it may not be 4 byte aligned, the + * fid_pad will force the alignment. + */ +#define MAXFIDSZ 64 +#define OLD_MAXFIDSZ 16 + +typedef struct fid { + union { + long fid_pad; + struct { + ushort_t len; /* length of data in bytes */ + char data[MAXFIDSZ]; /* data (variable len) */ + } _fid; + } un; +} fid_t; + +#ifdef _SYSCALL32 +/* + * Solaris 64 - use old-style cache format with 32-bit aligned fid for on-disk + * struct compatibility. + */ +typedef struct fid32 { + union { + int32_t fid_pad; + struct { + uint16_t len; /* length of data in bytes */ + char data[MAXFIDSZ]; /* data (variable len) */ + } _fid; + } un; +} fid32_t; +#else /* not _SYSCALL32 */ +#define fid32 fid +typedef fid_t fid32_t; +#endif /* _SYSCALL32 */ + +#define fid_len un._fid.len +#define fid_data un._fid.data + +/* + * Structure defining a mount option for a filesystem. + * option names are found in mntent.h + */ +typedef struct mntopt { + char *mo_name; /* option name */ + char **mo_cancel; /* list of options cancelled by this one */ + char *mo_arg; /* argument string for this option */ + int mo_flags; /* flags for this mount option */ + void *mo_data; /* filesystem specific data */ +} mntopt_t; + +/* + * Flags that apply to mount options + */ + +#define MO_SET 0x01 /* option is set */ +#define MO_NODISPLAY 0x02 /* option not listed in mnttab */ +#define MO_HASVALUE 0x04 /* option takes a value */ +#define MO_IGNORE 0x08 /* option ignored by parser */ +#define MO_DEFAULT MO_SET /* option is on by default */ +#define MO_TAG 0x10 /* flags a tag set by user program */ +#define MO_EMPTY 0x20 /* empty space in option table */ + +#define VFS_NOFORCEOPT 0x01 /* honor MO_IGNORE (don't set option) */ +#define VFS_DISPLAY 0x02 /* Turn off MO_NODISPLAY bit for opt */ +#define VFS_NODISPLAY 0x04 /* Turn on MO_NODISPLAY bit for opt */ +#define VFS_CREATEOPT 0x08 /* Create the opt if it's not there */ + +/* + * Structure holding mount option strings for the mounted file system. + */ +typedef struct mntopts { + uint_t mo_count; /* number of entries in table */ + mntopt_t *mo_list; /* list of mount options */ +} mntopts_t; + +/* + * The kstat structures associated with the vopstats are kept in an + * AVL tree. This is to avoid the case where a file system does not + * use a unique fsid_t for each vfs (e.g., namefs). In order to do + * this, we need a structure that the AVL tree can use that also + * references the kstat. + * Note that the vks_fsid is generated from the value reported by + * VFS_STATVFS(). + */ +typedef struct vskstat_anchor vsk_anchor_t; + +extern avl_tree_t vskstat_tree; +extern kmutex_t vskstat_tree_lock; + +#if defined(_KERNEL) || defined(_FAKE_KERNEL) +/* + * Structure per mounted file system. Each mounted file system has + * an array of operations and an instance record. + * + * The file systems are kept on a doubly linked circular list headed by + * "rootvfs". + * File system implementations should not access this list; + * it's intended for use only in the kernel's vfs layer. + * + * Each zone also has its own list of mounts, containing filesystems mounted + * somewhere within the filesystem tree rooted at the zone's rootpath. The + * list is doubly linked to match the global list. + * + * mnttab locking: the in-kernel mnttab uses the vfs_mntpt, vfs_resource and + * vfs_mntopts fields in the vfs_t. mntpt and resource are refstr_ts that + * are set at mount time and can only be modified during a remount. + * It is safe to read these fields if you can prevent a remount on the vfs, + * or through the convenience funcs vfs_getmntpoint() and vfs_getresource(). + * The mntopts field may only be accessed through the provided convenience + * functions, as it is protected by the vfs list lock. Modifying a mount + * option requires grabbing the vfs list write lock, which can be a very + * high latency lock. + */ +struct zone; /* from zone.h */ +struct fem_head; /* from fem.h */ + +typedef struct vfs { + struct vfs *vfs_next; /* next VFS in VFS list */ + struct vfs *vfs_prev; /* prev VFS in VFS list */ + +/* vfs_op should not be used directly. Accessor functions are provided */ + vfsops_t *vfs_op; /* operations on VFS */ + + struct vnode *vfs_vnodecovered; /* vnode mounted on */ + uint_t vfs_flag; /* flags */ + uint_t vfs_bsize; /* native block size */ + int vfs_fstype; /* file system type index */ + fsid_t vfs_fsid; /* file system id */ + void *vfs_data; /* private data */ + dev_t vfs_dev; /* device of mounted VFS */ + ulong_t vfs_bcount; /* I/O count (accounting) */ + struct vfs *vfs_list; /* sync list pointer */ + struct vfs *vfs_hash; /* hash list pointer */ + ksema_t vfs_reflock; /* mount/unmount/sync lock */ + uint_t vfs_count; /* vfs reference count */ + mntopts_t vfs_mntopts; /* options mounted with */ + refstr_t *vfs_resource; /* mounted resource name */ + refstr_t *vfs_mntpt; /* mount point name */ + time_t vfs_mtime; /* time we were mounted */ + struct vfs_impl *vfs_implp; /* impl specific data */ + /* + * Zones support. Note that the zone that "owns" the mount isn't + * necessarily the same as the zone in which the zone is visible. + * That is, vfs_zone and (vfs_zone_next|vfs_zone_prev) may refer to + * different zones. + */ + struct zone *vfs_zone; /* zone that owns the mount */ + struct vfs *vfs_zone_next; /* next VFS visible in zone */ + struct vfs *vfs_zone_prev; /* prev VFS visible in zone */ + + struct fem_head *vfs_femhead; /* fs monitoring */ + uint32_t vfs_lofi_id; /* ID if lofi mount */ +} vfs_t; + +#define vfs_featureset vfs_implp->vi_featureset +#define vfs_vskap vfs_implp->vi_vskap +#define vfs_fstypevsp vfs_implp->vi_fstypevsp +#define vfs_vopstats vfs_implp->vi_vopstats +#define vfs_hrctime vfs_implp->vi_hrctime + +#else // defined(_KERNEL) || defined(_FAKE_KERNEL) + +typedef struct vfs vfs_t; + +#endif // defined(_KERNEL) || defined(_FAKE_KERNEL) + +/* + * VFS flags. + */ +#define VFS_RDONLY 0x01 /* read-only vfs */ +#define VFS_NOMNTTAB 0x02 /* vfs not seen in mnttab */ +#define VFS_NOSETUID 0x08 /* setuid disallowed */ +#define VFS_REMOUNT 0x10 /* modify mount options only */ +#define VFS_NOTRUNC 0x20 /* does not truncate long file names */ +#define VFS_UNLINKABLE 0x40 /* unlink(2) can be applied to root */ +#define VFS_PXFS 0x80 /* clustering: global fs proxy vfs */ +#define VFS_UNMOUNTED 0x100 /* file system has been unmounted */ +#define VFS_NBMAND 0x200 /* allow non-blocking mandatory locks */ +#define VFS_XATTR 0x400 /* fs supports extended attributes */ +#define VFS_NODEVICES 0x800 /* device-special files disallowed */ +#define VFS_NOEXEC 0x1000 /* executables disallowed */ +#define VFS_STATS 0x2000 /* file system can collect stats */ +#define VFS_XID 0x4000 /* file system supports extended ids */ + +#define VFS_NORESOURCE "unspecified_resource" +#define VFS_NOMNTPT "unspecified_mountpoint" + +/* + * VFS features are implemented as bits set in the vfs_t. + * The vfs_feature_t typedef is a 64-bit number that will translate + * into an element in an array of bitmaps and a bit in that element. + * Developers must not depend on the implementation of this and + * need to use vfs_has_feature()/vfs_set_feature() routines. + */ +typedef uint64_t vfs_feature_t; + +#define VFSFT_XVATTR 0x100000001 /* Supports xvattr for attrs */ +#define VFSFT_CASEINSENSITIVE 0x100000002 /* Supports case-insensitive */ +#define VFSFT_NOCASESENSITIVE 0x100000004 /* NOT case-sensitive */ +#define VFSFT_DIRENTFLAGS 0x100000008 /* Supports dirent flags */ +#define VFSFT_ACLONCREATE 0x100000010 /* Supports ACL on create */ +#define VFSFT_ACEMASKONACCESS 0x100000020 /* Can use ACEMASK for access */ +#define VFSFT_SYSATTR_VIEWS 0x100000040 /* Supports sysattr view i/f */ +#define VFSFT_ACCESS_FILTER 0x100000080 /* dirents filtered by access */ +#define VFSFT_REPARSE 0x100000100 /* Supports reparse point */ +#define VFSFT_ZEROCOPY_SUPPORTED 0x100000200 + /* Support loaning /returning cache buffer */ +/* + * Argument structure for mount(2). + * + * Flags are defined in . + * + * Note that if the MS_SYSSPACE bit is set in flags, the pointer fields in + * this structure are to be interpreted as kernel addresses. File systems + * should be prepared for this possibility. + */ +struct mounta { + char *spec; + char *dir; + int flags; + char *fstype; + char *dataptr; + int datalen; + char *optptr; + int optlen; +}; + +/* + * Reasons for calling the vfs_mountroot() operation. + */ +enum whymountroot { ROOT_INIT, ROOT_REMOUNT, ROOT_UNMOUNT}; +typedef enum whymountroot whymountroot_t; + +/* + * Reasons for calling the VFS_VNSTATE(): + */ +enum vntrans { + VNTRANS_EXISTS, + VNTRANS_IDLED, + VNTRANS_RECLAIMED, + VNTRANS_DESTROYED +}; +typedef enum vntrans vntrans_t; + +/* + * VFS_OPS defines all the vfs operations. It is used to define + * the vfsops structure (below) and the fs_func_p union (vfs_opreg.h). + */ +#define VFS_OPS \ + int (*vfs_mount)(vfs_t *, vnode_t *, struct mounta *, cred_t *); \ + int (*vfs_unmount)(vfs_t *, int, cred_t *); \ + int (*vfs_root)(vfs_t *, vnode_t **); \ + int (*vfs_statvfs)(vfs_t *, statvfs64_t *); \ + int (*vfs_sync)(vfs_t *, short, cred_t *); \ + int (*vfs_vget)(vfs_t *, vnode_t **, fid_t *); \ + int (*vfs_mountroot)(vfs_t *, enum whymountroot); \ + void (*vfs_freevfs)(vfs_t *); \ + int (*vfs_vnstate)(vfs_t *, vnode_t *, vntrans_t) /* NB: No ";" */ + +/* + * Operations supported on virtual file system. + */ +struct vfsops { + VFS_OPS; /* Signature of all vfs operations (vfsops) */ +}; + +extern int fsop_mount(vfs_t *, vnode_t *, struct mounta *, cred_t *); +extern int fsop_unmount(vfs_t *, int, cred_t *); +extern int fsop_root(vfs_t *, vnode_t **); +extern int fsop_statfs(vfs_t *, statvfs64_t *); +extern int fsop_sync(vfs_t *, short, cred_t *); +extern int fsop_vget(vfs_t *, vnode_t **, fid_t *); +extern int fsop_mountroot(vfs_t *, enum whymountroot); +extern void fsop_freefs(vfs_t *); +extern int fsop_sync_by_kind(int, short, cred_t *); +extern int fsop_vnstate(vfs_t *, vnode_t *, vntrans_t); + +#define VFS_MOUNT(vfsp, mvp, uap, cr) fsop_mount(vfsp, mvp, uap, cr) +#define VFS_UNMOUNT(vfsp, flag, cr) fsop_unmount(vfsp, flag, cr) +#define VFS_ROOT(vfsp, vpp) fsop_root(vfsp, vpp) +#define VFS_STATVFS(vfsp, sp) fsop_statfs(vfsp, sp) +#define VFS_SYNC(vfsp, flag, cr) fsop_sync(vfsp, flag, cr) +#define VFS_VGET(vfsp, vpp, fidp) fsop_vget(vfsp, vpp, fidp) +#define VFS_MOUNTROOT(vfsp, init) fsop_mountroot(vfsp, init) +#define VFS_FREEVFS(vfsp) fsop_freefs(vfsp) +#define VFS_VNSTATE(vfsp, vn, ns) fsop_vnstate(vfsp, vn, ns) + +#define VFSNAME_MOUNT "mount" +#define VFSNAME_UNMOUNT "unmount" +#define VFSNAME_ROOT "root" +#define VFSNAME_STATVFS "statvfs" +#define VFSNAME_SYNC "sync" +#define VFSNAME_VGET "vget" +#define VFSNAME_MOUNTROOT "mountroot" +#define VFSNAME_FREEVFS "freevfs" +#define VFSNAME_VNSTATE "vnstate" +/* + * Filesystem type switch table. + */ + +typedef struct vfssw { + char *vsw_name; /* type name -- max len _ST_FSTYPSZ */ + int (*vsw_init) (int, char *); + /* init routine (for non-loadable fs only) */ + int vsw_flag; /* flags */ + mntopts_t vsw_optproto; /* mount options table prototype */ + uint_t vsw_count; /* count of references */ + kmutex_t vsw_lock; /* lock to protect vsw_count */ + vfsops_t vsw_vfsops; /* filesystem operations vector */ +} vfssw_t; + +/* + * Filesystem type definition record. All file systems must export a record + * of this type through their modlfs structure. N.B., changing the version + * number requires a change in sys/modctl.h. + */ + +typedef struct vfsdef_v5 { + int def_version; /* structure version, must be first */ + char *name; /* filesystem type name */ + int (*init) (int, char *); /* init routine */ + int flags; /* filesystem flags */ + mntopts_t *optproto; /* mount options table prototype */ +} vfsdef_v5; + +typedef struct vfsdef_v5 vfsdef_t; + +enum { + VFSDEF_VERSION = 5 +}; + +/* Specific to libfksmbfs */ +int fake_installfs(vfsdef_t *); +int fake_removefs(vfsdef_t *); + +/* + * flags for vfssw and vfsdef + */ +#define VSW_HASPROTO 0x01 /* struct has a mount options prototype */ +#define VSW_CANRWRO 0x02 /* file system can transition from rw to ro */ +#define VSW_CANREMOUNT 0x04 /* file system supports remounts */ +#define VSW_NOTZONESAFE 0x08 /* zone_enter(2) should fail for these files */ +#define VSW_VOLATILEDEV 0x10 /* vfs_dev can change each time fs is mounted */ +#define VSW_STATS 0x20 /* file system can collect stats */ +#define VSW_XID 0x40 /* file system supports extended ids */ +#define VSW_CANLOFI 0x80 /* file system supports lofi mounts */ +#define VSW_ZMOUNT 0x100 /* file system always allowed in a zone */ +#define VSW_MOUNTDEV 0x200 /* file system is mounted via device path */ + +#define VSW_INSTALLED 0x8000 /* this vsw is associated with a file system */ + +/* + * A flag for vfs_setpath(). + */ +#define VFSSP_VERBATIM 0x1 /* do not prefix the supplied path */ + +#if defined(_KERNEL) || defined(_FAKE_KERNEL) + +/* + * Private vfs data, NOT to be used by a file system implementation. + */ + +#define VFS_FEATURE_MAXSZ 4 + +typedef struct vfs_impl { + /* Counted array - Bitmap of vfs features */ + uint32_t vi_featureset[VFS_FEATURE_MAXSZ]; + /* + * Support for statistics on the vnode operations + */ + vsk_anchor_t *vi_vskap; /* anchor for vopstats' kstat */ + vopstats_t *vi_fstypevsp; /* ptr to per-fstype vopstats */ + vopstats_t vi_vopstats; /* per-mount vnode op stats */ + + timespec_t vi_hrctime; /* High-res creation time */ + + zone_ref_t vi_zone_ref; /* reference to zone */ +} vfs_impl_t; + +/* + * Public operations. + */ +struct umounta; +struct statvfsa; +struct fstatvfsa; + +void vfs_freevfsops(vfsops_t *); +int vfs_freevfsops_by_type(int); +void vfs_setops(vfs_t *, vfsops_t *); +vfsops_t *vfs_getops(vfs_t *vfsp); +int vfs_matchops(vfs_t *, vfsops_t *); +int vfs_can_sync(vfs_t *vfsp); +vfs_t *vfs_alloc(int); +void vfs_free(vfs_t *); +void vfs_init(vfs_t *vfsp, vfsops_t *, void *); +void vfsimpl_setup(vfs_t *vfsp); +void vfsimpl_teardown(vfs_t *vfsp); +void vn_exists(vnode_t *); +void vn_idle(vnode_t *); +void vn_reclaim(vnode_t *); +void vn_invalid(vnode_t *); + +int rootconf(void); +int domount(char *, struct mounta *, vnode_t *, struct cred *, + struct vfs **); +int dounmount(struct vfs *, int, cred_t *); +int vfs_lock(struct vfs *); +int vfs_rlock(struct vfs *); +void vfs_lock_wait(struct vfs *); +void vfs_rlock_wait(struct vfs *); +void vfs_unlock(struct vfs *); +int vfs_lock_held(struct vfs *); +struct _kthread *vfs_lock_owner(struct vfs *); +void sync(void); +void vfs_sync(int); +void vfs_mountroot(void); +void vfs_add(vnode_t *, struct vfs *, int); +void vfs_remove(struct vfs *); + +/* VFS feature routines */ +void vfs_set_feature(vfs_t *, vfs_feature_t); +void vfs_clear_feature(vfs_t *, vfs_feature_t); +int vfs_has_feature(vfs_t *, vfs_feature_t); +void vfs_propagate_features(vfs_t *, vfs_t *); + +/* The following functions are not for general use by filesystems */ + +void vfs_createopttbl(mntopts_t *, const char *); +void vfs_copyopttbl(const mntopts_t *, mntopts_t *); +void vfs_mergeopttbl(const mntopts_t *, const mntopts_t *, mntopts_t *); +void vfs_freeopttbl(mntopts_t *); +void vfs_parsemntopts(mntopts_t *, char *, int); +int vfs_buildoptionstr(const mntopts_t *, char *, int); +struct mntopt *vfs_hasopt(const mntopts_t *, const char *); +void vfs_mnttab_modtimeupd(void); + +void vfs_clearmntopt(struct vfs *, const char *); +void vfs_setmntopt(struct vfs *, const char *, const char *, int); +void vfs_setresource(struct vfs *, const char *, uint32_t); +void vfs_setmntpoint(struct vfs *, const char *, uint32_t); +refstr_t *vfs_getresource(const struct vfs *); +refstr_t *vfs_getmntpoint(const struct vfs *); +int vfs_optionisset(const struct vfs *, const char *, char **); +int vfs_settag(uint_t, uint_t, const char *, const char *, cred_t *); +int vfs_clrtag(uint_t, uint_t, const char *, const char *, cred_t *); +void vfs_syncall(void); +void vfsinit(void); +void vfs_unmountall(void); +void vfs_make_fsid(fsid_t *, dev_t, int); +void vfs_addmip(dev_t, struct vfs *); +void vfs_delmip(struct vfs *); +int vfs_devismounted(dev_t); +int vfs_devmounting(dev_t, struct vfs *); +int vfs_opsinuse(vfsops_t *); +struct vfs *getvfs(fsid_t *); +struct vfs *vfs_dev2vfsp(dev_t); +struct vfs *vfs_mntpoint2vfsp(const char *); +struct vfssw *allocate_vfssw(const char *); +struct vfssw *vfs_getvfssw(const char *); +struct vfssw *vfs_getvfsswbyname(const char *); +struct vfssw *vfs_getvfsswbyvfsops(vfsops_t *); +void vfs_refvfssw(struct vfssw *); +void vfs_unrefvfssw(struct vfssw *); +uint_t vf_to_stf(uint_t); +void vfs_mnttab_modtime(timespec_t *); +void vfs_mnttab_poll(timespec_t *, struct pollhead **); + +void vfs_list_lock(void); +void vfs_list_read_lock(void); +void vfs_list_unlock(void); +void vfs_list_add(struct vfs *); +void vfs_list_remove(struct vfs *); +void vfs_hold(vfs_t *vfsp); +void vfs_rele(vfs_t *vfsp); +void fs_freevfs(vfs_t *); +void vfs_root_redev(vfs_t *vfsp, dev_t ndev, int fstype); + +int vfs_zone_change_safe(vfs_t *); + +int vfs_get_lofi(vfs_t *, vnode_t **); + +#define VFSHASH(maj, min) (((int)((maj)+(min))) & (vfshsz - 1)) +#define VFS_ON_LIST(vfsp) \ + ((vfsp)->vfs_next != (vfsp) && (vfsp)->vfs_next != NULL) + +/* + * Globals. + */ + +extern struct vfssw vfssw[]; /* table of filesystem types */ +extern krwlock_t vfssw_lock; +extern char rootfstype[]; /* name of root fstype */ +extern const int nfstype; /* # of elements in vfssw array */ +extern vfsops_t *EIO_vfsops; /* operations for vfs being torn-down */ + +/* + * The following variables are private to the the kernel's vfs layer. File + * system implementations should not access them. + */ +extern struct vfs *rootvfs; /* ptr to root vfs structure */ +typedef struct { + struct vfs *rvfs_head; /* head vfs in chain */ + kmutex_t rvfs_lock; /* mutex protecting this chain */ + uint32_t rvfs_len; /* length of this chain */ +} rvfs_t; +extern rvfs_t *rvfs_list; +extern int vfshsz; /* # of elements in rvfs_head array */ +extern const mntopts_t vfs_mntopts; /* globally recognized options */ + +#endif /* defined(_KERNEL) */ + +#define VFS_HOLD(vfsp) { \ + vfs_hold(vfsp); \ +} + +#define VFS_RELE(vfsp) { \ + vfs_rele(vfsp); \ +} + +#define VFS_INIT(vfsp, op, data) { \ + vfs_init((vfsp), (op), (data)); \ +} + + +#define VFS_INSTALLED(vfsswp) (((vfsswp)->vsw_flag & VSW_INSTALLED) != 0) +#define ALLOCATED_VFSSW(vswp) ((vswp)->vsw_name[0] != '\0') +#define RLOCK_VFSSW() (rw_enter(&vfssw_lock, RW_READER)) +#define RUNLOCK_VFSSW() (rw_exit(&vfssw_lock)) +#define WLOCK_VFSSW() (rw_enter(&vfssw_lock, RW_WRITER)) +#define WUNLOCK_VFSSW() (rw_exit(&vfssw_lock)) +#define VFSSW_LOCKED() (RW_LOCK_HELD(&vfssw_lock)) +#define VFSSW_WRITE_LOCKED() (RW_WRITE_HELD(&vfssw_lock)) +/* + * VFS_SYNC flags. + */ +#define SYNC_ATTR 0x01 /* sync attributes only */ +#define SYNC_CLOSE 0x02 /* close open file */ +#define SYNC_ALL 0x04 /* force to sync all fs */ + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_VFS_H */ diff --git a/usr/src/lib/smbclnt/libfknsmb/common/sys/vfs_opreg.h b/usr/src/lib/smbclnt/libfknsmb/common/sys/vfs_opreg.h new file mode 100644 index 0000000000..cdb6c9c6c5 --- /dev/null +++ b/usr/src/lib/smbclnt/libfknsmb/common/sys/vfs_opreg.h @@ -0,0 +1,116 @@ +/* + * 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 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + */ + +#ifndef _SYS_VFS_OPREG_H +#define _SYS_VFS_OPREG_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(_KERNEL) || defined(_FAKE_KERNEL) + +/* + * The following union allows us to use C99's "designated initializer" + * feature so that we can have strong typechecking for the operations + * used in the the fs_operation_def structures. + */ + +typedef union fs_func { + fs_generic_func_p fs_generic; /* Generic function signature */ + int (*error)(); /* Signature of error function */ + VFS_OPS; /* Signatures of all vfs operations (vfsops) */ + VNODE_OPS; /* Signatures of all vnode operations (vops) */ + FEM_OPS; /* Signatures of all FEM operations (femops) */ + FSEM_OPS; /* Signatures of all FSEM ops (fsemops) */ +} fs_func_p; + +/* + * File systems use arrays of fs_operation_def structures to form + * name/value pairs of operations. These arrays get passed to: + * + * - vn_make_ops() to create vnodeops + * - vfs_makefsops()/vfs_setfsops() to create vfsops. + */ +typedef struct fs_operation_def { + char *name; /* name of operation (NULL at end) */ + fs_func_p func; /* function implementing operation */ +} fs_operation_def_t; + +/* + * The operation registration mechanism uses two master tables of operations: + * one for vnode operations (vn_ops_table[]) and one for vfs operations + * (vfs_ops_table[]). These tables are arrays of fs_operation_trans_def + * structures. They contain all of the information necessary for the system + * to populate an operations structure (e.g., vnodeops, vfsops). + * + * File systems call registration routines (vfs_setfsops(), vfs_makefsops(), + * and vn_make_ops()) and pass in their operations specification tables + * (arrays of fs_operation_def structures). These routines use the master + * table(s) of operations to build a vnodeops or vfsops structure. + */ +typedef struct fs_operation_trans_def { + char *name; /* name of operation (NULL at end) */ + int offset; /* byte offset within ops vector */ + fs_generic_func_p defaultFunc; /* default function */ + fs_generic_func_p errorFunc; /* error function */ +} fs_operation_trans_def_t; + +/* + * Generic operations vector types (used for vfs/vnode ops registration). + */ + +extern int fs_default(); /* "default" function placeholder */ +extern int fs_error(); /* "error" function placeholder */ + +int fs_build_vector(void *vector, int *unused_ops, + const fs_operation_trans_def_t *translation, + const fs_operation_def_t *operations); + +/* + * Public operations. + */ + +int vn_make_ops(const char *, const struct fs_operation_def *, + vnodeops_t **); +void vn_freevnodeops(vnodeops_t *); + +int vfs_setfsops(int, const fs_operation_def_t *, vfsops_t **); +int vfs_makefsops(const fs_operation_def_t *, vfsops_t **); +void vfs_freevfsops(vfsops_t *); +int vfs_freevfsops_by_type(int); + +#endif /* _KERNEL */ + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_VFS_OPREG_H */ diff --git a/usr/src/lib/smbclnt/libfknsmb/common/sys/vnode.h b/usr/src/lib/smbclnt/libfknsmb/common/sys/vnode.h new file mode 100644 index 0000000000..33e84e68f2 --- /dev/null +++ b/usr/src/lib/smbclnt/libfknsmb/common/sys/vnode.h @@ -0,0 +1,1452 @@ +/* + * 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 (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, Joyent, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + */ + +/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ +/* All Rights Reserved */ + +/* + * University Copyright- Copyright (c) 1982, 1986, 1988 + * The Regents of the University of California + * All Rights Reserved + * + * University Acknowledgment- Portions of this document are derived from + * software developed by the University of California, Berkeley, and its + * contributors. + */ + +#ifndef _SYS_VNODE_H +#define _SYS_VNODE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef _KERNEL +#include +#include +#endif /* _KERNEL */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(_KERNEL) || defined(_FAKE_KERNEL) + +/* + * Statistics for all vnode operations. + * All operations record number of ops (since boot/mount/zero'ed). + * Certain I/O operations (read, write, readdir) also record number + * of bytes transferred. + * This appears in two places in the system: one is embedded in each + * vfs_t. There is also an array of vopstats_t structures allocated + * on a per-fstype basis. + */ + +#define VOPSTATS_STR "vopstats_" /* Initial string for vopstat kstats */ + +typedef struct vopstats { + kstat_named_t nopen; /* VOP_OPEN */ + kstat_named_t nclose; /* VOP_CLOSE */ + kstat_named_t nread; /* VOP_READ */ + kstat_named_t read_bytes; + kstat_named_t nwrite; /* VOP_WRITE */ + kstat_named_t write_bytes; + kstat_named_t nioctl; /* VOP_IOCTL */ + kstat_named_t nsetfl; /* VOP_SETFL */ + kstat_named_t ngetattr; /* VOP_GETATTR */ + kstat_named_t nsetattr; /* VOP_SETATTR */ + kstat_named_t naccess; /* VOP_ACCESS */ + kstat_named_t nlookup; /* VOP_LOOKUP */ + kstat_named_t ncreate; /* VOP_CREATE */ + kstat_named_t nremove; /* VOP_REMOVE */ + kstat_named_t nlink; /* VOP_LINK */ + kstat_named_t nrename; /* VOP_RENAME */ + kstat_named_t nmkdir; /* VOP_MKDIR */ + kstat_named_t nrmdir; /* VOP_RMDIR */ + kstat_named_t nreaddir; /* VOP_READDIR */ + kstat_named_t readdir_bytes; + kstat_named_t nsymlink; /* VOP_SYMLINK */ + kstat_named_t nreadlink; /* VOP_READLINK */ + kstat_named_t nfsync; /* VOP_FSYNC */ + kstat_named_t ninactive; /* VOP_INACTIVE */ + kstat_named_t nfid; /* VOP_FID */ + kstat_named_t nrwlock; /* VOP_RWLOCK */ + kstat_named_t nrwunlock; /* VOP_RWUNLOCK */ + kstat_named_t nseek; /* VOP_SEEK */ + kstat_named_t ncmp; /* VOP_CMP */ + kstat_named_t nfrlock; /* VOP_FRLOCK */ + kstat_named_t nspace; /* VOP_SPACE */ + kstat_named_t nrealvp; /* VOP_REALVP */ + kstat_named_t ngetpage; /* VOP_GETPAGE */ + kstat_named_t nputpage; /* VOP_PUTPAGE */ + kstat_named_t nmap; /* VOP_MAP */ + kstat_named_t naddmap; /* VOP_ADDMAP */ + kstat_named_t ndelmap; /* VOP_DELMAP */ + kstat_named_t npoll; /* VOP_POLL */ + kstat_named_t ndump; /* VOP_DUMP */ + kstat_named_t npathconf; /* VOP_PATHCONF */ + kstat_named_t npageio; /* VOP_PAGEIO */ + kstat_named_t ndumpctl; /* VOP_DUMPCTL */ + kstat_named_t ndispose; /* VOP_DISPOSE */ + kstat_named_t nsetsecattr; /* VOP_SETSECATTR */ + kstat_named_t ngetsecattr; /* VOP_GETSECATTR */ + kstat_named_t nshrlock; /* VOP_SHRLOCK */ + kstat_named_t nvnevent; /* VOP_VNEVENT */ + kstat_named_t nreqzcbuf; /* VOP_REQZCBUF */ + kstat_named_t nretzcbuf; /* VOP_RETZCBUF */ +} vopstats_t; +#endif // defined(_KERNEL) || defined(_FAKE_KERNEL) + +/* + * The vnode is the focus of all file activity in UNIX. + * A vnode is allocated for each active file, each current + * directory, each mounted-on file, and the root. + * + * Each vnode is usually associated with a file-system-specific node (for + * UFS, this is the in-memory inode). Generally, a vnode and an fs-node + * should be created and destroyed together as a pair. + * + * If a vnode is reused for a new file, it should be reinitialized by calling + * either vn_reinit() or vn_recycle(). + * + * vn_reinit() resets the entire vnode as if it was returned by vn_alloc(). + * The caller is responsible for setting up the entire vnode after calling + * vn_reinit(). This is important when using kmem caching where the vnode is + * allocated by a constructor, for instance. + * + * vn_recycle() is used when the file system keeps some state around in both + * the vnode and the associated FS-node. In UFS, for example, the inode of + * a deleted file can be reused immediately. The v_data, v_vfsp, v_op, etc. + * remains the same but certain fields related to the previous instance need + * to be reset. In particular: + * v_femhead + * v_path + * v_rdcnt, v_wrcnt + * v_mmap_read, v_mmap_write + */ + +/* + * vnode types. VNON means no type. These values are unrelated to + * values in on-disk inodes. + */ +typedef enum vtype { + VNON = 0, + VREG = 1, + VDIR = 2, + VBLK = 3, + VCHR = 4, + VLNK = 5, + VFIFO = 6, + VDOOR = 7, + VPROC = 8, + VSOCK = 9, + VPORT = 10, + VBAD = 11 +} vtype_t; + +#if defined(_KERNEL) || defined(_FAKE_KERNEL) + +/* + * VSD - Vnode Specific Data + * Used to associate additional private data with a vnode. + */ +struct vsd_node { + list_node_t vs_nodes; /* list of all VSD nodes */ + uint_t vs_nkeys; /* entries in value array */ + void **vs_value; /* array of value/key */ +}; + +/* + * Many of the fields in the vnode are read-only once they are initialized + * at vnode creation time. Other fields are protected by locks. + * + * IMPORTANT: vnodes should be created ONLY by calls to vn_alloc(). They + * may not be embedded into the file-system specific node (inode). The + * size of vnodes may change. + * + * The v_lock protects: + * v_flag + * v_stream + * v_count + * v_shrlocks + * v_path + * v_vsd + * v_xattrdir + * + * A special lock (implemented by vn_vfswlock in vnode.c) protects: + * v_vfsmountedhere + * + * The global flock_lock mutex (in flock.c) protects: + * v_filocks + * + * IMPORTANT NOTE: + * + * The following vnode fields are considered public and may safely be + * accessed by file systems or other consumers: + * + * v_lock + * v_flag + * v_count + * v_data + * v_vfsp + * v_stream + * v_type + * v_rdev + * + * ALL OTHER FIELDS SHOULD BE ACCESSED ONLY BY THE OWNER OF THAT FIELD. + * In particular, file systems should not access other fields; they may + * change or even be removed. The functionality which was once provided + * by these fields is available through vn_* functions. + */ + +struct fem_head; /* from fem.h */ + +typedef struct vnode { + kmutex_t v_lock; /* protects vnode fields */ + uint_t v_flag; /* vnode flags (see below) */ + uint_t v_count; /* reference count */ + void *v_data; /* private data for fs */ + struct vfs *v_vfsp; /* ptr to containing VFS */ + struct stdata *v_stream; /* associated stream */ + enum vtype v_type; /* vnode type */ + dev_t v_rdev; /* device (VCHR, VBLK) */ + + /* PRIVATE FIELDS BELOW - DO NOT USE */ + + struct vfs *v_vfsmountedhere; /* ptr to vfs mounted here */ + struct vnodeops *v_op; /* vnode operations */ + krwlock_t v_nbllock; /* sync for NBMAND locks */ + char *v_path; /* cached path */ + uint_t v_rdcnt; /* open for read count (VREG only) */ + uint_t v_wrcnt; /* open for write count (VREG only) */ + struct vnode *v_xattrdir; /* unnamed extended attr dir (GFS) */ + + /* Private to the fake vnode impl. */ + + int v_fd; + dev_t v_st_dev; + ino_t v_st_ino; + avl_node_t v_avl_node; + int v_vfsrlocks; +} vnode_t; + +#define IS_DEVVP(vp) \ + ((vp)->v_type == VCHR || (vp)->v_type == VBLK || (vp)->v_type == VFIFO) + +#define VNODE_ALIGN 16 + +/* + * vnode flags. + */ +#define VROOT 0x01 /* root of its file system */ +#define VNOCACHE 0x02 /* don't keep cache pages on vnode */ +#define VNOMAP 0x04 /* file cannot be mapped/faulted */ +#define VDUP 0x08 /* file should be dup'ed rather then opened */ +#define VNOSWAP 0x10 /* file cannot be used as virtual swap device */ +#define VNOMOUNT 0x20 /* file cannot be covered by mount */ +#define VISSWAP 0x40 /* vnode is being used for swap */ +#define VSWAPLIKE 0x80 /* vnode acts like swap (but may not be) */ + +#define IS_SWAPVP(vp) (((vp)->v_flag & (VISSWAP | VSWAPLIKE)) != 0) + +#else // defined(_KERNEL) || defined(_FAKE_KERNEL) +typedef struct vnode vnode_t; +#endif // defined(_KERNEL) || defined(_FAKE_KERNEL) + +#if defined(_KERNEL) +typedef struct vn_vfslocks_entry { + rwstlock_t ve_lock; + void *ve_vpvfs; + struct vn_vfslocks_entry *ve_next; + uint32_t ve_refcnt; + char pad[64 - sizeof (rwstlock_t) - 2 * sizeof (void *) - \ + sizeof (uint32_t)]; +} vn_vfslocks_entry_t; +#endif /* _KERNEL */ + +/* + * The following two flags are used to lock the v_vfsmountedhere field + */ +#define VVFSLOCK 0x100 +#define VVFSWAIT 0x200 + +/* + * Used to serialize VM operations on a vnode + */ +#define VVMLOCK 0x400 + +/* + * Tell vn_open() not to fail a directory open for writing but + * to go ahead and call VOP_OPEN() to let the filesystem check. + */ +#define VDIROPEN 0x800 + +/* + * Flag to let the VM system know that this file is most likely a binary + * or shared library since it has been mmap()ed EXEC at some time. + */ +#define VVMEXEC 0x1000 + +#define VPXFS 0x2000 /* clustering: global fs proxy vnode */ + +#define IS_PXFSVP(vp) ((vp)->v_flag & VPXFS) + +#define V_XATTRDIR 0x4000 /* attribute unnamed directory */ + +#define IS_XATTRDIR(vp) ((vp)->v_flag & V_XATTRDIR) + +#define V_LOCALITY 0x8000 /* whether locality aware */ + +/* + * Flag that indicates the VM should maintain the v_pages list with all modified + * pages on one end and unmodified pages at the other. This makes finding dirty + * pages to write back to disk much faster at the expense of taking a minor + * fault on the first store instruction which touches a writable page. + */ +#define VMODSORT (0x10000) +#define IS_VMODSORT(vp) \ + (pvn_vmodsort_supported != 0 && ((vp)->v_flag & VMODSORT) != 0) + +#define VISSWAPFS 0x20000 /* vnode is being used for swapfs */ + +/* + * The mdb memstat command assumes that IS_SWAPFSVP only uses the + * vnode's v_flag field. If this changes, cache the additional + * fields in mdb; see vn_get in mdb/common/modules/genunix/memory.c + */ +#define IS_SWAPFSVP(vp) (((vp)->v_flag & VISSWAPFS) != 0) + +#define V_SYSATTR 0x40000 /* vnode is a GFS system attribute */ + +/* + * Vnode attributes. A bit-mask is supplied as part of the + * structure to indicate the attributes the caller wants to + * set (setattr) or extract (getattr). + */ + +/* + * Note that va_nodeid and va_nblocks are 64bit data type. + * We support large files over NFSV3. With Solaris client and + * Server that generates 64bit ino's and sizes these fields + * will overflow if they are 32 bit sizes. + */ + +typedef struct vattr { + uint_t va_mask; /* bit-mask of attributes */ + vtype_t va_type; /* vnode type (for create) */ + mode_t va_mode; /* file access mode */ + uid_t va_uid; /* owner user id */ + gid_t va_gid; /* owner group id */ + dev_t va_fsid; /* file system id (dev for now) */ + u_longlong_t va_nodeid; /* node id */ + nlink_t va_nlink; /* number of references to file */ + u_offset_t va_size; /* file size in bytes */ + timestruc_t va_atime; /* time of last access */ + timestruc_t va_mtime; /* time of last modification */ + timestruc_t va_ctime; /* time of last status change */ + dev_t va_rdev; /* device the file represents */ + uint_t va_blksize; /* fundamental block size */ + u_longlong_t va_nblocks; /* # of blocks allocated */ + uint_t va_seq; /* sequence number */ +} vattr_t; + +#define AV_SCANSTAMP_SZ 32 /* length of anti-virus scanstamp */ + +/* + * Structure of all optional attributes. + */ +typedef struct xoptattr { + timestruc_t xoa_createtime; /* Create time of file */ + uint8_t xoa_archive; + uint8_t xoa_system; + uint8_t xoa_readonly; + uint8_t xoa_hidden; + uint8_t xoa_nounlink; + uint8_t xoa_immutable; + uint8_t xoa_appendonly; + uint8_t xoa_nodump; + uint8_t xoa_opaque; + uint8_t xoa_av_quarantined; + uint8_t xoa_av_modified; + uint8_t xoa_av_scanstamp[AV_SCANSTAMP_SZ]; + uint8_t xoa_reparse; + uint64_t xoa_generation; + uint8_t xoa_offline; + uint8_t xoa_sparse; +} xoptattr_t; + +/* + * The xvattr structure is really a variable length structure that + * is made up of: + * - The classic vattr_t (xva_vattr) + * - a 32 bit quantity (xva_mapsize) that specifies the size of the + * attribute bitmaps in 32 bit words. + * - A pointer to the returned attribute bitmap (needed because the + * previous element, the requested attribute bitmap) is variable lenth. + * - The requested attribute bitmap, which is an array of 32 bit words. + * Callers use the XVA_SET_REQ() macro to set the bits corresponding to + * the attributes that are being requested. + * - The returned attribute bitmap, which is an array of 32 bit words. + * File systems that support optional attributes use the XVA_SET_RTN() + * macro to set the bits corresponding to the attributes that are being + * returned. + * - The xoptattr_t structure which contains the attribute values + * + * xva_mapsize determines how many words in the attribute bitmaps. + * Immediately following the attribute bitmaps is the xoptattr_t. + * xva_getxoptattr() is used to get the pointer to the xoptattr_t + * section. + */ + +#define XVA_MAPSIZE 3 /* Size of attr bitmaps */ +#define XVA_MAGIC 0x78766174 /* Magic # for verification */ + +/* + * The xvattr structure is an extensible structure which permits optional + * attributes to be requested/returned. File systems may or may not support + * optional attributes. They do so at their own discretion but if they do + * support optional attributes, they must register the VFSFT_XVATTR feature + * so that the optional attributes can be set/retrived. + * + * The fields of the xvattr structure are: + * + * xva_vattr - The first element of an xvattr is a legacy vattr structure + * which includes the common attributes. If AT_XVATTR is set in the va_mask + * then the entire structure is treated as an xvattr. If AT_XVATTR is not + * set, then only the xva_vattr structure can be used. + * + * xva_magic - 0x78766174 (hex for "xvat"). Magic number for verification. + * + * xva_mapsize - Size of requested and returned attribute bitmaps. + * + * xva_rtnattrmapp - Pointer to xva_rtnattrmap[]. We need this since the + * size of the array before it, xva_reqattrmap[], could change which means + * the location of xva_rtnattrmap[] could change. This will allow unbundled + * file systems to find the location of xva_rtnattrmap[] when the sizes change. + * + * xva_reqattrmap[] - Array of requested attributes. Attributes are + * represented by a specific bit in a specific element of the attribute + * map array. Callers set the bits corresponding to the attributes + * that the caller wants to get/set. + * + * xva_rtnattrmap[] - Array of attributes that the file system was able to + * process. Not all file systems support all optional attributes. This map + * informs the caller which attributes the underlying file system was able + * to set/get. (Same structure as the requested attributes array in terms + * of each attribute corresponding to specific bits and array elements.) + * + * xva_xoptattrs - Structure containing values of optional attributes. + * These values are only valid if the corresponding bits in xva_reqattrmap + * are set and the underlying file system supports those attributes. + */ +typedef struct xvattr { + vattr_t xva_vattr; /* Embedded vattr structure */ + uint32_t xva_magic; /* Magic Number */ + uint32_t xva_mapsize; /* Size of attr bitmap (32-bit words) */ + uint32_t *xva_rtnattrmapp; /* Ptr to xva_rtnattrmap[] */ + uint32_t xva_reqattrmap[XVA_MAPSIZE]; /* Requested attrs */ + uint32_t xva_rtnattrmap[XVA_MAPSIZE]; /* Returned attrs */ + xoptattr_t xva_xoptattrs; /* Optional attributes */ +} xvattr_t; + +#ifdef _SYSCALL32 +/* + * For bigtypes time_t changed to 64 bit on the 64-bit kernel. + * Define an old version for user/kernel interface + */ + +#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4 +#pragma pack(4) +#endif + +typedef struct vattr32 { + uint32_t va_mask; /* bit-mask of attributes */ + vtype_t va_type; /* vnode type (for create) */ + mode32_t va_mode; /* file access mode */ + uid32_t va_uid; /* owner user id */ + gid32_t va_gid; /* owner group id */ + dev32_t va_fsid; /* file system id (dev for now) */ + u_longlong_t va_nodeid; /* node id */ + nlink_t va_nlink; /* number of references to file */ + u_offset_t va_size; /* file size in bytes */ + timestruc32_t va_atime; /* time of last access */ + timestruc32_t va_mtime; /* time of last modification */ + timestruc32_t va_ctime; /* time of last status change */ + dev32_t va_rdev; /* device the file represents */ + uint32_t va_blksize; /* fundamental block size */ + u_longlong_t va_nblocks; /* # of blocks allocated */ + uint32_t va_seq; /* sequence number */ +} vattr32_t; + +#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4 +#pragma pack() +#endif + +#else /* not _SYSCALL32 */ +#define vattr32 vattr +typedef vattr_t vattr32_t; +#endif /* _SYSCALL32 */ + +/* + * Attributes of interest to the caller of setattr or getattr. + */ +#define AT_TYPE 0x00001 +#define AT_MODE 0x00002 +#define AT_UID 0x00004 +#define AT_GID 0x00008 +#define AT_FSID 0x00010 +#define AT_NODEID 0x00020 +#define AT_NLINK 0x00040 +#define AT_SIZE 0x00080 +#define AT_ATIME 0x00100 +#define AT_MTIME 0x00200 +#define AT_CTIME 0x00400 +#define AT_RDEV 0x00800 +#define AT_BLKSIZE 0x01000 +#define AT_NBLOCKS 0x02000 +/* 0x04000 */ /* unused */ +#define AT_SEQ 0x08000 +/* + * If AT_XVATTR is set then there are additional bits to process in + * the xvattr_t's attribute bitmap. If this is not set then the bitmap + * MUST be ignored. Note that this bit must be set/cleared explicitly. + * That is, setting AT_ALL will NOT set AT_XVATTR. + */ +#define AT_XVATTR 0x10000 + +#define AT_ALL (AT_TYPE|AT_MODE|AT_UID|AT_GID|AT_FSID|AT_NODEID|\ + AT_NLINK|AT_SIZE|AT_ATIME|AT_MTIME|AT_CTIME|\ + AT_RDEV|AT_BLKSIZE|AT_NBLOCKS|AT_SEQ) + +#define AT_STAT (AT_MODE|AT_UID|AT_GID|AT_FSID|AT_NODEID|AT_NLINK|\ + AT_SIZE|AT_ATIME|AT_MTIME|AT_CTIME|AT_RDEV|AT_TYPE) + +#define AT_TIMES (AT_ATIME|AT_MTIME|AT_CTIME) + +#define AT_NOSET (AT_NLINK|AT_RDEV|AT_FSID|AT_NODEID|AT_TYPE|\ + AT_BLKSIZE|AT_NBLOCKS|AT_SEQ) + +/* + * Attribute bits used in the extensible attribute's (xva's) attribute + * bitmaps. Note that the bitmaps are made up of a variable length number + * of 32-bit words. The convention is to use XAT{n}_{attrname} where "n" + * is the element in the bitmap (starting at 1). This convention is for + * the convenience of the maintainer to keep track of which element each + * attribute belongs to. + * + * NOTE THAT CONSUMERS MUST *NOT* USE THE XATn_* DEFINES DIRECTLY. CONSUMERS + * MUST USE THE XAT_* DEFINES. + */ +#define XAT0_INDEX 0LL /* Index into bitmap for XAT0 attrs */ +#define XAT0_CREATETIME 0x00000001 /* Create time of file */ +#define XAT0_ARCHIVE 0x00000002 /* Archive */ +#define XAT0_SYSTEM 0x00000004 /* System */ +#define XAT0_READONLY 0x00000008 /* Readonly */ +#define XAT0_HIDDEN 0x00000010 /* Hidden */ +#define XAT0_NOUNLINK 0x00000020 /* Nounlink */ +#define XAT0_IMMUTABLE 0x00000040 /* immutable */ +#define XAT0_APPENDONLY 0x00000080 /* appendonly */ +#define XAT0_NODUMP 0x00000100 /* nodump */ +#define XAT0_OPAQUE 0x00000200 /* opaque */ +#define XAT0_AV_QUARANTINED 0x00000400 /* anti-virus quarantine */ +#define XAT0_AV_MODIFIED 0x00000800 /* anti-virus modified */ +#define XAT0_AV_SCANSTAMP 0x00001000 /* anti-virus scanstamp */ +#define XAT0_REPARSE 0x00002000 /* FS reparse point */ +#define XAT0_GEN 0x00004000 /* object generation number */ +#define XAT0_OFFLINE 0x00008000 /* offline */ +#define XAT0_SPARSE 0x00010000 /* sparse */ + +#define XAT0_ALL_ATTRS (XAT0_CREATETIME|XAT0_ARCHIVE|XAT0_SYSTEM| \ + XAT0_READONLY|XAT0_HIDDEN|XAT0_NOUNLINK|XAT0_IMMUTABLE|XAT0_APPENDONLY| \ + XAT0_NODUMP|XAT0_OPAQUE|XAT0_AV_QUARANTINED| XAT0_AV_MODIFIED| \ + XAT0_AV_SCANSTAMP|XAT0_REPARSE|XATO_GEN|XAT0_OFFLINE|XAT0_SPARSE) + +/* Support for XAT_* optional attributes */ +#define XVA_MASK 0xffffffff /* Used to mask off 32 bits */ +#define XVA_SHFT 32 /* Used to shift index */ + +/* + * Used to pry out the index and attribute bits from the XAT_* attributes + * defined below. Note that we're masking things down to 32 bits then + * casting to uint32_t. + */ +#define XVA_INDEX(attr) ((uint32_t)(((attr) >> XVA_SHFT) & XVA_MASK)) +#define XVA_ATTRBIT(attr) ((uint32_t)((attr) & XVA_MASK)) + +/* + * The following defines present a "flat namespace" so that consumers don't + * need to keep track of which element belongs to which bitmap entry. + * + * NOTE THAT THESE MUST NEVER BE OR-ed TOGETHER + */ +#define XAT_CREATETIME ((XAT0_INDEX << XVA_SHFT) | XAT0_CREATETIME) +#define XAT_ARCHIVE ((XAT0_INDEX << XVA_SHFT) | XAT0_ARCHIVE) +#define XAT_SYSTEM ((XAT0_INDEX << XVA_SHFT) | XAT0_SYSTEM) +#define XAT_READONLY ((XAT0_INDEX << XVA_SHFT) | XAT0_READONLY) +#define XAT_HIDDEN ((XAT0_INDEX << XVA_SHFT) | XAT0_HIDDEN) +#define XAT_NOUNLINK ((XAT0_INDEX << XVA_SHFT) | XAT0_NOUNLINK) +#define XAT_IMMUTABLE ((XAT0_INDEX << XVA_SHFT) | XAT0_IMMUTABLE) +#define XAT_APPENDONLY ((XAT0_INDEX << XVA_SHFT) | XAT0_APPENDONLY) +#define XAT_NODUMP ((XAT0_INDEX << XVA_SHFT) | XAT0_NODUMP) +#define XAT_OPAQUE ((XAT0_INDEX << XVA_SHFT) | XAT0_OPAQUE) +#define XAT_AV_QUARANTINED ((XAT0_INDEX << XVA_SHFT) | XAT0_AV_QUARANTINED) +#define XAT_AV_MODIFIED ((XAT0_INDEX << XVA_SHFT) | XAT0_AV_MODIFIED) +#define XAT_AV_SCANSTAMP ((XAT0_INDEX << XVA_SHFT) | XAT0_AV_SCANSTAMP) +#define XAT_REPARSE ((XAT0_INDEX << XVA_SHFT) | XAT0_REPARSE) +#define XAT_GEN ((XAT0_INDEX << XVA_SHFT) | XAT0_GEN) +#define XAT_OFFLINE ((XAT0_INDEX << XVA_SHFT) | XAT0_OFFLINE) +#define XAT_SPARSE ((XAT0_INDEX << XVA_SHFT) | XAT0_SPARSE) + +/* + * The returned attribute map array (xva_rtnattrmap[]) is located past the + * requested attribute map array (xva_reqattrmap[]). Its location changes + * when the array sizes change. We use a separate pointer in a known location + * (xva_rtnattrmapp) to hold the location of xva_rtnattrmap[]. This is + * set in xva_init() + */ +#define XVA_RTNATTRMAP(xvap) ((xvap)->xva_rtnattrmapp) + +/* + * XVA_SET_REQ() sets an attribute bit in the proper element in the bitmap + * of requested attributes (xva_reqattrmap[]). + */ +#define XVA_SET_REQ(xvap, attr) \ + ASSERT((xvap)->xva_vattr.va_mask | AT_XVATTR); \ + ASSERT((xvap)->xva_magic == XVA_MAGIC); \ + (xvap)->xva_reqattrmap[XVA_INDEX(attr)] |= XVA_ATTRBIT(attr) +/* + * XVA_CLR_REQ() clears an attribute bit in the proper element in the bitmap + * of requested attributes (xva_reqattrmap[]). + */ +#define XVA_CLR_REQ(xvap, attr) \ + ASSERT((xvap)->xva_vattr.va_mask | AT_XVATTR); \ + ASSERT((xvap)->xva_magic == XVA_MAGIC); \ + (xvap)->xva_reqattrmap[XVA_INDEX(attr)] &= ~XVA_ATTRBIT(attr) + +/* + * XVA_SET_RTN() sets an attribute bit in the proper element in the bitmap + * of returned attributes (xva_rtnattrmap[]). + */ +#define XVA_SET_RTN(xvap, attr) \ + ASSERT((xvap)->xva_vattr.va_mask | AT_XVATTR); \ + ASSERT((xvap)->xva_magic == XVA_MAGIC); \ + (XVA_RTNATTRMAP(xvap))[XVA_INDEX(attr)] |= XVA_ATTRBIT(attr) + +/* + * XVA_ISSET_REQ() checks the requested attribute bitmap (xva_reqattrmap[]) + * to see of the corresponding attribute bit is set. If so, returns non-zero. + */ +#define XVA_ISSET_REQ(xvap, attr) \ + ((((xvap)->xva_vattr.va_mask | AT_XVATTR) && \ + ((xvap)->xva_magic == XVA_MAGIC) && \ + ((xvap)->xva_mapsize > XVA_INDEX(attr))) ? \ + ((xvap)->xva_reqattrmap[XVA_INDEX(attr)] & XVA_ATTRBIT(attr)) : 0) + +/* + * XVA_ISSET_RTN() checks the returned attribute bitmap (xva_rtnattrmap[]) + * to see of the corresponding attribute bit is set. If so, returns non-zero. + */ +#define XVA_ISSET_RTN(xvap, attr) \ + ((((xvap)->xva_vattr.va_mask | AT_XVATTR) && \ + ((xvap)->xva_magic == XVA_MAGIC) && \ + ((xvap)->xva_mapsize > XVA_INDEX(attr))) ? \ + ((XVA_RTNATTRMAP(xvap))[XVA_INDEX(attr)] & XVA_ATTRBIT(attr)) : 0) + +/* + * Modes. Some values same as S_xxx entries from stat.h for convenience. + */ +#define VSUID 04000 /* set user id on execution */ +#define VSGID 02000 /* set group id on execution */ +#define VSVTX 01000 /* save swapped text even after use */ + +/* + * Permissions. + */ +#define VREAD 00400 +#define VWRITE 00200 +#define VEXEC 00100 + +#define MODEMASK 07777 /* mode bits plus permission bits */ +#define PERMMASK 00777 /* permission bits */ + +/* + * VOP_ACCESS flags + */ +#define V_ACE_MASK 0x1 /* mask represents NFSv4 ACE permissions */ +#define V_APPEND 0x2 /* want to do append only check */ + +/* + * Check whether mandatory file locking is enabled. + */ + +#define MANDMODE(mode) (((mode) & (VSGID|(VEXEC>>3))) == VSGID) +#define MANDLOCK(vp, mode) ((vp)->v_type == VREG && MANDMODE(mode)) + +/* + * Flags for vnode operations. + */ +enum rm { RMFILE, RMDIRECTORY }; /* rm or rmdir (remove) */ +enum symfollow { NO_FOLLOW, FOLLOW }; /* follow symlinks (or not) */ +enum vcexcl { NONEXCL, EXCL }; /* (non)excl create */ +enum create { CRCREAT, CRMKNOD, CRMKDIR }; /* reason for create */ + +typedef enum rm rm_t; +typedef enum symfollow symfollow_t; +typedef enum vcexcl vcexcl_t; +typedef enum create create_t; + +/* Vnode Events - Used by VOP_VNEVENT */ +typedef enum vnevent { + VE_SUPPORT = 0, /* Query */ + VE_RENAME_SRC = 1, /* Rename, with vnode as source */ + VE_RENAME_DEST = 2, /* Rename, with vnode as target/destination */ + VE_REMOVE = 3, /* Remove of vnode's name */ + VE_RMDIR = 4, /* Remove of directory vnode's name */ + VE_CREATE = 5, /* Create with vnode's name which exists */ + VE_LINK = 6, /* Link with vnode's name as source */ + VE_RENAME_DEST_DIR = 7, /* Rename with vnode as target dir */ + VE_MOUNTEDOVER = 8, /* File or Filesystem got mounted over vnode */ + VE_TRUNCATE = 9 /* Truncate */ +} vnevent_t; + +/* + * Values for checking vnode open and map counts + */ +enum v_mode { V_READ, V_WRITE, V_RDORWR, V_RDANDWR }; + +typedef enum v_mode v_mode_t; + +#define V_TRUE 1 +#define V_FALSE 0 + +/* + * Structure used on VOP_GETSECATTR and VOP_SETSECATTR operations + */ + +typedef struct vsecattr { + uint_t vsa_mask; /* See below */ + int vsa_aclcnt; /* ACL entry count */ + void *vsa_aclentp; /* pointer to ACL entries */ + int vsa_dfaclcnt; /* default ACL entry count */ + void *vsa_dfaclentp; /* pointer to default ACL entries */ + size_t vsa_aclentsz; /* ACE size in bytes of vsa_aclentp */ + uint_t vsa_aclflags; /* ACE ACL flags */ +} vsecattr_t; + +/* vsa_mask values */ +#define VSA_ACL 0x0001 +#define VSA_ACLCNT 0x0002 +#define VSA_DFACL 0x0004 +#define VSA_DFACLCNT 0x0008 +#define VSA_ACE 0x0010 +#define VSA_ACECNT 0x0020 +#define VSA_ACE_ALLTYPES 0x0040 +#define VSA_ACE_ACLFLAGS 0x0080 /* get/set ACE ACL flags */ + +/* + * Structure used by various vnode operations to determine + * the context (pid, host, identity) of a caller. + * + * The cc_caller_id is used to identify one or more callers who invoke + * operations, possibly on behalf of others. For example, the NFS + * server could have it's own cc_caller_id which can be detected by + * vnode/vfs operations or (FEM) monitors on those operations. New + * caller IDs are generated by fs_new_caller_id(). + */ +typedef struct caller_context { + pid_t cc_pid; /* Process ID of the caller */ + int cc_sysid; /* System ID, used for remote calls */ + u_longlong_t cc_caller_id; /* Identifier for (set of) caller(s) */ + ulong_t cc_flags; +} caller_context_t; + +/* + * Flags for caller context. The caller sets CC_DONTBLOCK if it does not + * want to block inside of a FEM monitor. The monitor will set CC_WOULDBLOCK + * and return EAGAIN if the operation would have blocked. + */ +#define CC_WOULDBLOCK 0x01 +#define CC_DONTBLOCK 0x02 + +/* + * Structure tags for function prototypes, defined elsewhere. + */ +struct pathname; +struct fid; +struct flock64; +struct flk_callback; +struct shrlock; +struct page; +struct seg; +struct as; +struct pollhead; +struct taskq; + +#if defined(_KERNEL) || defined(_FAKE_KERNEL) + +/* + * VNODE_OPS defines all the vnode operations. It is used to define + * the vnodeops structure (below) and the fs_func_p union (vfs_opreg.h). + */ +#define VNODE_OPS \ + int (*vop_open)(vnode_t **, int, cred_t *, \ + caller_context_t *); \ + int (*vop_close)(vnode_t *, int, int, offset_t, cred_t *, \ + caller_context_t *); \ + int (*vop_read)(vnode_t *, uio_t *, int, cred_t *, \ + caller_context_t *); \ + int (*vop_write)(vnode_t *, uio_t *, int, cred_t *, \ + caller_context_t *); \ + int (*vop_ioctl)(vnode_t *, int, intptr_t, int, cred_t *, \ + int *, caller_context_t *); \ + int (*vop_setfl)(vnode_t *, int, int, cred_t *, \ + caller_context_t *); \ + int (*vop_getattr)(vnode_t *, vattr_t *, int, cred_t *, \ + caller_context_t *); \ + int (*vop_setattr)(vnode_t *, vattr_t *, int, cred_t *, \ + caller_context_t *); \ + int (*vop_access)(vnode_t *, int, int, cred_t *, \ + caller_context_t *); \ + int (*vop_lookup)(vnode_t *, char *, vnode_t **, \ + struct pathname *, \ + int, vnode_t *, cred_t *, \ + caller_context_t *, int *, \ + struct pathname *); \ + int (*vop_create)(vnode_t *, char *, vattr_t *, vcexcl_t, \ + int, vnode_t **, cred_t *, int, \ + caller_context_t *, vsecattr_t *); \ + int (*vop_remove)(vnode_t *, char *, cred_t *, \ + caller_context_t *, int); \ + int (*vop_link)(vnode_t *, vnode_t *, char *, cred_t *, \ + caller_context_t *, int); \ + int (*vop_rename)(vnode_t *, char *, vnode_t *, char *, \ + cred_t *, caller_context_t *, int); \ + int (*vop_mkdir)(vnode_t *, char *, vattr_t *, vnode_t **, \ + cred_t *, caller_context_t *, int, \ + vsecattr_t *); \ + int (*vop_rmdir)(vnode_t *, char *, vnode_t *, cred_t *, \ + caller_context_t *, int); \ + int (*vop_readdir)(vnode_t *, uio_t *, cred_t *, int *, \ + caller_context_t *, int); \ + int (*vop_symlink)(vnode_t *, char *, vattr_t *, char *, \ + cred_t *, caller_context_t *, int); \ + int (*vop_readlink)(vnode_t *, uio_t *, cred_t *, \ + caller_context_t *); \ + int (*vop_fsync)(vnode_t *, int, cred_t *, \ + caller_context_t *); \ + void (*vop_inactive)(vnode_t *, cred_t *, \ + caller_context_t *); \ + int (*vop_fid)(vnode_t *, struct fid *, \ + caller_context_t *); \ + int (*vop_rwlock)(vnode_t *, int, caller_context_t *); \ + void (*vop_rwunlock)(vnode_t *, int, caller_context_t *); \ + int (*vop_seek)(vnode_t *, offset_t, offset_t *, \ + caller_context_t *); \ + int (*vop_cmp)(vnode_t *, vnode_t *, caller_context_t *); \ + int (*vop_frlock)(vnode_t *, int, struct flock64 *, \ + int, offset_t, \ + struct flk_callback *, cred_t *, \ + caller_context_t *); \ + int (*vop_space)(vnode_t *, int, struct flock64 *, \ + int, offset_t, \ + cred_t *, caller_context_t *); \ + int (*vop_realvp)(vnode_t *, vnode_t **, \ + caller_context_t *); \ + int (*vop_getpage)(vnode_t *, offset_t, size_t, uint_t *, \ + struct page **, size_t, struct seg *, \ + caddr_t, enum seg_rw, cred_t *, \ + caller_context_t *); \ + int (*vop_putpage)(vnode_t *, offset_t, size_t, \ + int, cred_t *, caller_context_t *); \ + int (*vop_map)(vnode_t *, offset_t, struct as *, \ + caddr_t *, size_t, \ + uchar_t, uchar_t, uint_t, cred_t *, \ + caller_context_t *); \ + int (*vop_addmap)(vnode_t *, offset_t, struct as *, \ + caddr_t, size_t, \ + uchar_t, uchar_t, uint_t, cred_t *, \ + caller_context_t *); \ + int (*vop_delmap)(vnode_t *, offset_t, struct as *, \ + caddr_t, size_t, \ + uint_t, uint_t, uint_t, cred_t *, \ + caller_context_t *); \ + int (*vop_poll)(vnode_t *, short, int, short *, \ + struct pollhead **, \ + caller_context_t *); \ + int (*vop_dump)(vnode_t *, caddr_t, offset_t, offset_t, \ + caller_context_t *); \ + int (*vop_pathconf)(vnode_t *, int, ulong_t *, cred_t *, \ + caller_context_t *); \ + int (*vop_pageio)(vnode_t *, struct page *, \ + u_offset_t, size_t, int, cred_t *, \ + caller_context_t *); \ + int (*vop_dumpctl)(vnode_t *, int, offset_t *, \ + caller_context_t *); \ + void (*vop_dispose)(vnode_t *, struct page *, \ + int, int, cred_t *, \ + caller_context_t *); \ + int (*vop_setsecattr)(vnode_t *, vsecattr_t *, \ + int, cred_t *, caller_context_t *); \ + int (*vop_getsecattr)(vnode_t *, vsecattr_t *, \ + int, cred_t *, caller_context_t *); \ + int (*vop_shrlock)(vnode_t *, int, struct shrlock *, \ + int, cred_t *, caller_context_t *); \ + int (*vop_vnevent)(vnode_t *, vnevent_t, vnode_t *, \ + char *, caller_context_t *); \ + int (*vop_reqzcbuf)(vnode_t *, enum uio_rw, xuio_t *, \ + cred_t *, caller_context_t *); \ + int (*vop_retzcbuf)(vnode_t *, xuio_t *, cred_t *, \ + caller_context_t *) + /* NB: No ";" */ + +/* + * Operations on vnodes. Note: File systems must never operate directly + * on a 'vnodeops' structure -- it WILL change in future releases! They + * must use vn_make_ops() to create the structure. + */ +typedef struct vnodeops { + const char *vnop_name; + VNODE_OPS; /* Signatures of all vnode operations (vops) */ +} vnodeops_t; + +typedef int (*fs_generic_func_p) (); /* Generic vop/vfsop/femop/fsemop ptr */ + +extern int fop_open(vnode_t **, int, cred_t *, caller_context_t *); +extern int fop_close(vnode_t *, int, int, offset_t, cred_t *, + caller_context_t *); +extern int fop_read(vnode_t *, uio_t *, int, cred_t *, caller_context_t *); +extern int fop_write(vnode_t *, uio_t *, int, cred_t *, + caller_context_t *); +extern int fop_ioctl(vnode_t *, int, intptr_t, int, cred_t *, int *, + caller_context_t *); +extern int fop_setfl(vnode_t *, int, int, cred_t *, caller_context_t *); +extern int fop_getattr(vnode_t *, vattr_t *, int, cred_t *, + caller_context_t *); +extern int fop_setattr(vnode_t *, vattr_t *, int, cred_t *, + caller_context_t *); +extern int fop_access(vnode_t *, int, int, cred_t *, caller_context_t *); +extern int fop_lookup(vnode_t *, char *, vnode_t **, struct pathname *, + int, vnode_t *, cred_t *, caller_context_t *, + int *, struct pathname *); +extern int fop_create(vnode_t *, char *, vattr_t *, vcexcl_t, int, + vnode_t **, cred_t *, int, caller_context_t *, + vsecattr_t *); +extern int fop_remove(vnode_t *vp, char *, cred_t *, caller_context_t *, + int); +extern int fop_link(vnode_t *, vnode_t *, char *, cred_t *, + caller_context_t *, int); +extern int fop_rename(vnode_t *, char *, vnode_t *, char *, cred_t *, + caller_context_t *, int); +extern int fop_mkdir(vnode_t *, char *, vattr_t *, vnode_t **, cred_t *, + caller_context_t *, int, vsecattr_t *); +extern int fop_rmdir(vnode_t *, char *, vnode_t *, cred_t *, + caller_context_t *, int); +extern int fop_readdir(vnode_t *, uio_t *, cred_t *, int *, + caller_context_t *, int); +extern int fop_symlink(vnode_t *, char *, vattr_t *, char *, cred_t *, + caller_context_t *, int); +extern int fop_readlink(vnode_t *, uio_t *, cred_t *, caller_context_t *); +extern int fop_fsync(vnode_t *, int, cred_t *, caller_context_t *); +extern void fop_inactive(vnode_t *, cred_t *, caller_context_t *); +extern int fop_fid(vnode_t *, struct fid *, caller_context_t *); +extern int fop_rwlock(vnode_t *, int, caller_context_t *); +extern void fop_rwunlock(vnode_t *, int, caller_context_t *); +extern int fop_seek(vnode_t *, offset_t, offset_t *, caller_context_t *); +extern int fop_cmp(vnode_t *, vnode_t *, caller_context_t *); +extern int fop_frlock(vnode_t *, int, struct flock64 *, int, offset_t, + struct flk_callback *, cred_t *, + caller_context_t *); +extern int fop_space(vnode_t *, int, struct flock64 *, int, offset_t, + cred_t *, caller_context_t *); +extern int fop_realvp(vnode_t *, vnode_t **, caller_context_t *); +extern int fop_getpage(vnode_t *, offset_t, size_t, uint_t *, + struct page **, size_t, struct seg *, + caddr_t, enum seg_rw, cred_t *, + caller_context_t *); +extern int fop_putpage(vnode_t *, offset_t, size_t, int, cred_t *, + caller_context_t *); +extern int fop_map(vnode_t *, offset_t, struct as *, caddr_t *, size_t, + uchar_t, uchar_t, uint_t, cred_t *cr, + caller_context_t *); +extern int fop_addmap(vnode_t *, offset_t, struct as *, caddr_t, size_t, + uchar_t, uchar_t, uint_t, cred_t *, + caller_context_t *); +extern int fop_delmap(vnode_t *, offset_t, struct as *, caddr_t, size_t, + uint_t, uint_t, uint_t, cred_t *, + caller_context_t *); +extern int fop_poll(vnode_t *, short, int, short *, struct pollhead **, + caller_context_t *); +extern int fop_dump(vnode_t *, caddr_t, offset_t, offset_t, + caller_context_t *); +extern int fop_pathconf(vnode_t *, int, ulong_t *, cred_t *, + caller_context_t *); +extern int fop_pageio(vnode_t *, struct page *, u_offset_t, size_t, int, + cred_t *, caller_context_t *); +extern int fop_dumpctl(vnode_t *, int, offset_t *, caller_context_t *); +extern void fop_dispose(vnode_t *, struct page *, int, int, cred_t *, + caller_context_t *); +extern int fop_setsecattr(vnode_t *, vsecattr_t *, int, cred_t *, + caller_context_t *); +extern int fop_getsecattr(vnode_t *, vsecattr_t *, int, cred_t *, + caller_context_t *); +extern int fop_shrlock(vnode_t *, int, struct shrlock *, int, cred_t *, + caller_context_t *); +extern int fop_vnevent(vnode_t *, vnevent_t, vnode_t *, char *, + caller_context_t *); +extern int fop_reqzcbuf(vnode_t *, enum uio_rw, xuio_t *, cred_t *, + caller_context_t *); +extern int fop_retzcbuf(vnode_t *, xuio_t *, cred_t *, caller_context_t *); + +#endif /* _KERNEL */ + +#define VOP_OPEN(vpp, mode, cr, ct) \ + fop_open(vpp, mode, cr, ct) +#define VOP_CLOSE(vp, f, c, o, cr, ct) \ + fop_close(vp, f, c, o, cr, ct) +#define VOP_READ(vp, uiop, iof, cr, ct) \ + fop_read(vp, uiop, iof, cr, ct) +#define VOP_WRITE(vp, uiop, iof, cr, ct) \ + fop_write(vp, uiop, iof, cr, ct) +#define VOP_IOCTL(vp, cmd, a, f, cr, rvp, ct) \ + fop_ioctl(vp, cmd, a, f, cr, rvp, ct) +#define VOP_SETFL(vp, f, a, cr, ct) \ + fop_setfl(vp, f, a, cr, ct) +#define VOP_GETATTR(vp, vap, f, cr, ct) \ + fop_getattr(vp, vap, f, cr, ct) +#define VOP_SETATTR(vp, vap, f, cr, ct) \ + fop_setattr(vp, vap, f, cr, ct) +#define VOP_ACCESS(vp, mode, f, cr, ct) \ + fop_access(vp, mode, f, cr, ct) +#define VOP_LOOKUP(vp, cp, vpp, pnp, f, rdir, cr, ct, defp, rpnp) \ + fop_lookup(vp, cp, vpp, pnp, f, rdir, cr, ct, defp, rpnp) +#define VOP_CREATE(dvp, p, vap, ex, mode, vpp, cr, flag, ct, vsap) \ + fop_create(dvp, p, vap, ex, mode, vpp, cr, flag, ct, vsap) +#define VOP_REMOVE(dvp, p, cr, ct, f) \ + fop_remove(dvp, p, cr, ct, f) +#define VOP_LINK(tdvp, fvp, p, cr, ct, f) \ + fop_link(tdvp, fvp, p, cr, ct, f) +#define VOP_RENAME(fvp, fnm, tdvp, tnm, cr, ct, f) \ + fop_rename(fvp, fnm, tdvp, tnm, cr, ct, f) +#define VOP_MKDIR(dp, p, vap, vpp, cr, ct, f, vsap) \ + fop_mkdir(dp, p, vap, vpp, cr, ct, f, vsap) +#define VOP_RMDIR(dp, p, cdir, cr, ct, f) \ + fop_rmdir(dp, p, cdir, cr, ct, f) +#define VOP_READDIR(vp, uiop, cr, eofp, ct, f) \ + fop_readdir(vp, uiop, cr, eofp, ct, f) +#define VOP_SYMLINK(dvp, lnm, vap, tnm, cr, ct, f) \ + fop_symlink(dvp, lnm, vap, tnm, cr, ct, f) +#define VOP_READLINK(vp, uiop, cr, ct) \ + fop_readlink(vp, uiop, cr, ct) +#define VOP_FSYNC(vp, syncflag, cr, ct) \ + fop_fsync(vp, syncflag, cr, ct) +#define VOP_INACTIVE(vp, cr, ct) \ + fop_inactive(vp, cr, ct) +#define VOP_FID(vp, fidp, ct) \ + fop_fid(vp, fidp, ct) +#define VOP_RWLOCK(vp, w, ct) \ + fop_rwlock(vp, w, ct) +#define VOP_RWUNLOCK(vp, w, ct) \ + fop_rwunlock(vp, w, ct) +#define VOP_SEEK(vp, ooff, noffp, ct) \ + fop_seek(vp, ooff, noffp, ct) +#define VOP_CMP(vp1, vp2, ct) \ + fop_cmp(vp1, vp2, ct) +#define VOP_FRLOCK(vp, cmd, a, f, o, cb, cr, ct) \ + fop_frlock(vp, cmd, a, f, o, cb, cr, ct) +#define VOP_SPACE(vp, cmd, a, f, o, cr, ct) \ + fop_space(vp, cmd, a, f, o, cr, ct) +#define VOP_REALVP(vp1, vp2, ct) \ + fop_realvp(vp1, vp2, ct) +#define VOP_GETPAGE(vp, of, sz, pr, pl, ps, sg, a, rw, cr, ct) \ + fop_getpage(vp, of, sz, pr, pl, ps, sg, a, rw, cr, ct) +#define VOP_PUTPAGE(vp, of, sz, fl, cr, ct) \ + fop_putpage(vp, of, sz, fl, cr, ct) +#define VOP_MAP(vp, of, as, a, sz, p, mp, fl, cr, ct) \ + fop_map(vp, of, as, a, sz, p, mp, fl, cr, ct) +#define VOP_ADDMAP(vp, of, as, a, sz, p, mp, fl, cr, ct) \ + fop_addmap(vp, of, as, a, sz, p, mp, fl, cr, ct) +#define VOP_DELMAP(vp, of, as, a, sz, p, mp, fl, cr, ct) \ + fop_delmap(vp, of, as, a, sz, p, mp, fl, cr, ct) +#define VOP_POLL(vp, events, anyyet, reventsp, phpp, ct) \ + fop_poll(vp, events, anyyet, reventsp, phpp, ct) +#define VOP_DUMP(vp, addr, bn, count, ct) \ + fop_dump(vp, addr, bn, count, ct) +#define VOP_PATHCONF(vp, cmd, valp, cr, ct) \ + fop_pathconf(vp, cmd, valp, cr, ct) +#define VOP_PAGEIO(vp, pp, io_off, io_len, flags, cr, ct) \ + fop_pageio(vp, pp, io_off, io_len, flags, cr, ct) +#define VOP_DUMPCTL(vp, action, blkp, ct) \ + fop_dumpctl(vp, action, blkp, ct) +#define VOP_DISPOSE(vp, pp, flag, dn, cr, ct) \ + fop_dispose(vp, pp, flag, dn, cr, ct) +#define VOP_GETSECATTR(vp, vsap, f, cr, ct) \ + fop_getsecattr(vp, vsap, f, cr, ct) +#define VOP_SETSECATTR(vp, vsap, f, cr, ct) \ + fop_setsecattr(vp, vsap, f, cr, ct) +#define VOP_SHRLOCK(vp, cmd, shr, f, cr, ct) \ + fop_shrlock(vp, cmd, shr, f, cr, ct) +#define VOP_VNEVENT(vp, vnevent, dvp, fnm, ct) \ + fop_vnevent(vp, vnevent, dvp, fnm, ct) +#define VOP_REQZCBUF(vp, rwflag, xuiop, cr, ct) \ + fop_reqzcbuf(vp, rwflag, xuiop, cr, ct) +#define VOP_RETZCBUF(vp, xuiop, cr, ct) \ + fop_retzcbuf(vp, xuiop, cr, ct) + +#define VOPNAME_OPEN "open" +#define VOPNAME_CLOSE "close" +#define VOPNAME_READ "read" +#define VOPNAME_WRITE "write" +#define VOPNAME_IOCTL "ioctl" +#define VOPNAME_SETFL "setfl" +#define VOPNAME_GETATTR "getattr" +#define VOPNAME_SETATTR "setattr" +#define VOPNAME_ACCESS "access" +#define VOPNAME_LOOKUP "lookup" +#define VOPNAME_CREATE "create" +#define VOPNAME_REMOVE "remove" +#define VOPNAME_LINK "link" +#define VOPNAME_RENAME "rename" +#define VOPNAME_MKDIR "mkdir" +#define VOPNAME_RMDIR "rmdir" +#define VOPNAME_READDIR "readdir" +#define VOPNAME_SYMLINK "symlink" +#define VOPNAME_READLINK "readlink" +#define VOPNAME_FSYNC "fsync" +#define VOPNAME_INACTIVE "inactive" +#define VOPNAME_FID "fid" +#define VOPNAME_RWLOCK "rwlock" +#define VOPNAME_RWUNLOCK "rwunlock" +#define VOPNAME_SEEK "seek" +#define VOPNAME_CMP "cmp" +#define VOPNAME_FRLOCK "frlock" +#define VOPNAME_SPACE "space" +#define VOPNAME_REALVP "realvp" +#define VOPNAME_GETPAGE "getpage" +#define VOPNAME_PUTPAGE "putpage" +#define VOPNAME_MAP "map" +#define VOPNAME_ADDMAP "addmap" +#define VOPNAME_DELMAP "delmap" +#define VOPNAME_POLL "poll" +#define VOPNAME_DUMP "dump" +#define VOPNAME_PATHCONF "pathconf" +#define VOPNAME_PAGEIO "pageio" +#define VOPNAME_DUMPCTL "dumpctl" +#define VOPNAME_DISPOSE "dispose" +#define VOPNAME_GETSECATTR "getsecattr" +#define VOPNAME_SETSECATTR "setsecattr" +#define VOPNAME_SHRLOCK "shrlock" +#define VOPNAME_VNEVENT "vnevent" +#define VOPNAME_REQZCBUF "reqzcbuf" +#define VOPNAME_RETZCBUF "retzcbuf" + +/* + * Flags for VOP_LOOKUP + * + * Defined in file.h, but also possible, FIGNORECASE and FSEARCH + * + */ +#define LOOKUP_DIR 0x01 /* want parent dir vp */ +#define LOOKUP_XATTR 0x02 /* lookup up extended attr dir */ +#define CREATE_XATTR_DIR 0x04 /* Create extended attr dir */ +#define LOOKUP_HAVE_SYSATTR_DIR 0x08 /* Already created virtual GFS dir */ + +/* + * Flags for VOP_READDIR + */ +#define V_RDDIR_ENTFLAGS 0x01 /* request dirent flags */ +#define V_RDDIR_ACCFILTER 0x02 /* filter out inaccessible dirents */ + +/* + * Flags for VOP_RWLOCK/VOP_RWUNLOCK + * VOP_RWLOCK will return the flag that was actually set, or -1 if none. + */ +#define V_WRITELOCK_TRUE (1) /* Request write-lock on the vnode */ +#define V_WRITELOCK_FALSE (0) /* Request read-lock on the vnode */ + +/* + * Flags for VOP_DUMPCTL + */ +#define DUMP_ALLOC 0 +#define DUMP_FREE 1 +#define DUMP_SCAN 2 + +/* + * Public vnode manipulation functions. + */ +#if defined(_KERNEL) || defined(_FAKE_KERNEL) + +vnode_t *vn_alloc(int); +void vn_reinit(vnode_t *); +void vn_recycle(vnode_t *); +void vn_free(vnode_t *); + +int vn_is_readonly(vnode_t *); +int vn_is_opened(vnode_t *, v_mode_t); +int vn_is_mapped(vnode_t *, v_mode_t); +int vn_has_other_opens(vnode_t *, v_mode_t); +void vn_open_upgrade(vnode_t *, int); +void vn_open_downgrade(vnode_t *, int); + +int vn_can_change_zones(vnode_t *vp); + +int vn_has_flocks(vnode_t *); +int vn_has_mandatory_locks(vnode_t *, int); +int vn_has_cached_data(vnode_t *); + +void vn_setops(vnode_t *, vnodeops_t *); +vnodeops_t *vn_getops(vnode_t *); +int vn_matchops(vnode_t *, vnodeops_t *); +int vn_matchopval(vnode_t *, char *, fs_generic_func_p); +int vn_ismntpt(vnode_t *); + +struct vfs *vn_mountedvfs(vnode_t *); + +int vn_in_dnlc(vnode_t *); + +void vn_create_cache(void); +void vn_destroy_cache(void); + +void vn_freevnodeops(vnodeops_t *); + +int vn_open(char *pnamep, enum uio_seg seg, int filemode, int createmode, + struct vnode **vpp, enum create crwhy, mode_t umask); +int vn_openat(char *pnamep, enum uio_seg seg, int filemode, int createmode, + struct vnode **vpp, enum create crwhy, + mode_t umask, struct vnode *startvp, int fd); +int vn_create(char *pnamep, enum uio_seg seg, struct vattr *vap, + enum vcexcl excl, int mode, struct vnode **vpp, + enum create why, int flag, mode_t umask); +int vn_createat(char *pnamep, enum uio_seg seg, struct vattr *vap, + enum vcexcl excl, int mode, struct vnode **vpp, + enum create why, int flag, mode_t umask, struct vnode *startvp); +int vn_rdwr(enum uio_rw rw, struct vnode *vp, caddr_t base, ssize_t len, + offset_t offset, enum uio_seg seg, int ioflag, rlim64_t ulimit, + cred_t *cr, ssize_t *residp); + +void vn_hold(struct vnode *vp); +void vn_rele(struct vnode *vp); +void vn_rele_async(struct vnode *vp, struct taskq *taskq); +void vn_rele_dnlc(struct vnode *vp); +void vn_rele_stream(struct vnode *vp); +int vn_link(char *from, char *to, enum uio_seg seg); +int vn_linkat(vnode_t *fstartvp, char *from, enum symfollow follow, + vnode_t *tstartvp, char *to, enum uio_seg seg); +int vn_rename(char *from, char *to, enum uio_seg seg); +int vn_renameat(vnode_t *fdvp, char *fname, vnode_t *tdvp, char *tname, + enum uio_seg seg); +int vn_remove(char *fnamep, enum uio_seg seg, enum rm dirflag); +int vn_removeat(vnode_t *startvp, char *fnamep, enum uio_seg seg, + enum rm dirflag); +int vn_compare(vnode_t *vp1, vnode_t *vp2); +int vn_vfswlock(struct vnode *vp); +int vn_vfswlock_wait(struct vnode *vp); +int vn_vfsrlock(struct vnode *vp); +int vn_vfsrlock_wait(struct vnode *vp); +void vn_vfsunlock(struct vnode *vp); +int vn_vfswlock_held(struct vnode *vp); +vnode_t *specvp(struct vnode *vp, dev_t dev, vtype_t type, struct cred *cr); +vnode_t *makespecvp(dev_t dev, vtype_t type); + +#if defined(_KERNEL) +vn_vfslocks_entry_t *vn_vfslocks_getlock(void *); +void vn_vfslocks_rele(vn_vfslocks_entry_t *); +#endif + +boolean_t vn_is_reparse(vnode_t *, cred_t *, caller_context_t *); + +void vn_copypath(struct vnode *src, struct vnode *dst); +void vn_setpath_str(struct vnode *vp, const char *str, size_t len); +void vn_setpath(vnode_t *rootvp, struct vnode *startvp, struct vnode *vp, + const char *path, size_t plen); +void vn_renamepath(vnode_t *dvp, vnode_t *vp, const char *nm, size_t len); + +/* Vnode event notification */ +void vnevent_rename_src(vnode_t *, vnode_t *, char *, caller_context_t *); +void vnevent_rename_dest(vnode_t *, vnode_t *, char *, caller_context_t *); +void vnevent_remove(vnode_t *, vnode_t *, char *, caller_context_t *); +void vnevent_rmdir(vnode_t *, vnode_t *, char *, caller_context_t *); +void vnevent_create(vnode_t *, caller_context_t *); +void vnevent_link(vnode_t *, caller_context_t *); +void vnevent_rename_dest_dir(vnode_t *, caller_context_t *ct); +void vnevent_mountedover(vnode_t *, caller_context_t *); +void vnevent_truncate(vnode_t *, caller_context_t *); +int vnevent_support(vnode_t *, caller_context_t *); + +/* Vnode specific data */ +void vsd_create(uint_t *, void (*)(void *)); +void vsd_destroy(uint_t *); +void *vsd_get(vnode_t *, uint_t); +int vsd_set(vnode_t *, uint_t, void *); +void vsd_free(vnode_t *); + +/* + * Extensible vnode attribute (xva) routines: + * xva_init() initializes an xvattr_t (zero struct, init mapsize, set AT_XATTR) + * xva_getxoptattr() returns a ponter to the xoptattr_t section of xvattr_t + */ +void xva_init(xvattr_t *); +xoptattr_t *xva_getxoptattr(xvattr_t *); /* Get ptr to xoptattr_t */ + +void xattr_init(void); /* Initialize vnodeops for xattrs */ + +/* GFS tunnel for xattrs */ +int xattr_dir_lookup(vnode_t *, vnode_t **, int, cred_t *); + +/* Reparse Point */ +void reparse_point_init(void); + +/* Context identification */ +u_longlong_t fs_new_caller_id(); + +int vn_vmpss_usepageio(vnode_t *); + +/* Empty v_path placeholder */ +extern char *vn_vpath_empty; + +/* + * Needed for use of IS_VMODSORT() in kernel. + */ +extern uint_t pvn_vmodsort_supported; + +#define VN_HOLD(vp) { \ + vn_hold(vp); \ +} + +#define VN_RELE(vp) { \ + vn_rele(vp); \ +} + +#define VN_RELE_ASYNC(vp, taskq) { \ + vn_rele_async(vp, taskq); \ +} + +#define VN_RELE_LOCKED(vp) { \ + (vp)->v_count--; \ +} + +#define VN_SET_VFS_TYPE_DEV(vp, vfsp, type, dev) { \ + (vp)->v_vfsp = (vfsp); \ + (vp)->v_type = (type); \ + (vp)->v_rdev = (dev); \ +} + +/* + * Compare two vnodes for equality. In general this macro should be used + * in preference to calling VOP_CMP directly. + */ +#if defined(_FAKE_KERNEL) +#define VN_CMP(VP1, VP2) \ + (((VP1) == (VP2)) ? 1 : VOP_CMP(VP1, VP2, NULL)) +#else +#define VN_CMP(VP1, VP2) ((VP1) == (VP2) ? 1 : \ + ((VP1) && (VP2) && (vn_getops(VP1) == vn_getops(VP2)) ? \ + VOP_CMP(VP1, VP2, NULL) : 0)) +#endif + +/* + * Some well-known global vnodes used by the VM system to name pages. + */ +extern struct vnode kvps[]; + +typedef enum { + KV_KVP, /* vnode for all segkmem pages */ + KV_ZVP, /* vnode for all ZFS pages */ +#if defined(__sparc) + KV_MPVP, /* vnode for all page_t meta-pages */ + KV_PROMVP, /* vnode for all PROM pages */ +#endif /* __sparc */ + KV_MAX /* total number of vnodes in kvps[] */ +} kvps_index_t; + +#define VN_ISKAS(vp) ((vp) >= &kvps[0] && (vp) < &kvps[KV_MAX]) + +#endif /* _KERNEL */ + +/* + * Flags to VOP_SETATTR/VOP_GETATTR. + */ +#define ATTR_UTIME 0x01 /* non-default utime(2) request */ +#define ATTR_EXEC 0x02 /* invocation from exec(2) */ +#define ATTR_COMM 0x04 /* yield common vp attributes */ +#define ATTR_HINT 0x08 /* information returned will be `hint' */ +#define ATTR_REAL 0x10 /* yield attributes of the real vp */ +#define ATTR_NOACLCHECK 0x20 /* Don't check ACL when checking permissions */ +#define ATTR_TRIGGER 0x40 /* Mount first if vnode is a trigger mount */ +/* + * Generally useful macros. + */ +#define VBSIZE(vp) ((vp)->v_vfsp->vfs_bsize) + +#define VTOZONE(vp) ((vp)->v_vfsp->vfs_zone) + +#define NULLVP ((struct vnode *)0) +#define NULLVPP ((struct vnode **)0) + +#ifdef _KERNEL + +/* + * Structure used while handling asynchronous VOP_PUTPAGE operations. + */ +struct async_reqs { + struct async_reqs *a_next; /* pointer to next arg struct */ + struct vnode *a_vp; /* vnode pointer */ + u_offset_t a_off; /* offset in file */ + uint_t a_len; /* size of i/o request */ + int a_flags; /* flags to indicate operation type */ + struct cred *a_cred; /* cred pointer */ + ushort_t a_prealloced; /* set if struct is pre-allocated */ +}; + +/* + * VN_DISPOSE() -- given a page pointer, safely invoke VOP_DISPOSE(). + * Note that there is no guarantee that the page passed in will be + * freed. If that is required, then a check after calling VN_DISPOSE would + * be necessary to ensure the page was freed. + */ +#define VN_DISPOSE(pp, flag, dn, cr) { \ + if ((pp)->p_vnode != NULL && !VN_ISKAS((pp)->p_vnode)) \ + VOP_DISPOSE((pp)->p_vnode, (pp), (flag), (dn), (cr), NULL); \ + else if ((flag) == B_FREE) \ + page_free((pp), (dn)); \ + else \ + page_destroy((pp), (dn)); \ + } + +#endif /* _KERNEL */ + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_VNODE_H */ diff --git a/usr/src/lib/smbclnt/libfknsmb/i386/Makefile b/usr/src/lib/smbclnt/libfknsmb/i386/Makefile new file mode 100644 index 0000000000..40b7e3bf5d --- /dev/null +++ b/usr/src/lib/smbclnt/libfknsmb/i386/Makefile @@ -0,0 +1,18 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2017 Nexenta Systems, Inc. All rights reserved. +# + +include ../Makefile.com + +install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) diff --git a/usr/src/lib/smbclnt/libfknsmb/sparc/Makefile b/usr/src/lib/smbclnt/libfknsmb/sparc/Makefile new file mode 100644 index 0000000000..40b7e3bf5d --- /dev/null +++ b/usr/src/lib/smbclnt/libfknsmb/sparc/Makefile @@ -0,0 +1,18 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2017 Nexenta Systems, Inc. All rights reserved. +# + +include ../Makefile.com + +install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) diff --git a/usr/src/lib/smbclnt/libfknsmb/sparcv9/Makefile b/usr/src/lib/smbclnt/libfknsmb/sparcv9/Makefile new file mode 100644 index 0000000000..de1ec045d8 --- /dev/null +++ b/usr/src/lib/smbclnt/libfknsmb/sparcv9/Makefile @@ -0,0 +1,23 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2017 Nexenta Systems, Inc. All rights reserved. +# + +MACH_LDLIBS += -L$(ROOT)/usr/lib/smbfs/$(MACH64) + +include ../Makefile.com +include ../../../Makefile.lib.64 + +sparcv9_C_PICFLAGS= $(sparcv9_C_BIGPICFLAGS) + +install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64) diff --git a/usr/src/lib/smbclnt/libfksmbfs/Makefile b/usr/src/lib/smbclnt/libfksmbfs/Makefile new file mode 100644 index 0000000000..ee4ab9faf7 --- /dev/null +++ b/usr/src/lib/smbclnt/libfksmbfs/Makefile @@ -0,0 +1,16 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2017 Nexenta Systems, Inc. All rights reserved. +# + +include ../Makefile.smbclnt diff --git a/usr/src/lib/smbclnt/libfksmbfs/Makefile.com b/usr/src/lib/smbclnt/libfksmbfs/Makefile.com new file mode 100644 index 0000000000..5eb9728c12 --- /dev/null +++ b/usr/src/lib/smbclnt/libfksmbfs/Makefile.com @@ -0,0 +1,137 @@ +# +# 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 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# Copyright 2017 Nexenta Systems, Inc. All rights reserved. +# + +LIBRARY = libfksmbfs.a +VERS = .1 + +OBJS_LOCAL = \ + fksmbfs_rwlock.o \ + fake_fssub.o \ + fake_getdents.o \ + fake_lookup.o \ + fake_misc.o \ + fake_modconf.o \ + fake_nbmlock.o \ + fake_open.o \ + fake_rename.o \ + fake_rw.o \ + fake_stat.o \ + fake_unlink.o \ + fake_vfs.o \ + fake_vnode.o \ + fake_zone.o + +# See also: $SRC/uts/common/Makefile.files +# NB: Intentionally ommitted, compared w/ the above: +# smbfs_rwlock.o +# +OBJS_FS_SMBFS = \ + smbfs_vfsops.o \ + smbfs_vnops.o \ + smbfs_client.o \ + smbfs_node.o \ + smbfs_smb.o \ + smbfs_subr.o \ + smbfs_subr2.o \ + smbfs_acl.o \ + smbfs_xattr.o + +OBJS_CMN_SMBFS = \ + smbfs_ntacl.o + +OBJS_MISC = \ + acl_common.o \ + pathname.o \ + refstr.o + +OBJECTS = \ + $(OBJS_LOCAL) \ + $(OBJS_FS_SMBFS) \ + $(OBJS_CMN_SMBFS) \ + $(OBJS_MISC) + +include ../../../Makefile.lib +include ../../Makefile.lib + +# Force SOURCEDEBUG +CSOURCEDEBUGFLAGS = -g +CCSOURCEDEBUGFLAGS = -g +STRIP_STABS = : + +# Note: need our sys includes _before_ ENVCPPFLAGS, proto etc. +# Also, like Makefile.uts, reset CPPFLAGS +CPPFLAGS.first += -I../../../libfakekernel/common +CPPFLAGS.first += -I../../libfknsmb/common +CPPFLAGS.first += -I../common +CPPFLAGS= $(CPPFLAGS.first) + +INCS += -I$(SRC)/uts/common/fs/smbclnt +INCS += -I$(SRC)/uts/common +INCS += -I$(SRC)/common/smbclnt +INCS += -I$(SRC)/common + +CPPFLAGS += $(INCS) -D_REENTRANT -D_FAKE_KERNEL +CPPFLAGS += -D_FILE_OFFSET_BITS=64 +# Always want DEBUG here +CPPFLAGS += -DDEBUG + +CERRWARN += -_gcc=-Wno-switch +CERRWARN += -_gcc=-Wno-parentheses + +LDLIBS += $(MACH_LDLIBS) +LDLIBS += -lfknsmb -lfakekernel -lidmap -lcmdutils -lavl -lc + +FS_SMBFS_DIR=$(SRC)/uts/common/fs/smbclnt/smbfs +CMN_SMBFS_DIR=$(SRC)/common/smbclnt +SRCS= $(OBJS_LOCAL:%.o=$(SRCDIR)/%.c) \ + $(OBJS_FS_SMBFS:%.o=$(FS_SMBFS_DIR)/%.c) \ + $(OBJS_CMN_SMBFS:%.o=$(CMN_SMBFS_DIR)/%.c) + +all: + +pics/%.o: $(FS_SMBFS_DIR)/%.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) + +# pathname.o +pics/%.o: $(SRC)/uts/common/fs/%.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) + +# refstr.o +pics/%.o: $(SRC)/uts/common/os/%.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) + +pics/acl_common.o: $(SRC)/common/acl/acl_common.c + $(COMPILE.c) -o $@ $(SRC)/common/acl/acl_common.c + $(POST_PROCESS_O) + +.KEEP_STATE: + +include ../../Makefile.targ +include ../../../Makefile.targ diff --git a/usr/src/lib/smbclnt/libfksmbfs/amd64/Makefile b/usr/src/lib/smbclnt/libfksmbfs/amd64/Makefile new file mode 100644 index 0000000000..8b52fdf7af --- /dev/null +++ b/usr/src/lib/smbclnt/libfksmbfs/amd64/Makefile @@ -0,0 +1,23 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2017 Nexenta Systems, Inc. All rights reserved. +# + +MACH_LDLIBS += -L$(ROOT)/usr/lib/smbfs/$(MACH64) + +include ../Makefile.com +include ../../../Makefile.lib.64 + +DYNFLAGS += -R/usr/lib/smbfs/$(MACH64) + +install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64) diff --git a/usr/src/lib/smbclnt/libfksmbfs/common/fake_fssub.c b/usr/src/lib/smbclnt/libfksmbfs/common/fake_fssub.c new file mode 100644 index 0000000000..336406f095 --- /dev/null +++ b/usr/src/lib/smbclnt/libfksmbfs/common/fake_fssub.c @@ -0,0 +1,432 @@ +/* + * 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 (c) 1984, 1986, 1987, 1988, 1989 AT&T */ +/* All Rights Reserved */ + + +/* + * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2017 Joyent, Inc. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + */ + +/* + * Generic vnode operations. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* + * Tunable to limit the number of retry to recover from STALE error. + */ +int fs_estale_retry = 5; + +/* + * The associated operation is not supported by the file system. + */ +int +fs_nosys() +{ + return (ENOSYS); +} + +/* + * The associated operation is invalid (on this vnode). + */ +int +fs_inval() +{ + return (EINVAL); +} + +/* + * The associated operation is valid only for directories. + */ +int +fs_notdir() +{ + return (ENOTDIR); +} + +/* + * Free the file system specific resources. For the file systems that + * do not support the forced unmount, it will be a nop function. + */ + +/*ARGSUSED*/ +void +fs_freevfs(vfs_t *vfsp) +{ +} + +/* ARGSUSED */ +int +fs_nosys_map(struct vnode *vp, offset_t off, struct as *as, caddr_t *addrp, + size_t len, uchar_t prot, uchar_t maxprot, uint_t flags, struct cred *cr, + caller_context_t *ct) +{ + return (ENOSYS); +} + +/* ARGSUSED */ +int +fs_nosys_addmap(struct vnode *vp, offset_t off, struct as *as, caddr_t addr, + size_t len, uchar_t prot, uchar_t maxprot, uint_t flags, struct cred *cr, + caller_context_t *ct) +{ + return (ENOSYS); +} + +/* ARGSUSED */ +int +fs_nosys_poll(vnode_t *vp, short events, int anyyet, short *reventsp, + struct pollhead **phpp, caller_context_t *ct) +{ + return (ENOSYS); +} + + +/* + * The file system has nothing to sync to disk. However, the + * VFS_SYNC operation must not fail. + */ +/* ARGSUSED */ +int +fs_sync(struct vfs *vfspp, short flag, cred_t *cr) +{ + return (0); +} + +/* + * Does nothing but VOP_FSYNC must not fail. + */ +/* ARGSUSED */ +int +fs_fsync(vnode_t *vp, int syncflag, cred_t *cr, caller_context_t *ct) +{ + return (0); +} + +/* + * Does nothing but VOP_PUTPAGE must not fail. + */ +/* ARGSUSED */ +int +fs_putpage(vnode_t *vp, offset_t off, size_t len, int flags, cred_t *cr, + caller_context_t *ctp) +{ + return (0); +} + +/* + * Does nothing but VOP_IOCTL must not fail. + */ +/* ARGSUSED */ +int +fs_ioctl(vnode_t *vp, int com, intptr_t data, int flag, cred_t *cred, + int *rvalp) +{ + return (0); +} + +/* + * Read/write lock/unlock. Does nothing. + */ +/* ARGSUSED */ +int +fs_rwlock(vnode_t *vp, int write_lock, caller_context_t *ctp) +{ + return (-1); +} + +/* ARGSUSED */ +void +fs_rwunlock(vnode_t *vp, int write_lock, caller_context_t *ctp) +{ +} + +/* + * Compare two vnodes. + */ +/*ARGSUSED2*/ +int +fs_cmp(vnode_t *vp1, vnode_t *vp2, caller_context_t *ct) +{ + return (vp1 == vp2); +} + +/* + * No-op seek operation. + */ +/* ARGSUSED */ +int +fs_seek(vnode_t *vp, offset_t ooff, offset_t *noffp, caller_context_t *ct) +{ + return ((*noffp < 0 || *noffp > MAXOFFSET_T) ? EINVAL : 0); +} + +/* + * File and record locking. + */ +/* ARGSUSED */ +int +fs_frlock(vnode_t *vp, int cmd, struct flock64 *bfp, int flag, offset_t offset, + flk_callback_t *flk_cbp, cred_t *cr, caller_context_t *ct) +{ + return (ENOSYS); +} + +/* + * Allow any flags. + */ +/* ARGSUSED */ +int +fs_setfl(vnode_t *vp, int oflags, int nflags, cred_t *cr, caller_context_t *ct) +{ + return (0); +} + +/* + * Return the answer requested to poll() for non-device files. + * Only POLLIN, POLLRDNORM, and POLLOUT are recognized. + */ +struct pollhead fs_pollhd; + +/* ARGSUSED */ +int +fs_poll(vnode_t *vp, short events, int anyyet, short *reventsp, + struct pollhead **phpp, caller_context_t *ct) +{ + if (events & POLLET) { + return (EPERM); + } + + *reventsp = 0; + if (events & POLLIN) + *reventsp |= POLLIN; + if (events & POLLRDNORM) + *reventsp |= POLLRDNORM; + if (events & POLLRDBAND) + *reventsp |= POLLRDBAND; + if (events & POLLOUT) + *reventsp |= POLLOUT; + if (events & POLLWRBAND) + *reventsp |= POLLWRBAND; + if (*reventsp == 0 && !anyyet) { + *phpp = &fs_pollhd; + } + return (0); +} + +/* + * POSIX pathconf() support. + */ +/* ARGSUSED */ +int +fs_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr, + caller_context_t *ct) +{ + /* not called */ + return (EINVAL); +} + +/* + * Dispose of a page. + */ +/* ARGSUSED */ +void +fs_dispose(struct vnode *vp, page_t *pp, int fl, int dn, struct cred *cr, + caller_context_t *ct) +{ +} + +/* ARGSUSED */ +void +fs_nodispose(struct vnode *vp, page_t *pp, int fl, int dn, struct cred *cr, + caller_context_t *ct) +{ + cmn_err(CE_PANIC, "fs_nodispose invoked"); +} + +/* + * fabricate acls for file systems that do not support acls. + */ +/* ARGSUSED */ +int +fs_fab_acl(vnode_t *vp, vsecattr_t *vsecattr, int flag, cred_t *cr, + caller_context_t *ct) +{ + struct vattr vattr; + int error; + + vsecattr->vsa_aclcnt = 0; + vsecattr->vsa_aclentsz = 0; + vsecattr->vsa_aclentp = NULL; + vsecattr->vsa_dfaclcnt = 0; /* Default ACLs are not fabricated */ + vsecattr->vsa_dfaclentp = NULL; + + vattr.va_mask = AT_MODE | AT_UID | AT_GID; + if (error = VOP_GETATTR(vp, &vattr, 0, cr, ct)) + return (error); + + if (vsecattr->vsa_mask & (VSA_ACLCNT | VSA_ACL)) { + return (ENOSYS); + } + + if (vsecattr->vsa_mask & (VSA_ACECNT | VSA_ACE)) { + VERIFY(0 == acl_trivial_create(vattr.va_mode, + (vp->v_type == VDIR), (ace_t **)&vsecattr->vsa_aclentp, + &vsecattr->vsa_aclcnt)); + vsecattr->vsa_aclentsz = vsecattr->vsa_aclcnt * sizeof (ace_t); + } + + return (error); +} + +/* + * Common code for implementing DOS share reservations + */ +/* ARGSUSED */ +int +fs_shrlock(struct vnode *vp, int cmd, struct shrlock *shr, int flag, cred_t *cr, + caller_context_t *ct) +{ + return (ENOSYS); +} + +/*ARGSUSED1*/ +int +fs_vnevent_nosupport(vnode_t *vp, vnevent_t e, vnode_t *dvp, char *fnm, + caller_context_t *ct) +{ + ASSERT(vp != NULL); + return (ENOTSUP); +} + +/*ARGSUSED1*/ +int +fs_vnevent_support(vnode_t *vp, vnevent_t e, vnode_t *dvp, char *fnm, + caller_context_t *ct) +{ + ASSERT(vp != NULL); + return (0); +} + +// fs_acl_nontrivial + +/* + * Check whether we need a retry to recover from STALE error. + */ +int +fs_need_estale_retry(int retry_count) +{ + if (retry_count < fs_estale_retry) + return (1); + else + return (0); +} + +// fs_vscan... +// reparse... + +/* + * A few things from os/flock.c + */ + +/* ARGSUSED */ +void +cleanlocks(vnode_t *vp, pid_t pid, int sysid) +{ +} + +/* ARGSUSED */ +void +cleanshares(struct vnode *vp, pid_t pid) +{ +} + +/* + * convoff - converts the given data (start, whence) to the + * given whence. + */ +int +convoff(struct vnode *vp, struct flock64 *lckdat, int whence, offset_t offset) +{ + int error; + struct vattr vattr; + + if ((lckdat->l_whence == 2) || (whence == 2)) { + vattr.va_mask = AT_SIZE; + if (error = VOP_GETATTR(vp, &vattr, 0, CRED(), NULL)) + return (error); + } + + switch (lckdat->l_whence) { + case 1: + lckdat->l_start += offset; + break; + case 2: + lckdat->l_start += vattr.va_size; + /* FALLTHRU */ + case 0: + break; + default: + return (EINVAL); + } + + if (lckdat->l_start < 0) + return (EINVAL); + + switch (whence) { + case 1: + lckdat->l_start -= offset; + break; + case 2: + lckdat->l_start -= vattr.va_size; + /* FALLTHRU */ + case 0: + break; + default: + return (EINVAL); + } + + lckdat->l_whence = (short)whence; + return (0); +} diff --git a/usr/src/lib/smbclnt/libfksmbfs/common/fake_getdents.c b/usr/src/lib/smbclnt/libfksmbfs/common/fake_getdents.c new file mode 100644 index 0000000000..afa4eb1c0f --- /dev/null +++ b/usr/src/lib/smbclnt/libfksmbfs/common/fake_getdents.c @@ -0,0 +1,96 @@ +/* + * 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 (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + */ + +/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ +/* All Rights Reserved */ + +/* + * Portions of this source code were derived from Berkeley 4.3 BSD + * under license from the Regents of the University of California. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Returns count of dir entries, or -errno + */ +int +fake_getdents(vnode_t *vp, offset_t *offp, void *buf, size_t count) +{ + struct uio auio; + struct iovec aiov; + register int error; + int sink; + + if (count < sizeof (struct dirent64)) + return (-EINVAL); + + /* + * Don't let the user overcommit kernel resources. + */ + if (count > MAXGETDENTS_SIZE) + count = MAXGETDENTS_SIZE; + + if (vp->v_type != VDIR) { + return (-ENOTDIR); + } + + aiov.iov_base = buf; + aiov.iov_len = count; + auio.uio_iov = &aiov; + auio.uio_iovcnt = 1; + auio.uio_loffset = *offp; + auio.uio_segflg = UIO_USERSPACE; + auio.uio_resid = count; + auio.uio_fmode = 0; + auio.uio_extflg = UIO_COPY_CACHED; + (void) VOP_RWLOCK(vp, V_WRITELOCK_FALSE, NULL); + error = VOP_READDIR(vp, &auio, CRED(), &sink, NULL, 0); + VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL); + if (error) { + return (-error); + } + count = count - auio.uio_resid; + *offp = auio.uio_loffset; + + return (count); +} diff --git a/usr/src/lib/smbclnt/libfksmbfs/common/fake_lookup.c b/usr/src/lib/smbclnt/libfksmbfs/common/fake_lookup.c new file mode 100644 index 0000000000..8072a91b3b --- /dev/null +++ b/usr/src/lib/smbclnt/libfksmbfs/common/fake_lookup.c @@ -0,0 +1,173 @@ +/* + * 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 (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2016 Joyent, Inc. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + */ + +/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ +/* All Rights Reserved */ + +/* + * University Copyright- Copyright (c) 1982, 1986, 1988 + * The Regents of the University of California + * All Rights Reserved + * + * University Acknowledgment- Portions of this document are derived from + * software developed by the University of California, Berkeley, and its + * contributors. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +extern vnode_t *rootdir; + +/* + * Simplified variation on lookuppnvp() + */ +int +fake_lookup(vnode_t *dvp, char *path, vnode_t **vpp) +{ + char component[MAXNAMELEN]; /* buffer for component */ + pathname_t pn; + cred_t *cr; + vnode_t *cvp; /* current component vp */ + vnode_t *nvp; /* next component vp */ + char *p; + int flags = 0; + int error, len; + + bzero(&pn, sizeof (pn)); + pn.pn_buf = path; + pn.pn_path = path; + pn.pn_pathlen = strlen(path); + pn.pn_bufsize = pn.pn_pathlen + 1; + p = path; + + cr = CRED(); + cvp = (dvp != NULL) ? dvp : rootdir; + VN_HOLD(cvp); + nvp = NULL; + + while (*p != '\0') { + if (*p == '/') { + p++; + continue; + } + + len = strcspn(p, "/"); + ASSERT(len > 0); + if (len >= MAXNAMELEN) + return (EINVAL); + (void) strncpy(component, p, len); + component[len] = '\0'; + pn.pn_path = p; + pn.pn_pathlen = strlen(p); + + error = VOP_LOOKUP(cvp, component, &nvp, &pn, flags, + rootdir, cr, NULL, NULL, NULL); + VN_RELE(cvp); + if (error != 0) + return (error); + + /* Lookup gave us a hold on nvp */ + cvp = nvp; + nvp = NULL; + p += len; + } + + *vpp = cvp; + return (0); +} + +/* + * Lookup the directory and find the start of the + * last component of the given path. + */ +int +fake_lookup_dir(char *path, vnode_t **vpp, char **lastcomp) +{ + vnode_t *dvp; + char *last; + char *tpn = NULL; + int tpn_sz; + int lc_off; + int error; + + *vpp = NULL; + *lastcomp = NULL; + + tpn_sz = strlen(path) + 1; + tpn = kmem_alloc(tpn_sz, KM_SLEEP); + + /* + * Get a copy of the path, and zap the last / + */ + bcopy(path, tpn, tpn_sz); + last = strrchr(tpn, '/'); + if (last == NULL) { + lc_off = 0; + dvp = rootdir; + VN_HOLD(dvp); + error = 0; + } else { + *last++ = '\0'; + if (*last == '\0') { + error = EINVAL; + goto out; + } + error = fake_lookup(rootdir, tpn, &dvp); + if (error != 0) { + /* dir not found */ + goto out; + } + lc_off = last - tpn; + ASSERT(lc_off >= 0 && lc_off < tpn_sz); + } + *vpp = dvp; + *lastcomp = path + lc_off; + +out: + if (tpn != NULL) + kmem_free(tpn, tpn_sz); + + return (error); +} diff --git a/usr/src/lib/smbclnt/libfksmbfs/common/fake_misc.c b/usr/src/lib/smbclnt/libfksmbfs/common/fake_misc.c new file mode 100644 index 0000000000..e5ab8973b4 --- /dev/null +++ b/usr/src/lib/smbclnt/libfksmbfs/common/fake_misc.c @@ -0,0 +1,108 @@ +/* + * 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 (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017 by Delphix. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include + +volatile int ncsize = 500; /* dnlc.h */ + +static major_t devcnt = 0x280; +static kmutex_t udevlock; + +/* os/subr.c */ +major_t +getudev() +{ + static major_t next = 0; + major_t ret; + + mutex_enter(&udevlock); + if (next == 0) + next = devcnt; + if (next <= L_MAXMAJ32 && next >= devcnt) + ret = next++; + else { + cmn_err(CE_WARN, "out of major numbers"); + ret = ((major_t)-1); + } + mutex_exit(&udevlock); + return (ret); +} + +/* + * Compress 'long' device number encoding to 32-bit device number + * encoding. If it won't fit, we return failure, but set the + * device number to 32-bit NODEV for the sake of our callers. + */ +int +cmpldev(dev32_t *dst, dev_t dev) +{ +#if defined(_LP64) + if (dev == NODEV) { + *dst = (dev32_t)(-1); + } else { + major_t major = dev >> L_BITSMINOR; + minor_t minor = dev & L_MAXMIN; + + if (major > L_MAXMAJ32 || minor > L_MAXMIN32) { + *dst = (dev32_t)(-1); + return (0); + } + + *dst = (dev32_t)((major << L_BITSMINOR32) | minor); + } +#else + *dst = (dev32_t)dev; +#endif + return (1); +} + +/* os/cred.c */ +int +groupmember(gid_t gid, const cred_t *cr) +{ + if (gid == 0 || gid == 1) + return (1); + return (0); +} + +/* os/sig.c */ + +/* ARGSUSED */ +void +sigintr(k_sigset_t *smask, int intable) +{ +} + +/* ARGSUSED */ +void +sigunintr(k_sigset_t *smask) +{ +} diff --git a/usr/src/lib/smbclnt/libfksmbfs/common/fake_modconf.c b/usr/src/lib/smbclnt/libfksmbfs/common/fake_modconf.c new file mode 100644 index 0000000000..d5482f9cc5 --- /dev/null +++ b/usr/src/lib/smbclnt/libfksmbfs/common/fake_modconf.c @@ -0,0 +1,195 @@ +/* + * 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. + */ +/* + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#if 0 // XXX + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif // XXX + +#include + +/* + * Install a filesystem. + */ +/*ARGSUSED1*/ +int +fake_installfs(vfsdef_t *def) +{ + struct vfssw *vswp; + char *fsname = def->name; + int fstype; /* index into vfssw[] and vsanchor_fstype[] */ + int allocated; + int err; + + if (def->def_version != VFSDEF_VERSION) { + cmn_err(CE_WARN, "file system '%s' version mismatch", fsname); + return (ENXIO); + } + + allocated = 0; + + WLOCK_VFSSW(); + if ((vswp = vfs_getvfsswbyname(fsname)) == NULL) { + if ((vswp = allocate_vfssw(fsname)) == NULL) { + WUNLOCK_VFSSW(); + /* + * See 1095689. If this message appears, then + * we either need to make the vfssw table bigger + * statically, or make it grow dynamically. + */ + cmn_err(CE_WARN, "no room for '%s' in vfssw!", fsname); + return (ENXIO); + } + allocated = 1; + } + ASSERT(vswp != NULL); + + fstype = vswp - vfssw; /* Pointer arithmetic to get the fstype */ + + /* Turn on everything by default *except* VSW_STATS */ + vswp->vsw_flag = def->flags & ~(VSW_STATS); + + if (def->flags & VSW_HASPROTO) { + vfs_mergeopttbl(&vfs_mntopts, def->optproto, + &vswp->vsw_optproto); + } else { + vfs_copyopttbl(&vfs_mntopts, &vswp->vsw_optproto); + } + + if (def->flags & VSW_CANRWRO) { + /* + * This obviously implies VSW_CANREMOUNT. + */ + vswp->vsw_flag |= VSW_CANREMOUNT; + } + + /* vopstats ... */ + + if (def->init == NULL) + err = EFAULT; + else + err = (*(def->init))(fstype, fsname); + + if (err != 0) { + if (allocated) { + kmem_free(vswp->vsw_name, strlen(vswp->vsw_name)+1); + vswp->vsw_name = ""; + } + vswp->vsw_flag = 0; + vswp->vsw_init = NULL; + } + + vfs_unrefvfssw(vswp); + WUNLOCK_VFSSW(); + + /* ... vopstats */ + + return (err); +} + +int fake_removefs_allowed = 1; + +/* + * Remove a filesystem + */ +int +fake_removefs(vfsdef_t *def) +{ + struct vfssw *vswp; + + if (fake_removefs_allowed == 0) + return (EBUSY); + + WLOCK_VFSSW(); + if ((vswp = vfs_getvfsswbyname(def->name)) == NULL) { + WUNLOCK_VFSSW(); + cmn_err(CE_WARN, "fake_removefs: %s not in vfssw", + def->name); + return (EINVAL); + } + if (vswp->vsw_count != 1) { + vfs_unrefvfssw(vswp); + WUNLOCK_VFSSW(); + return (EBUSY); + } + + /* + * A mounted filesystem could still have vsw_count = 0 + * so we must check whether anyone is actually using our ops + */ + if (vfs_opsinuse(&vswp->vsw_vfsops)) { + vfs_unrefvfssw(vswp); + WUNLOCK_VFSSW(); + return (EBUSY); + } + + vfs_freeopttbl(&vswp->vsw_optproto); + vswp->vsw_optproto.mo_count = 0; + + vswp->vsw_flag = 0; + vswp->vsw_init = NULL; + vfs_unrefvfssw(vswp); + WUNLOCK_VFSSW(); + return (0); +} diff --git a/usr/src/lib/smbclnt/libfksmbfs/common/fake_nbmlock.c b/usr/src/lib/smbclnt/libfksmbfs/common/fake_nbmlock.c new file mode 100644 index 0000000000..c1b5ef63e8 --- /dev/null +++ b/usr/src/lib/smbclnt/libfksmbfs/common/fake_nbmlock.c @@ -0,0 +1,124 @@ +/* + * 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 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + */ + +/* + * Utility routines and top-level conflict detection code for NBMAND + * locks. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Enter the critical region for synchronizing I/O requests with lock/share + * requests. "mode" specifies whether the caller intends to update + * lock/share state (as opposed to just query it). + */ + +void +nbl_start_crit(vnode_t *vp, krw_t mode) +{ + rw_enter(&vp->v_nbllock, mode); +} + +/* + * Leave the critical region. + */ + +void +nbl_end_crit(vnode_t *vp) +{ + rw_exit(&vp->v_nbllock); +} + +/* + * Return non-zero if some thread is in the critical region. + * Note that this is appropriate for use in ASSERT()s only. + */ + +int +nbl_in_crit(vnode_t *vp) +{ + return (RW_LOCK_HELD(&vp->v_nbllock)); +} + +/* + * Returns non-zero if we need to look further for an NBMAND lock or + * share conflict. + */ +int +nbl_need_check(vnode_t *vp) +{ + /* + * Currently we only check if NBMAND locks/shares are allowed on + * the filesystem. An option for the future would be to have a + * flag on the vnode, though the locking for that can get tricky. + */ + return ((vp->v_vfsp) && (vp->v_vfsp->vfs_flag & VFS_NBMAND)); +} + +/* No locks, so no conflicts. */ +int +nbl_conflict(vnode_t *vp, + nbl_op_t op, /* attempted operation */ + u_offset_t offset, /* ignore if not I/O */ + ssize_t length, /* ignore if not I/O */ + int svmand, /* System V mandatory locking */ + caller_context_t *ct) /* caller context */ +{ + ASSERT(nbl_in_crit(vp)); + + return (0); +} + +/* + * Determine if the given file has mode bits for System V mandatory locks. + * If there was an error, the errno value is returned. Otherwise, zero is + * returned and *svp is set appropriately (non-zero for mandatory locks, + * zero for no mandatory locks). + */ + +int +nbl_svmand(vnode_t *vp, cred_t *cr, int *svp) +{ + struct vattr va; + int error; + + va.va_mask = AT_MODE; + error = VOP_GETATTR(vp, &va, 0, cr, NULL); + if (error != 0) + return (error); + + *svp = MANDLOCK(vp, va.va_mode); + return (0); +} diff --git a/usr/src/lib/smbclnt/libfksmbfs/common/fake_open.c b/usr/src/lib/smbclnt/libfksmbfs/common/fake_open.c new file mode 100644 index 0000000000..169197ae03 --- /dev/null +++ b/usr/src/lib/smbclnt/libfksmbfs/common/fake_open.c @@ -0,0 +1,340 @@ +/* + * 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 (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2017, Joyent, Inc. + * Copyright (c) 2011, 2017 by Delphix. All rights reserved. + * Copyright 2018 Nexenta Systems, Inc. All rights reserved. + */ + +/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ +/* All Rights Reserved */ + +/* + * University Copyright- Copyright (c) 1982, 1986, 1988 + * The Regents of the University of California + * All Rights Reserved + * + * University Acknowledgment- Portions of this document are derived from + * software developed by the University of California, Berkeley, and its + * contributors. + */ + +/* + * Portions of code from both of: + * syscall/open.c + * fs/vnode.c + * heavily modified for this use. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* close and release */ +int +vn_close_rele(vnode_t *vp, int flag) +{ + int error; + + error = VOP_CLOSE(vp, flag, 0, 0, CRED(), NULL); + vn_rele(vp); + + return (error); +} + +/* + * Open/create a vnode. + * This may be callable by the kernel, the only known use + * of user context being that the current user credentials + * are used for permissions. crwhy is defined iff filemode & FCREAT. + */ +int +vn_open( + char *pnamep, + enum uio_seg seg, + int filemode, + int createmode, + struct vnode **vpp, + enum create crwhy, + mode_t umask) +{ + struct vnode *vp; + int mode; + int accessflags; + int error; + int open_done = 0; + struct vattr vattr; + int estale_retry = 0; + + mode = 0; + accessflags = 0; + if (filemode & FREAD) + mode |= VREAD; + if (filemode & (FWRITE|FTRUNC)) + mode |= VWRITE; + if (filemode & (FSEARCH|FEXEC|FXATTRDIROPEN)) + mode |= VEXEC; + + if (filemode & FAPPEND) + accessflags |= V_APPEND; + +top: + if (filemode & FCREAT) { + enum vcexcl excl; + + /* + * Wish to create a file. + */ + vattr.va_type = VREG; + vattr.va_mode = createmode; + vattr.va_mask = AT_TYPE|AT_MODE; + if (filemode & FTRUNC) { + vattr.va_size = 0; + vattr.va_mask |= AT_SIZE; + } + if (filemode & FEXCL) + excl = EXCL; + else + excl = NONEXCL; + + if ((error = + vn_create(pnamep, seg, &vattr, excl, mode, &vp, crwhy, + (filemode & ~(FTRUNC|FEXCL)), umask)) != 0) + return (error); + } else { + /* + * Wish to open a file. Just look it up. + * Was lookupnameat() + */ + if ((error = fake_lookup(NULL, pnamep, &vp)) != 0) { + if ((error == ESTALE) && + fs_need_estale_retry(estale_retry++)) + goto top; + return (error); + } + + /* + * Want the XATTRDIR under it? + */ + if (filemode & FXATTRDIROPEN) { + vnode_t *xvp = NULL; + error = VOP_LOOKUP(vp, NULL, &xvp, NULL, + LOOKUP_XATTR, rootdir, CRED(), NULL, + NULL, NULL); + VN_RELE(vp); + vp = xvp; + /* continue with vp */ + } + + /* + * Can't write directories, active texts, or + * read-only filesystems. Can't truncate files + * on which mandatory locking is in effect. + */ + if (filemode & (FWRITE|FTRUNC)) { + if (vp->v_type == VDIR) { + error = EISDIR; + goto out; + } + } + /* + * Check permissions. + */ + if (error = VOP_ACCESS(vp, mode, accessflags, CRED(), NULL)) + goto out; + /* + * Require FSEARCH to return a directory. + * Require FEXEC to return a regular file. + */ + if ((filemode & FSEARCH) && vp->v_type != VDIR) { + error = ENOTDIR; + goto out; + } + if ((filemode & FEXEC) && vp->v_type != VREG) { + error = ENOEXEC; + goto out; + } + } + + /* + * Do remaining checks for FNOFOLLOW and FNOLINKS. + */ + if ((filemode & FNOFOLLOW) && vp->v_type == VLNK) { + error = ELOOP; + goto out; + } + if (filemode & FNOLINKS) { + vattr.va_mask = AT_NLINK; + if ((error = VOP_GETATTR(vp, &vattr, 0, CRED(), NULL))) { + goto out; + } + if (vattr.va_nlink != 1) { + error = EMLINK; + goto out; + } + } + + /* + * Opening a socket corresponding to the AF_UNIX pathname + * in the filesystem name space is not supported... + */ + if (vp->v_type == VSOCK) { + error = EOPNOTSUPP; + goto out; + } + + /* + * Do opening protocol. + */ + error = VOP_OPEN(&vp, filemode, CRED(), NULL); + if (error) + goto out; + open_done = 1; + + /* + * Truncate if required. + */ + if ((filemode & FTRUNC) && !(filemode & FCREAT)) { + vattr.va_size = 0; + vattr.va_mask = AT_SIZE; + if ((error = VOP_SETATTR(vp, &vattr, 0, CRED(), NULL)) != 0) + goto out; + } +out: + ASSERT(vp->v_count > 0); + + if (error) { + if (open_done) { + (void) VOP_CLOSE(vp, filemode, 1, (offset_t)0, CRED(), + NULL); + open_done = 0; + } + VN_RELE(vp); + } else + *vpp = vp; + return (error); +} + + +/* + * Create a vnode (makenode). + */ +int +vn_create( + char *pnamep, + enum uio_seg seg, + struct vattr *vap, + enum vcexcl excl, + int mode, + struct vnode **vpp, + enum create why, + int flag, + mode_t umask) +{ + struct vnode *dvp = NULL; /* ptr to parent dir vnode */ + char *lastcomp = NULL; + int error; + + ASSERT((vap->va_mask & (AT_TYPE|AT_MODE)) == (AT_TYPE|AT_MODE)); + + flag &= ~(FNOFOLLOW|FNOLINKS); + + *vpp = NULL; + + /* + * Lookup directory and last component + */ + error = fake_lookup_dir(pnamep, &dvp, &lastcomp); + if (error != 0) { + /* dir not found */ + return (error); + } + + /* + * If default ACLs are defined for the directory don't apply the + * umask if umask is passed. + */ + + if (umask) { + /* + * Apply the umask if no default ACLs... + */ + vap->va_mode &= ~umask; + } + + if (dvp->v_vfsp->vfs_flag & VFS_RDONLY) { + error = EROFS; + goto out; + } + + /* + * Call mkdir() if specified, otherwise create(). + */ + if (why == CRMKDIR) { + /* + * N.B., if vn_createat() ever requests + * case-insensitive behavior then it will need + * to be passed to VOP_MKDIR(). VOP_CREATE() + * will already get it via "flag" + */ + error = VOP_MKDIR(dvp, lastcomp, vap, vpp, CRED(), + NULL, 0, NULL); + } else { + error = VOP_CREATE(dvp, lastcomp, vap, + excl, mode, vpp, CRED(), flag, NULL, NULL); + } + +out: + if (dvp != NULL) + VN_RELE(dvp); + + return (error); +} diff --git a/usr/src/lib/smbclnt/libfksmbfs/common/fake_rename.c b/usr/src/lib/smbclnt/libfksmbfs/common/fake_rename.c new file mode 100644 index 0000000000..5ff428593d --- /dev/null +++ b/usr/src/lib/smbclnt/libfksmbfs/common/fake_rename.c @@ -0,0 +1,123 @@ +/* + * 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 (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2017, Joyent, Inc. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + * Copyright (c) 2011, 2017 by Delphix. All rights reserved. + */ + +/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ +/* All Rights Reserved */ + +/* + * University Copyright- Copyright (c) 1982, 1986, 1988 + * The Regents of the University of California + * All Rights Reserved + * + * University Acknowledgment- Portions of this document are derived from + * software developed by the University of California, Berkeley, and its + * contributors. + */ + +/* + * Portions of code from both of: + * syscall/rename.c + * fs/vnode.c + * heavily modified for this use. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +int +fake_rename(char *frompath, char *topath) +{ + vnode_t *fdvp = NULL; + vnode_t *tdvp = NULL; + char *fname = NULL; + char *tname = NULL; + int error; + + /* + * Lookup to and from directories. + */ + if ((error = fake_lookup_dir(frompath, &fdvp, &fname)) != 0) + goto out; + if ((error = fake_lookup_dir(topath, &tdvp, &tname)) != 0) + goto out; + + /* + * Make sure both the from vnode directory and the to directory + * are in the same vfs and the to directory is writable. + */ + if (fdvp != tdvp && fdvp->v_vfsp != tdvp->v_vfsp) { + error = EXDEV; + goto out; + } + if (tdvp->v_vfsp->vfs_flag & VFS_RDONLY) { + error = EROFS; + goto out; + } + + /* + * Do the rename. + */ + error = VOP_RENAME(fdvp, fname, tdvp, tname, CRED(), NULL, 0); + +out: + if (fdvp) + VN_RELE(fdvp); + if (tdvp) + VN_RELE(tdvp); + + return (error); +} diff --git a/usr/src/lib/smbclnt/libfksmbfs/common/fake_rw.c b/usr/src/lib/smbclnt/libfksmbfs/common/fake_rw.c new file mode 100644 index 0000000000..33a63a16dc --- /dev/null +++ b/usr/src/lib/smbclnt/libfksmbfs/common/fake_rw.c @@ -0,0 +1,203 @@ +/* + * 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 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * Copyright (c) 2015, Joyent, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + */ + +/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ +/* All Rights Reserved */ + +/* + * Portions of this source code were derived from Berkeley 4.3 BSD + * under license from the Regents of the University of California. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define set_errno(e) (-(e)) + +ssize_t +fake_pread(vnode_t *vp, void *cbuf, size_t count, off_t offset) +{ + struct uio auio; + struct iovec aiov; + int fflag, ioflag, rwflag; + ssize_t bcount; + int error = 0; + u_offset_t fileoff = (u_offset_t)(ulong_t)offset; + const u_offset_t maxoff = MAXOFF32_T; + + if ((bcount = (ssize_t)count) < 0) + return (set_errno(EINVAL)); + fflag = FREAD; + + rwflag = 0; + + if (vp->v_type == VREG) { + + if (bcount == 0) + goto out; + + /* + * Return EINVAL if an invalid offset comes to pread. + * Negative offset from user will cause this error. + */ + + if (fileoff > maxoff) { + error = EINVAL; + goto out; + } + /* + * Limit offset such that we don't read or write + * a file beyond the maximum offset representable in + * an off_t structure. + */ + if (fileoff + bcount > maxoff) + bcount = (ssize_t)((offset_t)maxoff - fileoff); + } else if (vp->v_type == VFIFO) { + error = ESPIPE; + goto out; + } + + aiov.iov_base = cbuf; + aiov.iov_len = bcount; + (void) VOP_RWLOCK(vp, rwflag, NULL); + auio.uio_loffset = fileoff; + auio.uio_iov = &aiov; + auio.uio_iovcnt = 1; + auio.uio_resid = bcount; + auio.uio_segflg = UIO_USERSPACE; + auio.uio_llimit = MAXOFFSET_T; + auio.uio_fmode = fflag; + auio.uio_extflg = UIO_COPY_CACHED; + + ioflag = auio.uio_fmode & (FAPPEND|FSYNC|FDSYNC|FRSYNC); + + /* If read sync is not asked for, filter sync flags */ + if ((ioflag & FRSYNC) == 0) + ioflag &= ~(FSYNC|FDSYNC); + error = VOP_READ(vp, &auio, ioflag, CRED(), NULL); + bcount -= auio.uio_resid; + VOP_RWUNLOCK(vp, rwflag, NULL); + + if (error == EINTR && bcount != 0) + error = 0; +out: + if (error) + return (set_errno(error)); + return (bcount); +} + +ssize_t +fake_pwrite(vnode_t *vp, void *cbuf, size_t count, off_t offset) +{ + struct uio auio; + struct iovec aiov; + int fflag, ioflag, rwflag; + ssize_t bcount; + int error = 0; + u_offset_t fileoff = (u_offset_t)(ulong_t)offset; + const u_offset_t maxoff = MAXOFF32_T; + + if ((bcount = (ssize_t)count) < 0) + return (set_errno(EINVAL)); + fflag = FREAD | FWRITE; + + rwflag = 1; + + if (vp->v_type == VREG) { + + if (bcount == 0) + goto out; + + /* + * return EINVAL for offsets that cannot be + * represented in an off_t. + */ + if (fileoff > maxoff) { + error = EINVAL; + goto out; + } + /* + * Don't allow pwrite to cause file sizes to exceed + * maxoff. + */ + if (fileoff == maxoff) { + error = EFBIG; + goto out; + } + if (fileoff + count > maxoff) + bcount = (ssize_t)((u_offset_t)maxoff - fileoff); + } else if (vp->v_type == VFIFO) { + error = ESPIPE; + goto out; + } + + aiov.iov_base = cbuf; + aiov.iov_len = bcount; + (void) VOP_RWLOCK(vp, rwflag, NULL); + auio.uio_loffset = fileoff; + auio.uio_iov = &aiov; + auio.uio_iovcnt = 1; + auio.uio_resid = bcount; + auio.uio_segflg = UIO_USERSPACE; + auio.uio_llimit = MAXOFFSET_T; + auio.uio_fmode = fflag; + auio.uio_extflg = UIO_COPY_CACHED; + + /* + * The SUSv4 POSIX specification states: + * The pwrite() function shall be equivalent to write(), except + * that it writes into a given position and does not change + * the file offset (regardless of whether O_APPEND is set). + * To make this be true, we omit the FAPPEND flag from ioflag. + */ + ioflag = auio.uio_fmode & (FSYNC|FDSYNC|FRSYNC); + + error = VOP_WRITE(vp, &auio, ioflag, CRED(), NULL); + bcount -= auio.uio_resid; + VOP_RWUNLOCK(vp, rwflag, NULL); + + if (error == EINTR && bcount != 0) + error = 0; +out: + if (error) + return (set_errno(error)); + return (bcount); +} diff --git a/usr/src/lib/smbclnt/libfksmbfs/common/fake_stat.c b/usr/src/lib/smbclnt/libfksmbfs/common/fake_stat.c new file mode 100644 index 0000000000..5b074e2be9 --- /dev/null +++ b/usr/src/lib/smbclnt/libfksmbfs/common/fake_stat.c @@ -0,0 +1,96 @@ +/* + * 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 (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + */ + +/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ +/* All Rights Reserved */ + +/* + * Portions of this source code were derived from Berkeley 4.3 BSD + * under license from the Regents of the University of California. + */ + +/* + * Get file attribute information through a file name or a file descriptor. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +int +fake_stat(vnode_t *vp, struct stat64 *ubp, int flag) +{ + cred_t *cr = CRED(); + struct vfssw *vswp; + struct stat64 lsb; + vattr_t vattr; + int error; + + vattr.va_mask = AT_STAT | AT_NBLOCKS | AT_BLKSIZE | AT_SIZE; + if (error = VOP_GETATTR(vp, &vattr, flag, cr, NULL)) + return (error); + + bzero(&lsb, sizeof (lsb)); + lsb.st_dev = vattr.va_fsid; + lsb.st_ino = vattr.va_nodeid; + lsb.st_mode = VTTOIF(vattr.va_type) | vattr.va_mode; + lsb.st_nlink = vattr.va_nlink; + lsb.st_uid = vattr.va_uid; + lsb.st_gid = vattr.va_gid; + lsb.st_rdev = vattr.va_rdev; + lsb.st_size = vattr.va_size; + lsb.st_atim = vattr.va_atime; + lsb.st_mtim = vattr.va_mtime; + lsb.st_ctim = vattr.va_ctime; + lsb.st_blksize = vattr.va_blksize; + lsb.st_blocks = vattr.va_nblocks; + if (vp->v_vfsp != NULL) { + vswp = &vfssw[vp->v_vfsp->vfs_fstype]; + if (vswp->vsw_name && *vswp->vsw_name) + (void) strcpy(lsb.st_fstype, vswp->vsw_name); + } + if (copyout(&lsb, ubp, sizeof (lsb))) + return (EFAULT); + return (0); +} diff --git a/usr/src/lib/smbclnt/libfksmbfs/common/fake_unlink.c b/usr/src/lib/smbclnt/libfksmbfs/common/fake_unlink.c new file mode 100644 index 0000000000..4c35620d29 --- /dev/null +++ b/usr/src/lib/smbclnt/libfksmbfs/common/fake_unlink.c @@ -0,0 +1,91 @@ +/* + * 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 (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + */ + +/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ +/* All Rights Reserved */ + +/* + * Portions of this source code were derived from Berkeley 4.3 BSD + * under license from the Regents of the University of California. + */ + +/* + * Modified version of syscall/unlink.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* + * Unlink a file from a directory + * Like syscall/unlinkat.c + */ +int +fake_unlink(char *path, int flags) +{ + vnode_t *dvp = NULL; + char *lastcomp = NULL; + int error; + + if (path == NULL) + return (EFAULT); + + error = fake_lookup_dir(path, &dvp, &lastcomp); + if (error != 0) + return (error); + + /* + * Some logic from vn_removeat() here + */ + if (dvp->v_vfsp->vfs_flag & VFS_RDONLY) { + error = EROFS; + goto out; + } + + if (flags == AT_REMOVEDIR) { + error = VOP_RMDIR(dvp, lastcomp, NULL, CRED(), NULL, 0); + } else { + error = VOP_REMOVE(dvp, lastcomp, CRED(), NULL, 0); + } + +out: + if (dvp != NULL) + VN_RELE(dvp); + + return (error); +} diff --git a/usr/src/lib/smbclnt/libfksmbfs/common/fake_vfs.c b/usr/src/lib/smbclnt/libfksmbfs/common/fake_vfs.c new file mode 100644 index 0000000000..cc63b01ee1 --- /dev/null +++ b/usr/src/lib/smbclnt/libfksmbfs/common/fake_vfs.c @@ -0,0 +1,2155 @@ +/* + * 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 (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2016 Joyent, Inc. + * Copyright 2016 Toomas Soome + * Copyright (c) 2016 by Delphix. All rights reserved. + * Copyright 2017 RackTop Systems. + * Copyright 2018 Nexenta Systems, Inc. + */ + +/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ +/* All Rights Reserved */ + +/* + * University Copyright- Copyright (c) 1982, 1986, 1988 + * The Regents of the University of California + * All Rights Reserved + * + * University Acknowledgment- Portions of this document are derived from + * software developed by the University of California, Berkeley, and its + * contributors. + */ + +/* + * This file contains those functions from fs/vfs.c that can be + * used with relatively little change. Functions that differ + * significantly from that are in other files. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static void vfs_clearmntopt_nolock(mntopts_t *, const char *, int); +static void vfs_setmntopt_nolock(mntopts_t *, const char *, + const char *, int, int); +static int vfs_optionisset_nolock(const mntopts_t *, const char *, char **); +// static void vfs_freemnttab(struct vfs *); +static void vfs_freeopt(mntopt_t *); +static void vfs_swapopttbl_nolock(mntopts_t *, mntopts_t *); +static void vfs_swapopttbl(mntopts_t *, mntopts_t *); +static void vfs_copyopttbl_extend(const mntopts_t *, mntopts_t *, int); +// static void vfs_createopttbl_extend(mntopts_t *, const char *, +// const mntopts_t *); +// static char **vfs_copycancelopt_extend(char **const, int); +static void vfs_freecancelopt(char **); + +/* + * VFS global data. + */ +vnode_t *rootdir; /* pointer to root inode vnode. */ +struct vfs *rootvfs = NULL; /* pointer to root vfs; head of VFS list. */ +static krwlock_t vfslist; +struct vfs *zone_vfslist; /* list of FS's mounted in zone */ + +/* from os/vfs_conf.c */ +const int nfstype = 5; +struct vfssw vfssw[10] = { + { "BADVFS" }, /* 0:invalid */ + { "" }, /* reserved for loadable fs */ + { "" }, + { "" }, + { "" }, +}; + +/* + * Table for generic options recognized in the VFS layer and acted + * on at this level before parsing file system specific options. + * The nosuid option is stronger than any of the devices and setuid + * options, so those are canceled when nosuid is seen. + * + * All options which are added here need to be added to the + * list of standard options in usr/src/cmd/fs.d/fslib.c as well. + */ +/* + * VFS Mount options table + */ +static char *ro_cancel[] = { MNTOPT_RW, NULL }; +static char *rw_cancel[] = { MNTOPT_RO, NULL }; +static char *suid_cancel[] = { MNTOPT_NOSUID, NULL }; +static char *nosuid_cancel[] = { MNTOPT_SUID, MNTOPT_DEVICES, MNTOPT_NODEVICES, + MNTOPT_NOSETUID, MNTOPT_SETUID, NULL }; +static char *devices_cancel[] = { MNTOPT_NODEVICES, NULL }; +static char *nodevices_cancel[] = { MNTOPT_DEVICES, NULL }; +static char *setuid_cancel[] = { MNTOPT_NOSETUID, NULL }; +static char *nosetuid_cancel[] = { MNTOPT_SETUID, NULL }; +static char *nbmand_cancel[] = { MNTOPT_NONBMAND, NULL }; +static char *nonbmand_cancel[] = { MNTOPT_NBMAND, NULL }; +static char *exec_cancel[] = { MNTOPT_NOEXEC, NULL }; +static char *noexec_cancel[] = { MNTOPT_EXEC, NULL }; + +static const mntopt_t mntopts[] = { +/* + * option name cancel options default arg flags + */ + { MNTOPT_REMOUNT, NULL, NULL, + MO_NODISPLAY, (void *)0 }, + { MNTOPT_RO, ro_cancel, NULL, 0, + (void *)0 }, + { MNTOPT_RW, rw_cancel, NULL, 0, + (void *)0 }, + { MNTOPT_SUID, suid_cancel, NULL, 0, + (void *)0 }, + { MNTOPT_NOSUID, nosuid_cancel, NULL, 0, + (void *)0 }, + { MNTOPT_DEVICES, devices_cancel, NULL, 0, + (void *)0 }, + { MNTOPT_NODEVICES, nodevices_cancel, NULL, 0, + (void *)0 }, + { MNTOPT_SETUID, setuid_cancel, NULL, 0, + (void *)0 }, + { MNTOPT_NOSETUID, nosetuid_cancel, NULL, 0, + (void *)0 }, + { MNTOPT_NBMAND, nbmand_cancel, NULL, 0, + (void *)0 }, + { MNTOPT_NONBMAND, nonbmand_cancel, NULL, 0, + (void *)0 }, + { MNTOPT_EXEC, exec_cancel, NULL, 0, + (void *)0 }, + { MNTOPT_NOEXEC, noexec_cancel, NULL, 0, + (void *)0 }, +}; + +const mntopts_t vfs_mntopts = { + sizeof (mntopts) / sizeof (mntopt_t), + (mntopt_t *)&mntopts[0] +}; + +/* + * File system operation dispatch functions. + */ + +int +fsop_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr) +{ + return (*(vfsp)->vfs_op->vfs_mount)(vfsp, mvp, uap, cr); +} + +int +fsop_unmount(vfs_t *vfsp, int flag, cred_t *cr) +{ + return (*(vfsp)->vfs_op->vfs_unmount)(vfsp, flag, cr); +} + +int +fsop_root(vfs_t *vfsp, vnode_t **vpp) +{ + return ((*(vfsp)->vfs_op->vfs_root)(vfsp, vpp)); +} + +int +fsop_statfs(vfs_t *vfsp, statvfs64_t *sp) +{ + return (*(vfsp)->vfs_op->vfs_statvfs)(vfsp, sp); +} + +int +fsop_sync(vfs_t *vfsp, short flag, cred_t *cr) +{ + return (*(vfsp)->vfs_op->vfs_sync)(vfsp, flag, cr); +} + +int +fsop_vget(vfs_t *vfsp, vnode_t **vpp, fid_t *fidp) +{ + return (*(vfsp)->vfs_op->vfs_vget)(vfsp, vpp, fidp); +} + +int +fsop_mountroot(vfs_t *vfsp, enum whymountroot reason) +{ + return (*(vfsp)->vfs_op->vfs_mountroot)(vfsp, reason); +} + +void +fsop_freefs(vfs_t *vfsp) +{ + (*(vfsp)->vfs_op->vfs_freevfs)(vfsp); +} + +int +fsop_vnstate(vfs_t *vfsp, vnode_t *vp, vntrans_t nstate) +{ + return ((*(vfsp)->vfs_op->vfs_vnstate)(vfsp, vp, nstate)); +} + +int +fsop_sync_by_kind(int fstype, short flag, cred_t *cr) +{ + ASSERT((fstype >= 0) && (fstype < nfstype)); + + if (ALLOCATED_VFSSW(&vfssw[fstype]) && VFS_INSTALLED(&vfssw[fstype])) + return (*vfssw[fstype].vsw_vfsops.vfs_sync) (NULL, flag, cr); + else + return (ENOTSUP); +} + +/* + * File system initialization. vfs_setfsops() must be called from a file + * system's init routine. + */ + +static int +fs_copyfsops(const fs_operation_def_t *template, vfsops_t *actual, + int *unused_ops) +{ + static const fs_operation_trans_def_t vfs_ops_table[] = { + VFSNAME_MOUNT, offsetof(vfsops_t, vfs_mount), + fs_nosys, fs_nosys, + + VFSNAME_UNMOUNT, offsetof(vfsops_t, vfs_unmount), + fs_nosys, fs_nosys, + + VFSNAME_ROOT, offsetof(vfsops_t, vfs_root), + fs_nosys, fs_nosys, + + VFSNAME_STATVFS, offsetof(vfsops_t, vfs_statvfs), + fs_nosys, fs_nosys, + + VFSNAME_SYNC, offsetof(vfsops_t, vfs_sync), + (fs_generic_func_p) fs_sync, + (fs_generic_func_p) fs_sync, /* No errors allowed */ + + VFSNAME_VGET, offsetof(vfsops_t, vfs_vget), + fs_nosys, fs_nosys, + + VFSNAME_MOUNTROOT, offsetof(vfsops_t, vfs_mountroot), + fs_nosys, fs_nosys, + + VFSNAME_FREEVFS, offsetof(vfsops_t, vfs_freevfs), + (fs_generic_func_p)fs_freevfs, + (fs_generic_func_p)fs_freevfs, /* Shouldn't fail */ + + VFSNAME_VNSTATE, offsetof(vfsops_t, vfs_vnstate), + (fs_generic_func_p)fs_nosys, + (fs_generic_func_p)fs_nosys, + + NULL, 0, NULL, NULL + }; + + return (fs_build_vector(actual, unused_ops, vfs_ops_table, template)); +} + +/* zfs_boot_init() */ + +int +vfs_setfsops(int fstype, const fs_operation_def_t *template, vfsops_t **actual) +{ + int error; + int unused_ops; + + /* + * Verify that fstype refers to a valid fs. Note that + * 0 is valid since it's used to set "stray" ops. + */ + if ((fstype < 0) || (fstype >= nfstype)) + return (EINVAL); + + if (!ALLOCATED_VFSSW(&vfssw[fstype])) + return (EINVAL); + + /* Set up the operations vector. */ + + error = fs_copyfsops(template, &vfssw[fstype].vsw_vfsops, &unused_ops); + + if (error != 0) + return (error); + + vfssw[fstype].vsw_flag |= VSW_INSTALLED; + + if (actual != NULL) + *actual = &vfssw[fstype].vsw_vfsops; + +#if DEBUG + if (unused_ops != 0) + cmn_err(CE_WARN, "vfs_setfsops: %s: %d operations supplied " + "but not used", vfssw[fstype].vsw_name, unused_ops); +#endif + + return (0); +} + +int +vfs_makefsops(const fs_operation_def_t *template, vfsops_t **actual) +{ + int error; + int unused_ops; + + *actual = (vfsops_t *)kmem_alloc(sizeof (vfsops_t), KM_SLEEP); + + error = fs_copyfsops(template, *actual, &unused_ops); + if (error != 0) { + kmem_free(*actual, sizeof (vfsops_t)); + *actual = NULL; + return (error); + } + + return (0); +} + +/* + * Free a vfsops structure created as a result of vfs_makefsops(). + * NOTE: For a vfsops structure initialized by vfs_setfsops(), use + * vfs_freevfsops_by_type(). + */ +void +vfs_freevfsops(vfsops_t *vfsops) +{ + kmem_free(vfsops, sizeof (vfsops_t)); +} + +/* + * Since the vfsops structure is part of the vfssw table and wasn't + * really allocated, we're not really freeing anything. We keep + * the name for consistency with vfs_freevfsops(). We do, however, + * need to take care of a little bookkeeping. + * NOTE: For a vfsops structure created by vfs_setfsops(), use + * vfs_freevfsops_by_type(). + */ +int +vfs_freevfsops_by_type(int fstype) +{ + + /* Verify that fstype refers to a loaded fs (and not fsid 0). */ + if ((fstype <= 0) || (fstype >= nfstype)) + return (EINVAL); + + WLOCK_VFSSW(); + if ((vfssw[fstype].vsw_flag & VSW_INSTALLED) == 0) { + WUNLOCK_VFSSW(); + return (EINVAL); + } + + vfssw[fstype].vsw_flag &= ~VSW_INSTALLED; + WUNLOCK_VFSSW(); + + return (0); +} + +/* Support routines used to reference vfs_op */ + +/* Set the operations vector for a vfs */ +void +vfs_setops(vfs_t *vfsp, vfsops_t *vfsops) +{ + + ASSERT(vfsp != NULL); + ASSERT(vfsops != NULL); + + vfsp->vfs_op = vfsops; +} + +/* Retrieve the operations vector for a vfs */ +vfsops_t * +vfs_getops(vfs_t *vfsp) +{ + + ASSERT(vfsp != NULL); + + return (vfsp->vfs_op); +} + +/* + * Returns non-zero (1) if the vfsops matches that of the vfs. + * Returns zero (0) if not. + */ +int +vfs_matchops(vfs_t *vfsp, vfsops_t *vfsops) +{ + return (vfs_getops(vfsp) == vfsops); +} + +/* + * Returns non-zero (1) if the file system has installed a non-default, + * non-error vfs_sync routine. Returns zero (0) otherwise. + */ +int +vfs_can_sync(vfs_t *vfsp) +{ + /* vfs_sync() routine is not the default/error function */ + return (vfs_getops(vfsp)->vfs_sync != fs_sync); +} + +/* + * Initialize a vfs structure. + */ +void +vfs_init(vfs_t *vfsp, vfsops_t *op, void *data) +{ + /* Always do full init, like vfs_alloc() */ + bzero(vfsp, sizeof (vfs_t)); + vfsp->vfs_count = 0; + vfsp->vfs_next = vfsp; + vfsp->vfs_prev = vfsp; + vfsp->vfs_zone_next = vfsp; + vfsp->vfs_zone_prev = vfsp; + vfsp->vfs_lofi_id = 0; + sema_init(&vfsp->vfs_reflock, 1, NULL, SEMA_DEFAULT, NULL); + vfsimpl_setup(vfsp); + vfsp->vfs_data = (data); + vfs_setops((vfsp), (op)); +} + +/* + * Allocate and initialize the vfs implementation private data + * structure, vfs_impl_t. + */ +void +vfsimpl_setup(vfs_t *vfsp) +{ + int i; + + if (vfsp->vfs_implp != NULL) { + return; + } + + vfsp->vfs_implp = kmem_alloc(sizeof (vfs_impl_t), KM_SLEEP); + /* Note that these are #define'd in vfs.h */ + vfsp->vfs_vskap = NULL; + vfsp->vfs_fstypevsp = NULL; + + /* Set size of counted array, then zero the array */ + vfsp->vfs_featureset[0] = VFS_FEATURE_MAXSZ - 1; + for (i = 1; i < VFS_FEATURE_MAXSZ; i++) { + vfsp->vfs_featureset[i] = 0; + } +} + +/* + * Release the vfs_impl_t structure, if it exists. Some unbundled + * filesystems may not use the newer version of vfs and thus + * would not contain this implementation private data structure. + */ +void +vfsimpl_teardown(vfs_t *vfsp) +{ + vfs_impl_t *vip = vfsp->vfs_implp; + + if (vip == NULL) + return; + + kmem_free(vfsp->vfs_implp, sizeof (vfs_impl_t)); + vfsp->vfs_implp = NULL; +} + +/* + * VFS system calls: mount, umount, syssync, statfs, fstatfs, statvfs, + * fstatvfs, and sysfs moved to common/syscall. + */ + +// vfs_sync, sync + +/* + * External routines. + */ + +krwlock_t vfssw_lock; /* lock accesses to vfssw */ + +/* + * Lock for accessing the vfs linked list. Initialized in vfs_mountroot(), + * but otherwise should be accessed only via vfs_list_lock() and + * vfs_list_unlock(). Also used to protect the timestamp for mods to the list. + */ +static krwlock_t vfslist; + +// vfs_mountdevices(void) +// vfs_mountdev1(void) +// vfs_mountfs() +// vfs_mountroot() +// lofi_add, lofi_remove + + +/* + * Mount the FS for the test jig. Based on domount() + */ +int +fake_domount(char *fsname, struct mounta *uap, struct vfs **vfspp) +{ + vnode_t *vp; + struct cred *credp; + struct vfssw *vswp; + vfsops_t *vfsops; + struct vfs *vfsp = NULL; + mntopts_t mnt_mntopts; + int error = 0; + int copyout_error = 0; + char *opts = uap->optptr; + char *inargs = opts; + int optlen = uap->optlen; + + credp = CRED(); + + /* + * Test jig specific: mount on rootdir + */ + if (rootvfs != NULL) + return (EBUSY); + vp = rootdir; + + /* + * The v_flag value for the mount point vp is permanently set + * to VVFSLOCK so that no one bypasses the vn_vfs*locks routine + * for mount point locking. + */ + mutex_enter(&vp->v_lock); + vp->v_flag |= VVFSLOCK; + mutex_exit(&vp->v_lock); + + mnt_mntopts.mo_count = 0; + + /* + * Find the ops vector to use to invoke the file system-specific mount + * method. If the fsname argument is non-NULL, use it directly. + */ + if ((vswp = vfs_getvfssw(fsname)) == NULL) { + return (EINVAL); + } + if (!VFS_INSTALLED(vswp)) + return (EINVAL); + + // secpolicy_fs_allowed_mount(fsname) + + vfsops = &vswp->vsw_vfsops; + + vfs_copyopttbl(&vswp->vsw_optproto, &mnt_mntopts); + + /* + * Fetch mount options and parse them for generic vfs options + */ + if (uap->flags & MS_OPTIONSTR) { + /* + * Limit the buffer size + */ + if (optlen < 0 || optlen > MAX_MNTOPT_STR) { + error = EINVAL; + goto errout; + } + if ((uap->flags & MS_SYSSPACE) == 0) { + inargs = kmem_alloc(MAX_MNTOPT_STR, KM_SLEEP); + inargs[0] = '\0'; + if (optlen) { + error = copyinstr(opts, inargs, (size_t)optlen, + NULL); + if (error) { + goto errout; + } + } + } + vfs_parsemntopts(&mnt_mntopts, inargs, 0); + } + /* + * Flag bits override the options string. + */ + if (uap->flags & MS_REMOUNT) + vfs_setmntopt_nolock(&mnt_mntopts, MNTOPT_REMOUNT, NULL, 0, 0); + if (uap->flags & MS_RDONLY) + vfs_setmntopt_nolock(&mnt_mntopts, MNTOPT_RO, NULL, 0, 0); + if (uap->flags & MS_NOSUID) + vfs_setmntopt_nolock(&mnt_mntopts, MNTOPT_NOSUID, NULL, 0, 0); + + /* + * Check if this is a remount; must be set in the option string and + * the file system must support a remount option. + */ + if (vfs_optionisset_nolock(&mnt_mntopts, + MNTOPT_REMOUNT, NULL)) { + /* disallow here */ + error = ENOTSUP; + goto errout; + } + + /* + * uap->flags and vfs_optionisset() should agree. + */ + if (vfs_optionisset_nolock(&mnt_mntopts, MNTOPT_RO, NULL)) { + uap->flags |= MS_RDONLY; + } + if (vfs_optionisset_nolock(&mnt_mntopts, MNTOPT_NOSUID, NULL)) { + uap->flags |= MS_NOSUID; + } + // nbmand ... + + /* + * If we are splicing the fs into the namespace, + * perform mount point checks... + * (always splice=0 here) + */ + + if ((uap->flags & (MS_DATA | MS_OPTIONSTR)) == 0) { + uap->dataptr = NULL; + uap->datalen = 0; + } + + /* + * If this is a remount, ... (never here) + */ + vfsp = vfs_alloc(KM_SLEEP); + VFS_INIT(vfsp, vfsops, NULL); + + VFS_HOLD(vfsp); + + // lofi_add(fsname, vfsp, &mnt_mntopts, uap) + + /* + * PRIV_SYS_MOUNT doesn't mean you can become root. + */ + uap->flags |= MS_NOSUID; + vfs_setmntopt_nolock(&mnt_mntopts, MNTOPT_NOSUID, NULL, 0, 0); + + /* + * The vfs_reflock... + */ + + /* + * Lock the vfs... + */ + if ((error = vfs_lock(vfsp)) != 0) { + vfs_free(vfsp); + vfsp = NULL; + goto errout; + } + + /* + * Add device to mount in progress table... + */ + /* + * Invalidate cached entry for the mount point. + */ + + /* + * If have an option string but the filesystem doesn't supply a + * prototype options table, create a table... + */ + + /* + * Serialize with zone state transitions... + */ + + // mount_in_progress(zone); + + /* + * Instantiate (or reinstantiate) the file system... + */ + vfs_swapopttbl(&mnt_mntopts, &vfsp->vfs_mntopts); + + vfs_setresource(vfsp, uap->spec, 0); + vfs_setmntpoint(vfsp, uap->dir, 0); + + /* + * going to mount on this vnode, so notify. + */ + // vnevent_mountedover(vp, NULL); + error = VFS_MOUNT(vfsp, vp, uap, credp); + + if (uap->flags & MS_RDONLY) + vfs_setmntopt(vfsp, MNTOPT_RO, NULL, 0); + if (uap->flags & MS_NOSUID) + vfs_setmntopt(vfsp, MNTOPT_NOSUID, NULL, 0); + if (uap->flags & MS_GLOBAL) + vfs_setmntopt(vfsp, MNTOPT_GLOBAL, NULL, 0); + + if (error) { + // lofi_remove(vfsp); + + // (remount == 0) + vfs_unlock(vfsp); + // vfs_freemnttab(vfsp); + vfs_free(vfsp); + vfsp = NULL; + } else { + /* + * Set the mount time to now + */ + // vfsp->vfs_mtime = ddi_get_time(); + // if (remount) ... + // else if (splice) vfs_add(vp, vfsp, flags) + // else VFS_HOLD(vfsp); + + /* + * Test jig specific: + * Do sort of like vfs_add for vp=rootdir + * Already have hold on vp. + */ + vfsp->vfs_vnodecovered = vp; + vfsp->vfs_flag |= (VFS_NOSETUID|VFS_NODEVICES); + VFS_HOLD(vfsp); + rootvfs = vfsp; + + /* + * Set flags for global options encountered + */ + if (vfs_optionisset(vfsp, MNTOPT_RO, NULL)) + vfsp->vfs_flag |= VFS_RDONLY; + else + vfsp->vfs_flag &= ~VFS_RDONLY; + if (vfs_optionisset(vfsp, MNTOPT_NOSUID, NULL)) { + vfsp->vfs_flag |= (VFS_NOSETUID|VFS_NODEVICES); + } else { + if (vfs_optionisset(vfsp, MNTOPT_NODEVICES, NULL)) + vfsp->vfs_flag |= VFS_NODEVICES; + else + vfsp->vfs_flag &= ~VFS_NODEVICES; + if (vfs_optionisset(vfsp, MNTOPT_NOSETUID, NULL)) + vfsp->vfs_flag |= VFS_NOSETUID; + else + vfsp->vfs_flag &= ~VFS_NOSETUID; + } + if (vfs_optionisset(vfsp, MNTOPT_NBMAND, NULL)) + vfsp->vfs_flag |= VFS_NBMAND; + else + vfsp->vfs_flag &= ~VFS_NBMAND; + + if (vfs_optionisset(vfsp, MNTOPT_XATTR, NULL)) + vfsp->vfs_flag |= VFS_XATTR; + else + vfsp->vfs_flag &= ~VFS_XATTR; + + if (vfs_optionisset(vfsp, MNTOPT_NOEXEC, NULL)) + vfsp->vfs_flag |= VFS_NOEXEC; + else + vfsp->vfs_flag &= ~VFS_NOEXEC; + + /* + * Now construct the output option string of options + * we recognized. + */ + if (uap->flags & MS_OPTIONSTR) { + vfs_list_read_lock(); + copyout_error = vfs_buildoptionstr( + &vfsp->vfs_mntopts, inargs, optlen); + vfs_list_unlock(); + if (copyout_error == 0 && + (uap->flags & MS_SYSSPACE) == 0) { + copyout_error = copyout(inargs, opts, optlen); + } + } + + /* + * If this isn't a remount, set up the vopstats... + */ + if (vswp->vsw_flag & VSW_XID) + vfsp->vfs_flag |= VFS_XID; + + vfs_unlock(vfsp); + + /* + * Test jig specicific: + * Replace rootdir with the mounted root. + */ + error = VFS_ROOT(vfsp, &rootdir); + if (error != 0) { + panic("fake_domount, get root %d\n", error); + } + } + // mount_completed(zone); + // zone_rele(zone); + + // if (splice) + // vn_vfsunlock(vp); + + if ((error == 0) && (copyout_error == 0)) { + /* get_vskstat_anchor() */ + /* Return vfsp to caller. */ + *vfspp = vfsp; + } +errout: + vfs_freeopttbl(&mnt_mntopts); + /* resource, mountpt not allocated */ + /* no addmip, delmip */ + ASSERT(vswp != NULL); + vfs_unrefvfssw(vswp); + if (inargs != opts) + kmem_free(inargs, MAX_MNTOPT_STR); + if (copyout_error) { + if (vfsp != NULL) { + // lofi_remove(vfsp); + VFS_RELE(vfsp); + } + error = copyout_error; + } + return (error); +} + + +static void +vfs_setpath( + struct vfs *vfsp, /* vfs being updated */ + refstr_t **refp, /* Ref-count string to contain the new path */ + const char *newpath, /* Path to add to refp (above) */ + uint32_t flag) /* flag */ +{ + // size_t len; + refstr_t *ref; + // char *sp; + int have_list_lock = 0; + + ASSERT(!VFS_ON_LIST(vfsp) || vfs_lock_held(vfsp)); + + /* + * New path must be less than MAXPATHLEN because mntfs + * will only display up to MAXPATHLEN bytes. This is currently + * safe, because domount() uses pn_get(), and other callers + * similarly cap the size to fewer than MAXPATHLEN bytes. + */ + + ASSERT(strlen(newpath) < MAXPATHLEN); + + /* mntfs requires consistency while vfs list lock is held */ + + if (VFS_ON_LIST(vfsp)) { + have_list_lock = 1; + vfs_list_lock(); + } + + if (*refp != NULL) + refstr_rele(*refp); + + /* + * If we are in a non-global zone... (do something else) + */ + ref = refstr_alloc(newpath); + *refp = ref; + + if (have_list_lock) { + vfs_mnttab_modtimeupd(); + vfs_list_unlock(); + } +} + +/* + * Record a mounted resource name in a vfs structure. + * If vfsp is already mounted, caller must hold the vfs lock. + */ +void +vfs_setresource(struct vfs *vfsp, const char *resource, uint32_t flag) +{ + if (resource == NULL || resource[0] == '\0') + resource = VFS_NORESOURCE; + vfs_setpath(vfsp, &vfsp->vfs_resource, resource, flag); +} + +/* + * Record a mount point name in a vfs structure. + * If vfsp is already mounted, caller must hold the vfs lock. + */ +void +vfs_setmntpoint(struct vfs *vfsp, const char *mntpt, uint32_t flag) +{ + if (mntpt == NULL || mntpt[0] == '\0') + mntpt = VFS_NOMNTPT; + vfs_setpath(vfsp, &vfsp->vfs_mntpt, mntpt, flag); +} + +/* Returns the vfs_resource. Caller must call refstr_rele() when finished. */ + +refstr_t * +vfs_getresource(const struct vfs *vfsp) +{ + refstr_t *resource; + + vfs_list_read_lock(); + resource = vfsp->vfs_resource; + refstr_hold(resource); + vfs_list_unlock(); + + return (resource); +} + +/* Returns the vfs_mntpt. Caller must call refstr_rele() when finished. */ + +refstr_t * +vfs_getmntpoint(const struct vfs *vfsp) +{ + refstr_t *mntpt; + + vfs_list_read_lock(); + mntpt = vfsp->vfs_mntpt; + refstr_hold(mntpt); + vfs_list_unlock(); + + return (mntpt); +} + +// vfs_createopttbl_extend +// vfs_createopttbl + +/* + * Swap two mount options tables + */ +static void +vfs_swapopttbl_nolock(mntopts_t *optbl1, mntopts_t *optbl2) +{ + uint_t tmpcnt; + mntopt_t *tmplist; + + tmpcnt = optbl2->mo_count; + tmplist = optbl2->mo_list; + optbl2->mo_count = optbl1->mo_count; + optbl2->mo_list = optbl1->mo_list; + optbl1->mo_count = tmpcnt; + optbl1->mo_list = tmplist; +} + +static void +vfs_swapopttbl(mntopts_t *optbl1, mntopts_t *optbl2) +{ + vfs_list_lock(); + vfs_swapopttbl_nolock(optbl1, optbl2); + vfs_mnttab_modtimeupd(); + vfs_list_unlock(); +} + +static char ** +vfs_copycancelopt_extend(char **const moc, int extend) +{ + int i = 0; + int j; + char **result; + + if (moc != NULL) { + for (; moc[i] != NULL; i++) + /* count number of options to cancel */; + } + + if (i + extend == 0) + return (NULL); + + result = kmem_alloc((i + extend + 1) * sizeof (char *), KM_SLEEP); + + for (j = 0; j < i; j++) { + result[j] = kmem_alloc(strlen(moc[j]) + 1, KM_SLEEP); + (void) strcpy(result[j], moc[j]); + } + for (; j <= i + extend; j++) + result[j] = NULL; + + return (result); +} + +static void +vfs_copyopt(const mntopt_t *s, mntopt_t *d) +{ + char *sp, *dp; + + d->mo_flags = s->mo_flags; + d->mo_data = s->mo_data; + sp = s->mo_name; + if (sp != NULL) { + dp = kmem_alloc(strlen(sp) + 1, KM_SLEEP); + (void) strcpy(dp, sp); + d->mo_name = dp; + } else { + d->mo_name = NULL; /* should never happen */ + } + + d->mo_cancel = vfs_copycancelopt_extend(s->mo_cancel, 0); + + sp = s->mo_arg; + if (sp != NULL) { + dp = kmem_alloc(strlen(sp) + 1, KM_SLEEP); + (void) strcpy(dp, sp); + d->mo_arg = dp; + } else { + d->mo_arg = NULL; + } +} + +// vfs_copyopttbl_extend +// vfs_copyopttbl + +/* + * Copy a mount options table, possibly allocating some spare + * slots at the end. It is permissible to copy_extend the NULL table. + */ +static void +vfs_copyopttbl_extend(const mntopts_t *smo, mntopts_t *dmo, int extra) +{ + uint_t i, count; + mntopt_t *motbl; + + /* + * Clear out any existing stuff in the options table being initialized + */ + vfs_freeopttbl(dmo); + count = (smo == NULL) ? 0 : smo->mo_count; + if ((count + extra) == 0) /* nothing to do */ + return; + dmo->mo_count = count + extra; + motbl = kmem_zalloc((count + extra) * sizeof (mntopt_t), KM_SLEEP); + dmo->mo_list = motbl; + for (i = 0; i < count; i++) { + vfs_copyopt(&smo->mo_list[i], &motbl[i]); + } + for (i = count; i < count + extra; i++) { + motbl[i].mo_flags = MO_EMPTY; + } +} + +/* + * Copy a mount options table. + * + * This function is *not* for general use by filesystems. + * + * Note: caller is responsible for locking the vfs list, if needed, + * to protect smo and dmo. + */ +void +vfs_copyopttbl(const mntopts_t *smo, mntopts_t *dmo) +{ + vfs_copyopttbl_extend(smo, dmo, 0); +} + +static char ** +vfs_mergecancelopts(const mntopt_t *mop1, const mntopt_t *mop2) +{ + int c1 = 0; + int c2 = 0; + char **result; + char **sp1, **sp2, **dp; + + /* + * First we count both lists of cancel options. + * If either is NULL or has no elements, we return a copy of + * the other. + */ + if (mop1->mo_cancel != NULL) { + for (; mop1->mo_cancel[c1] != NULL; c1++) + /* count cancel options in mop1 */; + } + + if (c1 == 0) + return (vfs_copycancelopt_extend(mop2->mo_cancel, 0)); + + if (mop2->mo_cancel != NULL) { + for (; mop2->mo_cancel[c2] != NULL; c2++) + /* count cancel options in mop2 */; + } + + result = vfs_copycancelopt_extend(mop1->mo_cancel, c2); + + if (c2 == 0) + return (result); + + /* + * When we get here, we've got two sets of cancel options; + * we need to merge the two sets. We know that the result + * array has "c1+c2+1" entries and in the end we might shrink + * it. + * Result now has a copy of the c1 entries from mop1; we'll + * now lookup all the entries of mop2 in mop1 and copy it if + * it is unique. + * This operation is O(n^2) but it's only called once per + * filesystem per duplicate option. This is a situation + * which doesn't arise with the filesystems in ON and + * n is generally 1. + */ + + dp = &result[c1]; + for (sp2 = mop2->mo_cancel; *sp2 != NULL; sp2++) { + for (sp1 = mop1->mo_cancel; *sp1 != NULL; sp1++) { + if (strcmp(*sp1, *sp2) == 0) + break; + } + if (*sp1 == NULL) { + /* + * Option *sp2 not found in mop1, so copy it. + * The calls to vfs_copycancelopt_extend() + * guarantee that there's enough room. + */ + *dp = kmem_alloc(strlen(*sp2) + 1, KM_SLEEP); + (void) strcpy(*dp++, *sp2); + } + } + if (dp != &result[c1+c2]) { + size_t bytes = (dp - result + 1) * sizeof (char *); + char **nres = kmem_alloc(bytes, KM_SLEEP); + + bcopy(result, nres, bytes); + kmem_free(result, (c1 + c2 + 1) * sizeof (char *)); + result = nres; + } + return (result); +} + +/* + * Merge two mount option tables (outer and inner) into one. This is very + * similar to "merging" global variables and automatic variables in C. + * + * This isn't (and doesn't have to be) fast. + * + * This function is *not* for general use by filesystems. + * + * Note: caller is responsible for locking the vfs list, if needed, + * to protect omo, imo & dmo. + */ +void +vfs_mergeopttbl(const mntopts_t *omo, const mntopts_t *imo, mntopts_t *dmo) +{ + uint_t i, count; + mntopt_t *mop, *motbl; + uint_t freeidx; + + /* + * First determine how much space we need to allocate. + */ + count = omo->mo_count; + for (i = 0; i < imo->mo_count; i++) { + if (imo->mo_list[i].mo_flags & MO_EMPTY) + continue; + if (vfs_hasopt(omo, imo->mo_list[i].mo_name) == NULL) + count++; + } + ASSERT(count >= omo->mo_count && + count <= omo->mo_count + imo->mo_count); + motbl = kmem_alloc(count * sizeof (mntopt_t), KM_SLEEP); + for (i = 0; i < omo->mo_count; i++) + vfs_copyopt(&omo->mo_list[i], &motbl[i]); + freeidx = omo->mo_count; + for (i = 0; i < imo->mo_count; i++) { + if (imo->mo_list[i].mo_flags & MO_EMPTY) + continue; + if ((mop = vfs_hasopt(omo, imo->mo_list[i].mo_name)) != NULL) { + char **newcanp; + uint_t index = mop - omo->mo_list; + + newcanp = vfs_mergecancelopts(mop, &motbl[index]); + + vfs_freeopt(&motbl[index]); + vfs_copyopt(&imo->mo_list[i], &motbl[index]); + + vfs_freecancelopt(motbl[index].mo_cancel); + motbl[index].mo_cancel = newcanp; + } else { + /* + * If it's a new option, just copy it over to the first + * free location. + */ + vfs_copyopt(&imo->mo_list[i], &motbl[freeidx++]); + } + } + dmo->mo_count = count; + dmo->mo_list = motbl; +} + +/* + * Functions to set and clear mount options in a mount options table. + */ + +/* + * Clear a mount option, if it exists. + * + * The update_mnttab arg indicates whether mops is part of a vfs that is on + * the vfs list. + */ +static void +vfs_clearmntopt_nolock(mntopts_t *mops, const char *opt, int update_mnttab) +{ + struct mntopt *mop; + uint_t i, count; + + ASSERT(!update_mnttab || RW_WRITE_HELD(&vfslist)); + + count = mops->mo_count; + for (i = 0; i < count; i++) { + mop = &mops->mo_list[i]; + + if (mop->mo_flags & MO_EMPTY) + continue; + if (strcmp(opt, mop->mo_name)) + continue; + mop->mo_flags &= ~MO_SET; + if (mop->mo_arg != NULL) { + kmem_free(mop->mo_arg, strlen(mop->mo_arg) + 1); + } + mop->mo_arg = NULL; + if (update_mnttab) + vfs_mnttab_modtimeupd(); + break; + } +} + +void +vfs_clearmntopt(struct vfs *vfsp, const char *opt) +{ + int gotlock = 0; + + if (VFS_ON_LIST(vfsp)) { + gotlock = 1; + vfs_list_lock(); + } + vfs_clearmntopt_nolock(&vfsp->vfs_mntopts, opt, gotlock); + if (gotlock) + vfs_list_unlock(); +} + + +/* + * Set a mount option on... + */ +static void +vfs_setmntopt_nolock(mntopts_t *mops, const char *opt, + const char *arg, int flags, int update_mnttab) +{ + mntopt_t *mop; + uint_t i, count; + char *sp; + + ASSERT(!update_mnttab || RW_WRITE_HELD(&vfslist)); + + if (flags & VFS_CREATEOPT) { + if (vfs_hasopt(mops, opt) != NULL) { + flags &= ~VFS_CREATEOPT; + } + } + count = mops->mo_count; + for (i = 0; i < count; i++) { + mop = &mops->mo_list[i]; + + if (mop->mo_flags & MO_EMPTY) { + if ((flags & VFS_CREATEOPT) == 0) + continue; + sp = kmem_alloc(strlen(opt) + 1, KM_SLEEP); + (void) strcpy(sp, opt); + mop->mo_name = sp; + if (arg != NULL) + mop->mo_flags = MO_HASVALUE; + else + mop->mo_flags = 0; + } else if (strcmp(opt, mop->mo_name)) { + continue; + } + if ((mop->mo_flags & MO_IGNORE) && (flags & VFS_NOFORCEOPT)) + break; + if (arg != NULL && (mop->mo_flags & MO_HASVALUE) != 0) { + sp = kmem_alloc(strlen(arg) + 1, KM_SLEEP); + (void) strcpy(sp, arg); + } else { + sp = NULL; + } + if (mop->mo_arg != NULL) + kmem_free(mop->mo_arg, strlen(mop->mo_arg) + 1); + mop->mo_arg = sp; + if (flags & VFS_DISPLAY) + mop->mo_flags &= ~MO_NODISPLAY; + if (flags & VFS_NODISPLAY) + mop->mo_flags |= MO_NODISPLAY; + mop->mo_flags |= MO_SET; + if (mop->mo_cancel != NULL) { + char **cp; + + for (cp = mop->mo_cancel; *cp != NULL; cp++) + vfs_clearmntopt_nolock(mops, *cp, 0); + } + if (update_mnttab) + vfs_mnttab_modtimeupd(); + break; + } +} + +void +vfs_setmntopt(struct vfs *vfsp, const char *opt, const char *arg, int flags) +{ + int gotlock = 0; + + if (VFS_ON_LIST(vfsp)) { + gotlock = 1; + vfs_list_lock(); + } + vfs_setmntopt_nolock(&vfsp->vfs_mntopts, opt, arg, flags, gotlock); + if (gotlock) + vfs_list_unlock(); +} + +// vfs_addtag +// vfs_settag +// vfs_clrtag + +/* + * Function to parse an option string and fill in a mount options table. + * Unknown options are silently ignored. The input option string is modified + * by replacing separators with nulls. If the create flag is set, options + * not found in the table are just added on the fly. The table must have + * an option slot marked MO_EMPTY to add an option on the fly. + * + * This function is *not* for general use by filesystems. + * + * Note: caller is responsible for locking the vfs list, if needed, + * to protect mops.. + */ +void +vfs_parsemntopts(mntopts_t *mops, char *osp, int create) +{ + char *s = osp, *p, *nextop, *valp, *cp, *ep = NULL; + int setflg = VFS_NOFORCEOPT; + + if (osp == NULL) + return; + while (*s != '\0') { + p = strchr(s, ','); /* find next option */ + if (p == NULL) { + cp = NULL; + p = s + strlen(s); + } else { + cp = p; /* save location of comma */ + *p++ = '\0'; /* mark end and point to next option */ + } + nextop = p; + p = strchr(s, '='); /* look for value */ + if (p == NULL) { + valp = NULL; /* no value supplied */ + ep = NULL; + } else { + ep = p; /* save location of equals */ + *p++ = '\0'; /* end option and point to value */ + valp = p; + } + /* + * set option into options table + */ + if (create) + setflg |= VFS_CREATEOPT; + vfs_setmntopt_nolock(mops, s, valp, setflg, 0); + if (cp != NULL) + *cp = ','; /* restore the comma */ + if (valp != NULL) + *ep = '='; /* restore the equals */ + s = nextop; + } +} + +/* + * Function to inquire if an option exists in a mount options table. + * Returns a pointer to the option if it exists, else NULL. + */ +struct mntopt * +vfs_hasopt(const mntopts_t *mops, const char *opt) +{ + struct mntopt *mop; + uint_t i, count; + + count = mops->mo_count; + for (i = 0; i < count; i++) { + mop = &mops->mo_list[i]; + + if (mop->mo_flags & MO_EMPTY) + continue; + if (strcmp(opt, mop->mo_name) == 0) + return (mop); + } + return (NULL); +} + +/* + * Function to inquire if an option is set in a mount options table. + * Returns non-zero if set and fills in the arg pointer with a pointer to + * the argument string or NULL if there is no argument string. + */ +static int +vfs_optionisset_nolock(const mntopts_t *mops, const char *opt, char **argp) +{ + struct mntopt *mop; + uint_t i, count; + + count = mops->mo_count; + for (i = 0; i < count; i++) { + mop = &mops->mo_list[i]; + + if (mop->mo_flags & MO_EMPTY) + continue; + if (strcmp(opt, mop->mo_name)) + continue; + if ((mop->mo_flags & MO_SET) == 0) + return (0); + if (argp != NULL && (mop->mo_flags & MO_HASVALUE) != 0) + *argp = mop->mo_arg; + return (1); + } + return (0); +} + + +int +vfs_optionisset(const struct vfs *vfsp, const char *opt, char **argp) +{ + int ret; + + vfs_list_read_lock(); + ret = vfs_optionisset_nolock(&vfsp->vfs_mntopts, opt, argp); + vfs_list_unlock(); + return (ret); +} + + +/* + * Construct a comma separated string of the options set in the given + * mount table, return the string in the given buffer. Return non-zero if + * the buffer would overflow. + * + * This function is *not* for general use by filesystems. + * + * Note: caller is responsible for locking the vfs list, if needed, + * to protect mp. + */ +int +vfs_buildoptionstr(const mntopts_t *mp, char *buf, int len) +{ + char *cp; + uint_t i; + + buf[0] = '\0'; + cp = buf; + for (i = 0; i < mp->mo_count; i++) { + struct mntopt *mop; + + mop = &mp->mo_list[i]; + if (mop->mo_flags & MO_SET) { + int optlen, comma = 0; + + if (buf[0] != '\0') + comma = 1; + optlen = strlen(mop->mo_name); + if (strlen(buf) + comma + optlen + 1 > len) + goto err; + if (comma) + *cp++ = ','; + (void) strcpy(cp, mop->mo_name); + cp += optlen; + /* + * Append option value if there is one + */ + if (mop->mo_arg != NULL) { + int arglen; + + arglen = strlen(mop->mo_arg); + if (strlen(buf) + arglen + 2 > len) + goto err; + *cp++ = '='; + (void) strcpy(cp, mop->mo_arg); + cp += arglen; + } + } + } + return (0); +err: + return (EOVERFLOW); +} + +static void +vfs_freecancelopt(char **moc) +{ + if (moc != NULL) { + int ccnt = 0; + char **cp; + + for (cp = moc; *cp != NULL; cp++) { + kmem_free(*cp, strlen(*cp) + 1); + ccnt++; + } + kmem_free(moc, (ccnt + 1) * sizeof (char *)); + } +} + +static void +vfs_freeopt(mntopt_t *mop) +{ + if (mop->mo_name != NULL) + kmem_free(mop->mo_name, strlen(mop->mo_name) + 1); + + vfs_freecancelopt(mop->mo_cancel); + + if (mop->mo_arg != NULL) + kmem_free(mop->mo_arg, strlen(mop->mo_arg) + 1); +} + +/* + * Free a mount options table + * + * This function is *not* for general use by filesystems. + * + * Note: caller is responsible for locking the vfs list, if needed, + * to protect mp. + */ +void +vfs_freeopttbl(mntopts_t *mp) +{ + uint_t i, count; + + count = mp->mo_count; + for (i = 0; i < count; i++) { + vfs_freeopt(&mp->mo_list[i]); + } + if (count) { + kmem_free(mp->mo_list, sizeof (mntopt_t) * count); + mp->mo_count = 0; + mp->mo_list = NULL; + } +} + +// vfs_mntdummyread +// vfs_mntdummywrite +// vfs_mntdummygetattr +// vfs_mnttabvp_setup +// vfs_mnttab_rwop +// vfs_mnttab_writeop +// vfs_mnttab_readop +// vfs_freemnttab +// vfs_mnttab_modtime +// vfs_mnttab_poll +// vfs_mono_time + +/* + * Update the mnttab modification time... + */ +void +vfs_mnttab_modtimeupd() +{ +} + +/* + * Unlike the real dounmount, we don't have + * vn_vfswlock_held(coveredvp) + */ +int +fake_dounmount(struct vfs *vfsp, int flag) +{ + cred_t *cr = CRED(); + vnode_t *coveredvp; + int error; + + /* + * Get covered vnode. This will be NULL if the vfs is not linked + * into the file system name space (i.e., domount() with MNT_NOSPICE). + */ + coveredvp = vfsp->vfs_vnodecovered; + + /* For forcible umount, skip VFS_SYNC() since it may hang */ + if ((flag & MS_FORCE) == 0) + (void) VFS_SYNC(vfsp, 0, cr); + + /* + * Test-jig specific: + * Need to release rootdir before unmount or VFS_UNMOUNT + * may fail due to that node being active. + */ + if (rootdir != NULL) { + ASSERT(rootdir != coveredvp); + VN_RELE(rootdir); + rootdir = NULL; + } + + /* + * Lock the vfs to maintain fs status quo during unmount. This + * has to be done after the sync because ufs_update tries to acquire + * the vfs_reflock. + */ + vfs_lock_wait(vfsp); + + if ((error = VFS_UNMOUNT(vfsp, flag, cr)) != 0) { + int err2; + vfs_unlock(vfsp); + /* Get rootdir back */ + err2 = VFS_ROOT(vfsp, &rootdir); + if (err2 != 0) { + panic("fake_dounmount, get root %d\n", err2); + } + } else { + /* + * Real dounmount does vfs_remove. + * + * Test-jig specific: + * Restore the covered rootdir, + * release the rootvfs hold and clear. + */ + if (coveredvp != NULL) { + // vfs_list_remove(vfsp); + vfsp->vfs_vnodecovered = NULL; + rootdir = coveredvp; + } + if (rootvfs == vfsp) { + VFS_RELE(vfsp); + rootvfs = NULL; + } + + /* + * Release the (final) reference to vfs + */ + vfs_unlock(vfsp); + VFS_RELE(vfsp); + } + return (error); +} + +// vfs_unmountall(void) +// vfs_addmip +// vfs_delmip +// vfs_add +// vfs_remove + +static krwlock_t vpvfsentry_ve_lock; + +/* + * Lock a filesystem to prevent access to it while mounting, + * unmounting and syncing. Return EBUSY immediately if lock + * can't be acquired. + */ +int +vfs_lock(vfs_t *vfsp) +{ + + if (rw_tryenter(&vpvfsentry_ve_lock, RW_WRITER)) + return (0); + + return (EBUSY); +} + +int +vfs_rlock(vfs_t *vfsp) +{ + + if (rw_tryenter(&vpvfsentry_ve_lock, RW_READER)) + return (0); + + return (EBUSY); +} + +void +vfs_lock_wait(vfs_t *vfsp) +{ + + rw_enter(&vpvfsentry_ve_lock, RW_WRITER); +} + +void +vfs_rlock_wait(vfs_t *vfsp) +{ + rw_enter(&vpvfsentry_ve_lock, RW_READER); +} + +/* + * Unlock a locked filesystem. + */ +void +vfs_unlock(vfs_t *vfsp) +{ + + rw_exit(&vpvfsentry_ve_lock); +} + +/* + * Utility routine that allows a filesystem to construct its + * fsid in "the usual way" - by munging some underlying dev_t and + * the filesystem type number into the 64-bit fsid. ... + */ +void +vfs_make_fsid(fsid_t *fsi, dev_t dev, int val) +{ + if (!cmpldev((dev32_t *)&fsi->val[0], dev)) + panic("device number too big for fsid!"); + fsi->val[1] = val; +} + +int +vfs_lock_held(vfs_t *vfsp) +{ + int held; + + held = rw_write_held(&vpvfsentry_ve_lock); + + return (held); +} + +// vfs_lock_owner + +/* + * vfs list locking. + */ + +void +vfs_list_lock() +{ + rw_enter(&vfslist, RW_WRITER); +} + +void +vfs_list_read_lock() +{ + rw_enter(&vfslist, RW_READER); +} + +void +vfs_list_unlock() +{ + rw_exit(&vfslist); +} + +/* + * Low level worker routines for adding entries to and removing entries from + * the vfs list. + */ + +// vfs_hash_add +// vfs_hash_remove +// vfs_list_add +// vfs_list_remove +// getvfs +// vfs_devmounting + +/* + * Search the vfs list for a specified device. Returns 1, if entry is found + * or 0 if no suitable entry is found. + */ + +int +vfs_devismounted(dev_t dev) +{ + return (0); +} + +// vfs_dev2vfsp +// vfs_mntpoint2vfsp + +/* + * Search the vfs list for a specified vfsops. + * if vfs entry is found then return 1, else 0. + */ +int +vfs_opsinuse(vfsops_t *ops) +{ + return (0); +} + +/* + * Allocate an entry in vfssw for a file system type + */ +struct vfssw * +allocate_vfssw(const char *type) +{ + struct vfssw *vswp; + + if (type[0] == '\0' || strlen(type) + 1 > _ST_FSTYPSZ) { + /* + * The vfssw table uses the empty string to identify an + * available entry; we cannot add any type which has + * a leading NUL. The string length is limited to + * the size of the st_fstype array in struct stat. + */ + return (NULL); + } + + ASSERT(VFSSW_WRITE_LOCKED()); + for (vswp = &vfssw[1]; vswp < &vfssw[nfstype]; vswp++) + if (!ALLOCATED_VFSSW(vswp)) { + vswp->vsw_name = kmem_alloc(strlen(type) + 1, KM_SLEEP); + (void) strcpy(vswp->vsw_name, type); + ASSERT(vswp->vsw_count == 0); + vswp->vsw_count = 1; + mutex_init(&vswp->vsw_lock, NULL, MUTEX_DEFAULT, NULL); + return (vswp); + } + return (NULL); +} + +// vfs_to_modname +// vfs_getvfssw + +/* + * Find a vfssw entry given a file system type name. + */ +struct vfssw * +vfs_getvfssw(const char *type) +{ + struct vfssw *vswp; + + if (type == NULL || *type == '\0') + return (NULL); + + for (vswp = &vfssw[1]; vswp < &vfssw[nfstype]; vswp++) { + if (strcmp(type, vswp->vsw_name) == 0) { + return (vswp); + } + } + + return (NULL); + +} + +/* + * Find a vfssw entry given a file system type name. + */ +struct vfssw * +vfs_getvfsswbyname(const char *type) +{ + struct vfssw *vswp; + + ASSERT(VFSSW_LOCKED()); + if (type == NULL || *type == '\0') + return (NULL); + + for (vswp = &vfssw[1]; vswp < &vfssw[nfstype]; vswp++) { + if (strcmp(type, vswp->vsw_name) == 0) { + vfs_refvfssw(vswp); + return (vswp); + } + } + + return (NULL); +} + +// vfs_getvfsswbyvfsops + +/* + * Reference a vfssw entry. + */ +void +vfs_refvfssw(struct vfssw *vswp) +{ + + mutex_enter(&vswp->vsw_lock); + vswp->vsw_count++; + mutex_exit(&vswp->vsw_lock); +} + +/* + * Unreference a vfssw entry. + */ +void +vfs_unrefvfssw(struct vfssw *vswp) +{ + + mutex_enter(&vswp->vsw_lock); + vswp->vsw_count--; + mutex_exit(&vswp->vsw_lock); +} + +// vfs_syncall + +/* + * Map VFS flags to statvfs flags. These shouldn't really be separate + * flags at all. + */ +uint_t +vf_to_stf(uint_t vf) +{ + uint_t stf = 0; + + if (vf & VFS_RDONLY) + stf |= ST_RDONLY; + if (vf & VFS_NOSETUID) + stf |= ST_NOSUID; + if (vf & VFS_NOTRUNC) + stf |= ST_NOTRUNC; + + return (stf); +} + +// vfsstray_sync +// vfsstray +// vfs_EIO +// vfs_EIO_sync +// EIO_vfs +// EIO_vfsops + +#pragma init(vfsinit) + +/* + * Called from startup() to initialize all loaded vfs's + */ +void +vfsinit(void) +{ + vn_create_cache(); + + /* Temporary, until we mount root */ + rootdir = vn_alloc(KM_SLEEP); + rootdir->v_type = VDIR; +} + +vfs_t * +vfs_alloc(int kmflag) +{ + vfs_t *vfsp; + + vfsp = kmem_alloc(sizeof (struct vfs), kmflag); + + /* + * Do the simplest initialization here. + * Everything else gets done in vfs_init() + */ + bzero(vfsp, sizeof (vfs_t)); + return (vfsp); +} + +void +vfs_free(vfs_t *vfsp) +{ + /* + * One would be tempted to assert that "vfsp->vfs_count == 0". + * Don't. See fs/vfs.c + */ + + /* If FEM was in use, make sure everything gets cleaned up */ + + if (vfsp->vfs_implp) + vfsimpl_teardown(vfsp); + sema_destroy(&vfsp->vfs_reflock); + kmem_free(vfsp, sizeof (struct vfs)); +} + +/* + * Increments the vfs reference count by one atomically. + */ +void +vfs_hold(vfs_t *vfsp) +{ + atomic_inc_32(&vfsp->vfs_count); + ASSERT(vfsp->vfs_count != 0); +} + +/* + * Decrements the vfs reference count by one atomically. When + * vfs reference count becomes zero, it calls the file system + * specific vfs_freevfs() to free up the resources. + */ +void +vfs_rele(vfs_t *vfsp) +{ + ASSERT(vfsp->vfs_count != 0); + if (atomic_dec_32_nv(&vfsp->vfs_count) == 0) { + VFS_FREEVFS(vfsp); + // lofi_remove(vfsp); + // zone_rele_ref... + // vfs_freemnttab(vfsp); + vfs_free(vfsp); + } +} + +/* + * Generic operations vector support. + */ + +int +fs_build_vector(void *vector, int *unused_ops, + const fs_operation_trans_def_t *translation, + const fs_operation_def_t *operations) +{ + int i, num_trans, num_ops, used; + + /* + * Count the number of translations and the number of supplied + * operations. + */ + + { + const fs_operation_trans_def_t *p; + + for (num_trans = 0, p = translation; + p->name != NULL; + num_trans++, p++) + ; + } + + { + const fs_operation_def_t *p; + + for (num_ops = 0, p = operations; + p->name != NULL; + num_ops++, p++) + ; + } + + /* Walk through each operation known to our caller. There will be */ + /* one entry in the supplied "translation table" for each. */ + + used = 0; + + for (i = 0; i < num_trans; i++) { + int j, found; + char *curname; + fs_generic_func_p result; + fs_generic_func_p *location; + + curname = translation[i].name; + + /* Look for a matching operation in the list supplied by the */ + /* file system. */ + + found = 0; + + for (j = 0; j < num_ops; j++) { + if (strcmp(operations[j].name, curname) == 0) { + used++; + found = 1; + break; + } + } + + /* + * If the file system is using a "placeholder" for default + * or error functions, grab the appropriate function out of + * the translation table. If the file system didn't supply + * this operation at all, use the default function. + */ + + if (found) { + result = operations[j].func.fs_generic; + if (result == fs_default) { + result = translation[i].defaultFunc; + } else if (result == fs_error) { + result = translation[i].errorFunc; + } else if (result == NULL) { + /* Null values are PROHIBITED */ + return (EINVAL); + } + } else { + result = translation[i].defaultFunc; + } + + /* Now store the function into the operations vector. */ + + /* LINTED E_BAD_PTR_CAST_ALIGN */ + location = (fs_generic_func_p *) + (((char *)vector) + translation[i].offset); + + *location = result; + } + + *unused_ops = num_ops - used; + + return (0); +} + +/* Placeholder functions, should never be called. */ + +int +fs_error(void) +{ + cmn_err(CE_PANIC, "fs_error called"); + return (0); +} + +int +fs_default(void) +{ + cmn_err(CE_PANIC, "fs_default called"); + return (0); +} + +// rootconf +// getfsname +// getrootfs + +/* + * VFS feature routines + */ + +#define VFTINDEX(feature) (((feature) >> 32) & 0xFFFFFFFF) +#define VFTBITS(feature) ((feature) & 0xFFFFFFFFLL) + +/* Register a feature in the vfs */ +void +vfs_set_feature(vfs_t *vfsp, vfs_feature_t feature) +{ + /* Note that vfs_featureset[] is found in *vfsp->vfs_implp */ + if (vfsp->vfs_implp == NULL) + return; + + vfsp->vfs_featureset[VFTINDEX(feature)] |= VFTBITS(feature); +} + +void +vfs_clear_feature(vfs_t *vfsp, vfs_feature_t feature) +{ + /* Note that vfs_featureset[] is found in *vfsp->vfs_implp */ + if (vfsp->vfs_implp == NULL) + return; + vfsp->vfs_featureset[VFTINDEX(feature)] &= VFTBITS(~feature); +} + +/* + * Query a vfs for a feature. + * Returns 1 if feature is present, 0 if not + */ +int +vfs_has_feature(vfs_t *vfsp, vfs_feature_t feature) +{ + int ret = 0; + + /* Note that vfs_featureset[] is found in *vfsp->vfs_implp */ + if (vfsp->vfs_implp == NULL) + return (ret); + + if (vfsp->vfs_featureset[VFTINDEX(feature)] & VFTBITS(feature)) + ret = 1; + + return (ret); +} + +// vfs_propagate_features +// vfs_get_lofi diff --git a/usr/src/lib/smbclnt/libfksmbfs/common/fake_vnode.c b/usr/src/lib/smbclnt/libfksmbfs/common/fake_vnode.c new file mode 100644 index 0000000000..07eb5bc18d --- /dev/null +++ b/usr/src/lib/smbclnt/libfksmbfs/common/fake_vnode.c @@ -0,0 +1,2026 @@ +/* + * 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 (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2017, Joyent, Inc. + * Copyright (c) 2011, 2017 by Delphix. All rights reserved. + * Copyright 2018 Nexenta Systems, Inc. All rights reserved. + */ + +/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ +/* All Rights Reserved */ + +/* + * University Copyright- Copyright (c) 1982, 1986, 1988 + * The Regents of the University of California + * All Rights Reserved + * + * University Acknowledgment- Portions of this document are derived from + * software developed by the University of California, Berkeley, and its + * contributors. + */ + +/* + * This file contains those functions from fs/vnode.c that can be + * used with relatively little change. Functions that differ + * significantly from that are in other files. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* Determine if this vnode is a file that is read-only */ +#define ISROFILE(vp) \ + ((vp)->v_type != VCHR && (vp)->v_type != VBLK && \ + (vp)->v_type != VFIFO && vn_is_readonly(vp)) + +#define VOPSTATS_UPDATE(vp, counter) ((void)vp) +#define VOPSTATS_UPDATE_IO(vp, counter, bytecounter, bytesval) \ + ((void)vp, (void)bytesval) +#define VOPXID_MAP_CR(vp, cr) ((void)vp) + +/* + * Excerpts from fs/vnode.c + */ + +/* Global used for empty/invalid v_path */ +char *vn_vpath_empty = ""; + +static int fs_reparse_mark(char *target, vattr_t *vap, xvattr_t *xvattr); + +/* + * Convert stat(2) formats to vnode types and vice versa. (Knows about + * numerical order of S_IFMT and vnode types.) + */ +enum vtype iftovt_tab[] = { + VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON, + VREG, VNON, VLNK, VNON, VSOCK, VNON, VNON, VNON +}; + +ushort_t vttoif_tab[] = { + 0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK, S_IFIFO, + S_IFDOOR, 0, S_IFSOCK, S_IFPORT, 0 +}; + +/* + * The system vnode cache. + */ + +kmem_cache_t *vn_cache; + + +/* + * Vnode operations vector. + */ + +static const fs_operation_trans_def_t vn_ops_table[] = { + VOPNAME_OPEN, offsetof(struct vnodeops, vop_open), + fs_nosys, fs_nosys, + + VOPNAME_CLOSE, offsetof(struct vnodeops, vop_close), + fs_nosys, fs_nosys, + + VOPNAME_READ, offsetof(struct vnodeops, vop_read), + fs_nosys, fs_nosys, + + VOPNAME_WRITE, offsetof(struct vnodeops, vop_write), + fs_nosys, fs_nosys, + + VOPNAME_IOCTL, offsetof(struct vnodeops, vop_ioctl), + fs_nosys, fs_nosys, + + VOPNAME_SETFL, offsetof(struct vnodeops, vop_setfl), + fs_setfl, fs_nosys, + + VOPNAME_GETATTR, offsetof(struct vnodeops, vop_getattr), + fs_nosys, fs_nosys, + + VOPNAME_SETATTR, offsetof(struct vnodeops, vop_setattr), + fs_nosys, fs_nosys, + + VOPNAME_ACCESS, offsetof(struct vnodeops, vop_access), + fs_nosys, fs_nosys, + + VOPNAME_LOOKUP, offsetof(struct vnodeops, vop_lookup), + fs_nosys, fs_nosys, + + VOPNAME_CREATE, offsetof(struct vnodeops, vop_create), + fs_nosys, fs_nosys, + + VOPNAME_REMOVE, offsetof(struct vnodeops, vop_remove), + fs_nosys, fs_nosys, + + VOPNAME_LINK, offsetof(struct vnodeops, vop_link), + fs_nosys, fs_nosys, + + VOPNAME_RENAME, offsetof(struct vnodeops, vop_rename), + fs_nosys, fs_nosys, + + VOPNAME_MKDIR, offsetof(struct vnodeops, vop_mkdir), + fs_nosys, fs_nosys, + + VOPNAME_RMDIR, offsetof(struct vnodeops, vop_rmdir), + fs_nosys, fs_nosys, + + VOPNAME_READDIR, offsetof(struct vnodeops, vop_readdir), + fs_nosys, fs_nosys, + + VOPNAME_SYMLINK, offsetof(struct vnodeops, vop_symlink), + fs_nosys, fs_nosys, + + VOPNAME_READLINK, offsetof(struct vnodeops, vop_readlink), + fs_nosys, fs_nosys, + + VOPNAME_FSYNC, offsetof(struct vnodeops, vop_fsync), + fs_nosys, fs_nosys, + + VOPNAME_INACTIVE, offsetof(struct vnodeops, vop_inactive), + fs_nosys, fs_nosys, + + VOPNAME_FID, offsetof(struct vnodeops, vop_fid), + fs_nosys, fs_nosys, + + VOPNAME_RWLOCK, offsetof(struct vnodeops, vop_rwlock), + fs_rwlock, fs_rwlock, + + VOPNAME_RWUNLOCK, offsetof(struct vnodeops, vop_rwunlock), + (fs_generic_func_p) fs_rwunlock, + (fs_generic_func_p) fs_rwunlock, /* no errors allowed */ + + VOPNAME_SEEK, offsetof(struct vnodeops, vop_seek), + fs_nosys, fs_nosys, + + VOPNAME_CMP, offsetof(struct vnodeops, vop_cmp), + fs_cmp, fs_cmp, /* no errors allowed */ + + VOPNAME_FRLOCK, offsetof(struct vnodeops, vop_frlock), + fs_frlock, fs_nosys, + + VOPNAME_SPACE, offsetof(struct vnodeops, vop_space), + fs_nosys, fs_nosys, + + VOPNAME_REALVP, offsetof(struct vnodeops, vop_realvp), + fs_nosys, fs_nosys, + + VOPNAME_GETPAGE, offsetof(struct vnodeops, vop_getpage), + fs_nosys, fs_nosys, + + VOPNAME_PUTPAGE, offsetof(struct vnodeops, vop_putpage), + fs_nosys, fs_nosys, + + VOPNAME_MAP, offsetof(struct vnodeops, vop_map), + (fs_generic_func_p) fs_nosys_map, + (fs_generic_func_p) fs_nosys_map, + + VOPNAME_ADDMAP, offsetof(struct vnodeops, vop_addmap), + (fs_generic_func_p) fs_nosys_addmap, + (fs_generic_func_p) fs_nosys_addmap, + + VOPNAME_DELMAP, offsetof(struct vnodeops, vop_delmap), + fs_nosys, fs_nosys, + + VOPNAME_POLL, offsetof(struct vnodeops, vop_poll), + (fs_generic_func_p) fs_poll, (fs_generic_func_p) fs_nosys_poll, + + VOPNAME_DUMP, offsetof(struct vnodeops, vop_dump), + fs_nosys, fs_nosys, + + VOPNAME_PATHCONF, offsetof(struct vnodeops, vop_pathconf), + fs_pathconf, fs_nosys, + + VOPNAME_PAGEIO, offsetof(struct vnodeops, vop_pageio), + fs_nosys, fs_nosys, + + VOPNAME_DUMPCTL, offsetof(struct vnodeops, vop_dumpctl), + fs_nosys, fs_nosys, + + VOPNAME_DISPOSE, offsetof(struct vnodeops, vop_dispose), + (fs_generic_func_p) fs_dispose, + (fs_generic_func_p) fs_nodispose, + + VOPNAME_SETSECATTR, offsetof(struct vnodeops, vop_setsecattr), + fs_nosys, fs_nosys, + + VOPNAME_GETSECATTR, offsetof(struct vnodeops, vop_getsecattr), + fs_fab_acl, fs_nosys, + + VOPNAME_SHRLOCK, offsetof(struct vnodeops, vop_shrlock), + fs_shrlock, fs_nosys, + + VOPNAME_VNEVENT, offsetof(struct vnodeops, vop_vnevent), + (fs_generic_func_p) fs_vnevent_nosupport, + (fs_generic_func_p) fs_vnevent_nosupport, + + VOPNAME_REQZCBUF, offsetof(struct vnodeops, vop_reqzcbuf), + fs_nosys, fs_nosys, + + VOPNAME_RETZCBUF, offsetof(struct vnodeops, vop_retzcbuf), + fs_nosys, fs_nosys, + + NULL, 0, NULL, NULL +}; + +/* Extensible attribute (xva) routines. */ + +/* + * Zero out the structure, set the size of the requested/returned bitmaps, + * set AT_XVATTR in the embedded vattr_t's va_mask, and set up the pointer + * to the returned attributes array. + */ +void +xva_init(xvattr_t *xvap) +{ + bzero(xvap, sizeof (xvattr_t)); + xvap->xva_mapsize = XVA_MAPSIZE; + xvap->xva_magic = XVA_MAGIC; + xvap->xva_vattr.va_mask = AT_XVATTR; + xvap->xva_rtnattrmapp = &(xvap->xva_rtnattrmap)[0]; +} + +/* + * If AT_XVATTR is set, returns a pointer to the embedded xoptattr_t + * structure. Otherwise, returns NULL. + */ +xoptattr_t * +xva_getxoptattr(xvattr_t *xvap) +{ + xoptattr_t *xoap = NULL; + if (xvap->xva_vattr.va_mask & AT_XVATTR) + xoap = &xvap->xva_xoptattrs; + return (xoap); +} + +// vska_compar +// create_vopstats_template +// new_vskstat +// vopstats_startup +// initialize_vopstats +// get_fstype_vopstats +// get_vskstat_anchor +// teardown_vopstats + +/* + * Read or write a vnode. Called from kernel code. + */ +int +vn_rdwr( + enum uio_rw rw, + struct vnode *vp, + caddr_t base, + ssize_t len, + offset_t offset, + enum uio_seg seg, + int ioflag, + rlim64_t ulimit, /* meaningful only if rw is UIO_WRITE */ + cred_t *cr, + ssize_t *residp) +{ + struct uio uio; + struct iovec iov; + int error; + int in_crit = 0; + + if (rw == UIO_WRITE && ISROFILE(vp)) + return (EROFS); + + if (len < 0) + return (EIO); + + VOPXID_MAP_CR(vp, cr); + + iov.iov_base = base; + iov.iov_len = len; + uio.uio_iov = &iov; + uio.uio_iovcnt = 1; + uio.uio_loffset = offset; + uio.uio_segflg = (short)seg; + uio.uio_resid = len; + uio.uio_llimit = ulimit; + + /* + * We have to enter the critical region before calling VOP_RWLOCK + * to avoid a deadlock with ufs. + */ + if (nbl_need_check(vp)) { + int svmand; + + nbl_start_crit(vp, RW_READER); + in_crit = 1; + error = nbl_svmand(vp, cr, &svmand); + if (error != 0) + goto done; + if (nbl_conflict(vp, rw == UIO_WRITE ? NBL_WRITE : NBL_READ, + uio.uio_offset, uio.uio_resid, svmand, NULL)) { + error = EACCES; + goto done; + } + } + + (void) VOP_RWLOCK(vp, + rw == UIO_WRITE ? V_WRITELOCK_TRUE : V_WRITELOCK_FALSE, NULL); + if (rw == UIO_WRITE) { + uio.uio_fmode = FWRITE; + uio.uio_extflg = UIO_COPY_DEFAULT; + error = VOP_WRITE(vp, &uio, ioflag, cr, NULL); + } else { + uio.uio_fmode = FREAD; + uio.uio_extflg = UIO_COPY_CACHED; + error = VOP_READ(vp, &uio, ioflag, cr, NULL); + } + VOP_RWUNLOCK(vp, + rw == UIO_WRITE ? V_WRITELOCK_TRUE : V_WRITELOCK_FALSE, NULL); + if (residp) + *residp = uio.uio_resid; + else if (uio.uio_resid) + error = EIO; + +done: + if (in_crit) + nbl_end_crit(vp); + return (error); +} + +/* + * Incremend the hold on a vnode + * (Real kernel uses a macro) + */ +void +vn_hold(struct vnode *vp) +{ + mutex_enter(&vp->v_lock); + (vp)->v_count++; + mutex_exit(&vp->v_lock); +} + +/* + * Release a vnode. Call VOP_INACTIVE on last reference or + * decrement reference count... + */ +void +vn_rele(vnode_t *vp) +{ + VERIFY(vp->v_count > 0); + mutex_enter(&vp->v_lock); + if (vp->v_count == 1) { + mutex_exit(&vp->v_lock); + VOP_INACTIVE(vp, CRED(), NULL); + return; + } + VN_RELE_LOCKED(vp); + mutex_exit(&vp->v_lock); +} + +// vn_rele_dnlc +// vn_rele_stream +// vn_rele_inactive +// vn_rele_async +// vn_open, vn_openat +// vn_open_upgrade +// vn_open_downgrade +// vn_create, vn_createat +// vn_link, vn_linkat +// vn_rename, vn_renameat +// vn_remove, vn_removeat + + +/* + * Utility function to compare equality of vnodes. + * Compare the underlying real vnodes, if there are underlying vnodes. + * This is a more thorough comparison than the VN_CMP() macro provides. + */ +int +vn_compare(vnode_t *vp1, vnode_t *vp2) +{ + vnode_t *realvp; + + if (vp1 != NULL && VOP_REALVP(vp1, &realvp, NULL) == 0) + vp1 = realvp; + if (vp2 != NULL && VOP_REALVP(vp2, &realvp, NULL) == 0) + vp2 = realvp; + return (VN_CMP(vp1, vp2)); +} + +// vn_vfslocks_buckets +// vn_vfslocks_getlock +// vn_vfslocks_rele + +static krwlock_t vfsentry_ve_lock; + +/* + * vn_vfswlock_wait is used to implement a lock which is logically a + * writers lock protecting the v_vfsmountedhere field. + * vn_vfswlock_wait has been modified to be similar to vn_vfswlock, + * except that it blocks to acquire the lock VVFSLOCK. + * + * traverse() and routines re-implementing part of traverse (e.g. autofs) + * need to hold this lock. mount(), vn_rename(), vn_remove() and so on + * need the non-blocking version of the writers lock i.e. vn_vfswlock + */ +int +vn_vfswlock_wait(vnode_t *vp) +{ + + ASSERT(vp != NULL); + + rw_enter(&vfsentry_ve_lock, RW_WRITER); + + return (0); +} + +int +vn_vfsrlock_wait(vnode_t *vp) +{ + + ASSERT(vp != NULL); + + rw_enter(&vfsentry_ve_lock, RW_READER); + + return (0); +} + +/* + * vn_vfswlock is used to implement a lock which is logically a writers lock + * protecting the v_vfsmountedhere field. + */ +int +vn_vfswlock(vnode_t *vp) +{ + + if (vp == NULL) + return (EBUSY); + + if (rw_tryenter(&vfsentry_ve_lock, RW_WRITER)) + return (0); + + return (EBUSY); +} + +int +vn_vfsrlock(vnode_t *vp) +{ + + if (vp == NULL) + return (EBUSY); + + if (rw_tryenter(&vfsentry_ve_lock, RW_READER)) + return (0); + + return (EBUSY); +} + +void +vn_vfsunlock(vnode_t *vp) +{ + + rw_exit(&vfsentry_ve_lock); +} + +int +vn_vfswlock_held(vnode_t *vp) +{ + int held; + + ASSERT(vp != NULL); + + held = rw_write_held(&vfsentry_ve_lock); + + return (held); +} + + +int +vn_make_ops( + const char *name, /* Name of file system */ + const fs_operation_def_t *templ, /* Operation specification */ + vnodeops_t **actual) /* Return the vnodeops */ +{ + int unused_ops; + int error; + + *actual = (vnodeops_t *)kmem_alloc(sizeof (vnodeops_t), KM_SLEEP); + + (*actual)->vnop_name = name; + + error = fs_build_vector(*actual, &unused_ops, vn_ops_table, templ); + if (error) { + kmem_free(*actual, sizeof (vnodeops_t)); + } + +#if DEBUG + if (unused_ops != 0) + cmn_err(CE_WARN, "vn_make_ops: %s: %d operations supplied " + "but not used", name, unused_ops); +#endif + + return (error); +} + +/* + * Free the vnodeops created as a result of vn_make_ops() + */ +void +vn_freevnodeops(vnodeops_t *vnops) +{ + kmem_free(vnops, sizeof (vnodeops_t)); +} + +/* + * Vnode cache. + */ + +/* ARGSUSED */ +static int +vn_cache_constructor(void *buf, void *cdrarg, int kmflags) +{ + struct vnode *vp = buf; + + bzero(vp, sizeof (*vp)); + mutex_init(&vp->v_lock, NULL, MUTEX_DEFAULT, NULL); + rw_init(&vp->v_nbllock, NULL, RW_DEFAULT, NULL); + vp->v_path = vn_vpath_empty; + vp->v_fd = -1; + vp->v_st_dev = NODEV; + + return (0); +} + +/* ARGSUSED */ +static void +vn_cache_destructor(void *buf, void *cdrarg) +{ + struct vnode *vp; + + vp = buf; + + rw_destroy(&vp->v_nbllock); + mutex_destroy(&vp->v_lock); +} + +void +vn_create_cache(void) +{ + vn_cache = kmem_cache_create("vn_cache", sizeof (struct vnode), + VNODE_ALIGN, vn_cache_constructor, vn_cache_destructor, NULL, NULL, + NULL, 0); +} + +void +vn_destroy_cache(void) +{ + kmem_cache_destroy(vn_cache); +} + +/* + * Used by file systems when fs-specific nodes (e.g., ufs inodes) are + * cached by the file system and vnodes remain associated. + */ +void +vn_recycle(vnode_t *vp) +{ + VERIFY(vp->v_path != NULL); + + /* + * XXX - This really belongs in vn_reinit(), but we have some issues + * with the counts. Best to have it here for clean initialization. + */ + vp->v_rdcnt = 0; + vp->v_wrcnt = 0; + + /* + * If FEM was in use... + */ + + if (vp->v_path != vn_vpath_empty) { + kmem_free(vp->v_path, strlen(vp->v_path) + 1); + vp->v_path = vn_vpath_empty; + } + // vsd_free(vp); +} + +/* + * Used to reset the vnode fields including those that are directly accessible + * as well as those which require an accessor function. + */ +void +vn_reinit(vnode_t *vp) +{ + vp->v_count = 1; + // vp->v_count_dnlc = 0; + vp->v_vfsp = NULL; + vp->v_stream = NULL; + vp->v_vfsmountedhere = NULL; + vp->v_flag = 0; + vp->v_type = VNON; + vp->v_rdev = NODEV; + + vp->v_xattrdir = NULL; + + /* + * In a few specific instances, vn_reinit() is used to initialize + * locally defined vnode_t instances. Lacking the construction offered + * by vn_alloc(), these vnodes require v_path initialization. + */ + if (vp->v_path == NULL) { + vp->v_path = vn_vpath_empty; + } + + /* Handles v_femhead, v_path, and the r/w/map counts */ + vn_recycle(vp); +} + +vnode_t * +vn_alloc(int kmflag) +{ + vnode_t *vp; + + vp = kmem_cache_alloc(vn_cache, kmflag); + + if (vp != NULL) { + // vp->v_femhead = NULL; /* Must be done before vn_reinit() */ + // vp->v_fopdata = NULL; + vn_reinit(vp); + } + + return (vp); +} + +void +vn_free(vnode_t *vp) +{ + extern vnode_t *rootdir; + ASSERT(vp != rootdir); + + /* + * Some file systems call vn_free() with v_count of zero, + * some with v_count of 1. In any case, the value should + * never be anything else. + */ + ASSERT((vp->v_count == 0) || (vp->v_count == 1)); + VERIFY(vp->v_path != NULL); + if (vp->v_path != vn_vpath_empty) { + kmem_free(vp->v_path, strlen(vp->v_path) + 1); + vp->v_path = vn_vpath_empty; + } + + /* If FEM was in use... */ + + // vsd_free(vp); + kmem_cache_free(vn_cache, vp); +} + +/* + * vnode status changes, should define better states than 1, 0. + */ +void +vn_reclaim(vnode_t *vp) +{ + vfs_t *vfsp = vp->v_vfsp; + + if (vfsp == NULL || + vfsp->vfs_implp == NULL || vfsp->vfs_femhead == NULL) { + return; + } + (void) VFS_VNSTATE(vfsp, vp, VNTRANS_RECLAIMED); +} + +void +vn_idle(vnode_t *vp) +{ + vfs_t *vfsp = vp->v_vfsp; + + if (vfsp == NULL || + vfsp->vfs_implp == NULL || vfsp->vfs_femhead == NULL) { + return; + } + (void) VFS_VNSTATE(vfsp, vp, VNTRANS_IDLED); +} +void +vn_exists(vnode_t *vp) +{ + vfs_t *vfsp = vp->v_vfsp; + + if (vfsp == NULL || + vfsp->vfs_implp == NULL || vfsp->vfs_femhead == NULL) { + return; + } + (void) VFS_VNSTATE(vfsp, vp, VNTRANS_EXISTS); +} + +void +vn_invalid(vnode_t *vp) +{ +} + +/* Vnode event notification */ +// vnevent_support() +// vnevent_... + +/* + * Vnode accessors. + */ + +int +vn_is_readonly(vnode_t *vp) +{ + return (vp->v_vfsp->vfs_flag & VFS_RDONLY); +} + +int +vn_has_flocks(vnode_t *vp) +{ + return (0); +} + +int +vn_has_mandatory_locks(vnode_t *vp, int mode) +{ + return (0); +} + +int +vn_has_cached_data(vnode_t *vp) +{ + return (0); +} + +// vn_can_change_zones + +/* + * Return nonzero if the vnode is a mount point, zero if not. + */ +int +vn_ismntpt(vnode_t *vp) +{ + return (vp->v_vfsmountedhere != NULL); +} + +/* Retrieve the vfs (if any) mounted on this vnode */ +vfs_t * +vn_mountedvfs(vnode_t *vp) +{ + return (vp->v_vfsmountedhere); +} + +/* + * Return nonzero if the vnode is referenced by the dnlc, zero if not. + * (no DNLC here) + */ +int +vn_in_dnlc(vnode_t *vp) +{ + return (0); +} + + +/* + * vn_has_other_opens() checks whether a particular file is opened by more than + * just the caller and whether the open is for read and/or write. + * This routine is for calling after the caller has already called VOP_OPEN() + * and the caller wishes to know if they are the only one with it open for + * the mode(s) specified. + * + * Vnode counts are only kept on regular files (v_type=VREG). + */ +int +vn_has_other_opens( + vnode_t *vp, + v_mode_t mode) +{ + + ASSERT(vp != NULL); + + switch (mode) { + case V_WRITE: + if (vp->v_wrcnt > 1) + return (V_TRUE); + break; + case V_RDORWR: + if ((vp->v_rdcnt > 1) || (vp->v_wrcnt > 1)) + return (V_TRUE); + break; + case V_RDANDWR: + if ((vp->v_rdcnt > 1) && (vp->v_wrcnt > 1)) + return (V_TRUE); + break; + case V_READ: + if (vp->v_rdcnt > 1) + return (V_TRUE); + break; + } + + return (V_FALSE); +} + +/* + * vn_is_opened() checks whether a particular file is opened and + * whether the open is for read and/or write. + * + * Vnode counts are only kept on regular files (v_type=VREG). + */ +int +vn_is_opened( + vnode_t *vp, + v_mode_t mode) +{ + + ASSERT(vp != NULL); + + switch (mode) { + case V_WRITE: + if (vp->v_wrcnt) + return (V_TRUE); + break; + case V_RDANDWR: + if (vp->v_rdcnt && vp->v_wrcnt) + return (V_TRUE); + break; + case V_RDORWR: + if (vp->v_rdcnt || vp->v_wrcnt) + return (V_TRUE); + break; + case V_READ: + if (vp->v_rdcnt) + return (V_TRUE); + break; + } + + return (V_FALSE); +} + +/* + * vn_is_mapped() checks whether a particular file is mapped and whether + * the file is mapped read and/or write. (no mmap here) + */ +int +vn_is_mapped( + vnode_t *vp, + v_mode_t mode) +{ + return (V_FALSE); +} + +/* + * Set the operations vector for a vnode. + */ +void +vn_setops(vnode_t *vp, vnodeops_t *vnodeops) +{ + + ASSERT(vp != NULL); + ASSERT(vnodeops != NULL); + + vp->v_op = vnodeops; +} + +/* + * Retrieve the operations vector for a vnode + */ +vnodeops_t * +vn_getops(vnode_t *vp) +{ + + ASSERT(vp != NULL); + + return (vp->v_op); +} + +/* + * Returns non-zero (1) if the vnodeops matches that of the vnode. + * Returns zero (0) if not. + */ +int +vn_matchops(vnode_t *vp, vnodeops_t *vnodeops) +{ + return (vn_getops(vp) == vnodeops); +} + +// vn_matchopval +// fs_new_caller_id + +// vn_clearpath +// vn_setpath_common + +/* ARGSUSED */ +void +vn_updatepath(vnode_t *pvp, vnode_t *vp, const char *name) +{ +} + +// vn_setpath... +// vn_renamepath +// vn_copypath + +// vn_vmpss_usepageio + +/* VOP_XXX() macros call the corresponding fop_xxx() function */ + +int +fop_open( + vnode_t **vpp, + int mode, + cred_t *cr, + caller_context_t *ct) +{ + int ret; + vnode_t *vp = *vpp; + + VN_HOLD(vp); + /* + * Adding to the vnode counts before calling open + * avoids the need for a mutex... + */ + if ((*vpp)->v_type == VREG) { + if (mode & FREAD) + atomic_inc_32(&(*vpp)->v_rdcnt); + if (mode & FWRITE) + atomic_inc_32(&(*vpp)->v_wrcnt); + } + + VOPXID_MAP_CR(vp, cr); + + ret = (*(*(vpp))->v_op->vop_open)(vpp, mode, cr, ct); + + if (ret) { + /* + * Use the saved vp just in case the vnode ptr got trashed + * by the error. + */ + VOPSTATS_UPDATE(vp, open); + if ((vp->v_type == VREG) && (mode & FREAD)) + atomic_dec_32(&vp->v_rdcnt); + if ((vp->v_type == VREG) && (mode & FWRITE)) + atomic_dec_32(&vp->v_wrcnt); + } else { + /* + * Some filesystems will return a different vnode, + * but the same path was still used to open it. + * So if we do change the vnode and need to + * copy over the path, do so here, rather than special + * casing each filesystem. Adjust the vnode counts to + * reflect the vnode switch. + */ + VOPSTATS_UPDATE(*vpp, open); + if (*vpp != vp && *vpp != NULL) { + // vn_copypath(vp, *vpp); + if (((*vpp)->v_type == VREG) && (mode & FREAD)) + atomic_inc_32(&(*vpp)->v_rdcnt); + if ((vp->v_type == VREG) && (mode & FREAD)) + atomic_dec_32(&vp->v_rdcnt); + if (((*vpp)->v_type == VREG) && (mode & FWRITE)) + atomic_inc_32(&(*vpp)->v_wrcnt); + if ((vp->v_type == VREG) && (mode & FWRITE)) + atomic_dec_32(&vp->v_wrcnt); + } + } + VN_RELE(vp); + return (ret); +} + +int +fop_close( + vnode_t *vp, + int flag, + int count, + offset_t offset, + cred_t *cr, + caller_context_t *ct) +{ + int err; + + VOPXID_MAP_CR(vp, cr); + + err = (*(vp)->v_op->vop_close)(vp, flag, count, offset, cr, ct); + VOPSTATS_UPDATE(vp, close); + /* + * Check passed in count to handle possible dups. Vnode counts are only + * kept on regular files + */ + if ((vp->v_type == VREG) && (count == 1)) { + if (flag & FREAD) { + ASSERT(vp->v_rdcnt > 0); + atomic_dec_32(&vp->v_rdcnt); + } + if (flag & FWRITE) { + ASSERT(vp->v_wrcnt > 0); + atomic_dec_32(&vp->v_wrcnt); + } + } + return (err); +} + +int +fop_read( + vnode_t *vp, + uio_t *uiop, + int ioflag, + cred_t *cr, + caller_context_t *ct) +{ + int err; + ssize_t resid_start = uiop->uio_resid; + + VOPXID_MAP_CR(vp, cr); + + err = (*(vp)->v_op->vop_read)(vp, uiop, ioflag, cr, ct); + VOPSTATS_UPDATE_IO(vp, read, + read_bytes, (resid_start - uiop->uio_resid)); + return (err); +} + +int +fop_write( + vnode_t *vp, + uio_t *uiop, + int ioflag, + cred_t *cr, + caller_context_t *ct) +{ + int err; + ssize_t resid_start = uiop->uio_resid; + + VOPXID_MAP_CR(vp, cr); + + err = (*(vp)->v_op->vop_write)(vp, uiop, ioflag, cr, ct); + VOPSTATS_UPDATE_IO(vp, write, + write_bytes, (resid_start - uiop->uio_resid)); + return (err); +} + +int +fop_ioctl( + vnode_t *vp, + int cmd, + intptr_t arg, + int flag, + cred_t *cr, + int *rvalp, + caller_context_t *ct) +{ + int err; + + VOPXID_MAP_CR(vp, cr); + + err = (*(vp)->v_op->vop_ioctl)(vp, cmd, arg, flag, cr, rvalp, ct); + VOPSTATS_UPDATE(vp, ioctl); + return (err); +} + +int +fop_setfl( + vnode_t *vp, + int oflags, + int nflags, + cred_t *cr, + caller_context_t *ct) +{ + int err; + + VOPXID_MAP_CR(vp, cr); + + err = (*(vp)->v_op->vop_setfl)(vp, oflags, nflags, cr, ct); + VOPSTATS_UPDATE(vp, setfl); + return (err); +} + +int +fop_getattr( + vnode_t *vp, + vattr_t *vap, + int flags, + cred_t *cr, + caller_context_t *ct) +{ + int err; + + VOPXID_MAP_CR(vp, cr); + + /* + * If this file system doesn't understand the xvattr extensions + * then turn off the xvattr bit. + */ + if (vfs_has_feature(vp->v_vfsp, VFSFT_XVATTR) == 0) { + vap->va_mask &= ~AT_XVATTR; + } + + /* + * We're only allowed to skip the ACL check iff we used a 32 bit + * ACE mask with VOP_ACCESS() to determine permissions. + */ + if ((flags & ATTR_NOACLCHECK) && + vfs_has_feature(vp->v_vfsp, VFSFT_ACEMASKONACCESS) == 0) { + return (EINVAL); + } + err = (*(vp)->v_op->vop_getattr)(vp, vap, flags, cr, ct); + VOPSTATS_UPDATE(vp, getattr); + return (err); +} + +int +fop_setattr( + vnode_t *vp, + vattr_t *vap, + int flags, + cred_t *cr, + caller_context_t *ct) +{ + int err; + + VOPXID_MAP_CR(vp, cr); + + /* + * If this file system doesn't understand the xvattr extensions + * then turn off the xvattr bit. + */ + if (vfs_has_feature(vp->v_vfsp, VFSFT_XVATTR) == 0) { + vap->va_mask &= ~AT_XVATTR; + } + + /* + * We're only allowed to skip the ACL check iff we used a 32 bit + * ACE mask with VOP_ACCESS() to determine permissions. + */ + if ((flags & ATTR_NOACLCHECK) && + vfs_has_feature(vp->v_vfsp, VFSFT_ACEMASKONACCESS) == 0) { + return (EINVAL); + } + err = (*(vp)->v_op->vop_setattr)(vp, vap, flags, cr, ct); + VOPSTATS_UPDATE(vp, setattr); + return (err); +} + +int +fop_access( + vnode_t *vp, + int mode, + int flags, + cred_t *cr, + caller_context_t *ct) +{ + int err; + + if ((flags & V_ACE_MASK) && + vfs_has_feature(vp->v_vfsp, VFSFT_ACEMASKONACCESS) == 0) { + return (EINVAL); + } + + VOPXID_MAP_CR(vp, cr); + + err = (*(vp)->v_op->vop_access)(vp, mode, flags, cr, ct); + VOPSTATS_UPDATE(vp, access); + return (err); +} + +int +fop_lookup( + vnode_t *dvp, + char *nm, + vnode_t **vpp, + pathname_t *pnp, + int flags, + vnode_t *rdir, + cred_t *cr, + caller_context_t *ct, + int *deflags, /* Returned per-dirent flags */ + pathname_t *ppnp) /* Returned case-preserved name in directory */ +{ + int ret; + + /* + * If this file system doesn't support case-insensitive access + * and said access is requested, fail quickly. It is required + * that if the vfs supports case-insensitive lookup, it also + * supports extended dirent flags. + */ + if (flags & FIGNORECASE && + (vfs_has_feature(dvp->v_vfsp, VFSFT_CASEINSENSITIVE) == 0 && + vfs_has_feature(dvp->v_vfsp, VFSFT_NOCASESENSITIVE) == 0)) + return (EINVAL); + + VOPXID_MAP_CR(dvp, cr); + + /* + * The real vnode.c would call xattr_dir_lookup here, + * which inserts the special "System Attribute" files: + * (SUNWattr_rw, SUNWattr_ro) into the xattr list. + * Here the main focus is on testing xattr support, + * so the system attribute stuff is ommitted. + */ +#if 0 + if ((flags & LOOKUP_XATTR) && (flags & LOOKUP_HAVE_SYSATTR_DIR) == 0) { + // Don't need xattr support in libfksmbfs. + // ret = xattr_dir_lookup(dvp, vpp, flags, cr); + ret = EINVAL; + } else +#endif + { + ret = (*(dvp)->v_op->vop_lookup) + (dvp, nm, vpp, pnp, flags, rdir, cr, ct, deflags, ppnp); + } + if (ret == 0 && *vpp) { + VOPSTATS_UPDATE(*vpp, lookup); + vn_updatepath(dvp, *vpp, nm); + } + + return (ret); +} + +int +fop_create( + vnode_t *dvp, + char *name, + vattr_t *vap, + vcexcl_t excl, + int mode, + vnode_t **vpp, + cred_t *cr, + int flags, + caller_context_t *ct, + vsecattr_t *vsecp) /* ACL to set during create */ +{ + int ret; + + if (vsecp != NULL && + vfs_has_feature(dvp->v_vfsp, VFSFT_ACLONCREATE) == 0) { + return (EINVAL); + } + /* + * If this file system doesn't support case-insensitive access + * and said access is requested, fail quickly. + */ + if (flags & FIGNORECASE && + (vfs_has_feature(dvp->v_vfsp, VFSFT_CASEINSENSITIVE) == 0 && + vfs_has_feature(dvp->v_vfsp, VFSFT_NOCASESENSITIVE) == 0)) + return (EINVAL); + + VOPXID_MAP_CR(dvp, cr); + + ret = (*(dvp)->v_op->vop_create) + (dvp, name, vap, excl, mode, vpp, cr, flags, ct, vsecp); + if (ret == 0 && *vpp) { + VOPSTATS_UPDATE(*vpp, create); + vn_updatepath(dvp, *vpp, name); + } + + return (ret); +} + +int +fop_remove( + vnode_t *dvp, + char *nm, + cred_t *cr, + caller_context_t *ct, + int flags) +{ + int err; + + /* + * If this file system doesn't support case-insensitive access + * and said access is requested, fail quickly. + */ + if (flags & FIGNORECASE && + (vfs_has_feature(dvp->v_vfsp, VFSFT_CASEINSENSITIVE) == 0 && + vfs_has_feature(dvp->v_vfsp, VFSFT_NOCASESENSITIVE) == 0)) + return (EINVAL); + + VOPXID_MAP_CR(dvp, cr); + + err = (*(dvp)->v_op->vop_remove)(dvp, nm, cr, ct, flags); + VOPSTATS_UPDATE(dvp, remove); + return (err); +} + +int +fop_link( + vnode_t *tdvp, + vnode_t *svp, + char *tnm, + cred_t *cr, + caller_context_t *ct, + int flags) +{ + int err; + + /* + * If the target file system doesn't support case-insensitive access + * and said access is requested, fail quickly. + */ + if (flags & FIGNORECASE && + (vfs_has_feature(tdvp->v_vfsp, VFSFT_CASEINSENSITIVE) == 0 && + vfs_has_feature(tdvp->v_vfsp, VFSFT_NOCASESENSITIVE) == 0)) + return (EINVAL); + + VOPXID_MAP_CR(tdvp, cr); + + err = (*(tdvp)->v_op->vop_link)(tdvp, svp, tnm, cr, ct, flags); + VOPSTATS_UPDATE(tdvp, link); + return (err); +} + +int +fop_rename( + vnode_t *sdvp, + char *snm, + vnode_t *tdvp, + char *tnm, + cred_t *cr, + caller_context_t *ct, + int flags) +{ + int err; + + /* + * If the file system involved does not support + * case-insensitive access and said access is requested, fail + * quickly. + */ + if (flags & FIGNORECASE && + ((vfs_has_feature(sdvp->v_vfsp, VFSFT_CASEINSENSITIVE) == 0 && + vfs_has_feature(sdvp->v_vfsp, VFSFT_NOCASESENSITIVE) == 0))) + return (EINVAL); + + VOPXID_MAP_CR(tdvp, cr); + + err = (*(sdvp)->v_op->vop_rename)(sdvp, snm, tdvp, tnm, cr, ct, flags); + VOPSTATS_UPDATE(sdvp, rename); + return (err); +} + +int +fop_mkdir( + vnode_t *dvp, + char *dirname, + vattr_t *vap, + vnode_t **vpp, + cred_t *cr, + caller_context_t *ct, + int flags, + vsecattr_t *vsecp) /* ACL to set during create */ +{ + int ret; + + if (vsecp != NULL && + vfs_has_feature(dvp->v_vfsp, VFSFT_ACLONCREATE) == 0) { + return (EINVAL); + } + /* + * If this file system doesn't support case-insensitive access + * and said access is requested, fail quickly. + */ + if (flags & FIGNORECASE && + (vfs_has_feature(dvp->v_vfsp, VFSFT_CASEINSENSITIVE) == 0 && + vfs_has_feature(dvp->v_vfsp, VFSFT_NOCASESENSITIVE) == 0)) + return (EINVAL); + + VOPXID_MAP_CR(dvp, cr); + + ret = (*(dvp)->v_op->vop_mkdir) + (dvp, dirname, vap, vpp, cr, ct, flags, vsecp); + if (ret == 0 && *vpp) { + VOPSTATS_UPDATE(*vpp, mkdir); + vn_updatepath(dvp, *vpp, dirname); + } + + return (ret); +} + +int +fop_rmdir( + vnode_t *dvp, + char *nm, + vnode_t *cdir, + cred_t *cr, + caller_context_t *ct, + int flags) +{ + int err; + + /* + * If this file system doesn't support case-insensitive access + * and said access is requested, fail quickly. + */ + if (flags & FIGNORECASE && + (vfs_has_feature(dvp->v_vfsp, VFSFT_CASEINSENSITIVE) == 0 && + vfs_has_feature(dvp->v_vfsp, VFSFT_NOCASESENSITIVE) == 0)) + return (EINVAL); + + VOPXID_MAP_CR(dvp, cr); + + err = (*(dvp)->v_op->vop_rmdir)(dvp, nm, cdir, cr, ct, flags); + VOPSTATS_UPDATE(dvp, rmdir); + return (err); +} + +int +fop_readdir( + vnode_t *vp, + uio_t *uiop, + cred_t *cr, + int *eofp, + caller_context_t *ct, + int flags) +{ + int err; + ssize_t resid_start = uiop->uio_resid; + + /* + * If this file system doesn't support retrieving directory + * entry flags and said access is requested, fail quickly. + */ + if (flags & V_RDDIR_ENTFLAGS && + vfs_has_feature(vp->v_vfsp, VFSFT_DIRENTFLAGS) == 0) + return (EINVAL); + + VOPXID_MAP_CR(vp, cr); + + err = (*(vp)->v_op->vop_readdir)(vp, uiop, cr, eofp, ct, flags); + VOPSTATS_UPDATE_IO(vp, readdir, + readdir_bytes, (resid_start - uiop->uio_resid)); + return (err); +} + +int +fop_symlink( + vnode_t *dvp, + char *linkname, + vattr_t *vap, + char *target, + cred_t *cr, + caller_context_t *ct, + int flags) +{ + int err; + xvattr_t xvattr; + + /* + * If this file system doesn't support case-insensitive access + * and said access is requested, fail quickly. + */ + if (flags & FIGNORECASE && + (vfs_has_feature(dvp->v_vfsp, VFSFT_CASEINSENSITIVE) == 0 && + vfs_has_feature(dvp->v_vfsp, VFSFT_NOCASESENSITIVE) == 0)) + return (EINVAL); + + VOPXID_MAP_CR(dvp, cr); + + /* check for reparse point */ + if ((vfs_has_feature(dvp->v_vfsp, VFSFT_REPARSE)) && + (strncmp(target, FS_REPARSE_TAG_STR, + strlen(FS_REPARSE_TAG_STR)) == 0)) { + if (!fs_reparse_mark(target, vap, &xvattr)) + vap = (vattr_t *)&xvattr; + } + + err = (*(dvp)->v_op->vop_symlink) + (dvp, linkname, vap, target, cr, ct, flags); + VOPSTATS_UPDATE(dvp, symlink); + return (err); +} + +int +fop_readlink( + vnode_t *vp, + uio_t *uiop, + cred_t *cr, + caller_context_t *ct) +{ + int err; + + VOPXID_MAP_CR(vp, cr); + + err = (*(vp)->v_op->vop_readlink)(vp, uiop, cr, ct); + VOPSTATS_UPDATE(vp, readlink); + return (err); +} + +int +fop_fsync( + vnode_t *vp, + int syncflag, + cred_t *cr, + caller_context_t *ct) +{ + int err; + + VOPXID_MAP_CR(vp, cr); + + err = (*(vp)->v_op->vop_fsync)(vp, syncflag, cr, ct); + VOPSTATS_UPDATE(vp, fsync); + return (err); +} + +void +fop_inactive( + vnode_t *vp, + cred_t *cr, + caller_context_t *ct) +{ + /* Need to update stats before vop call since we may lose the vnode */ + VOPSTATS_UPDATE(vp, inactive); + + VOPXID_MAP_CR(vp, cr); + + (*(vp)->v_op->vop_inactive)(vp, cr, ct); +} + +int +fop_fid( + vnode_t *vp, + fid_t *fidp, + caller_context_t *ct) +{ + int err; + + err = (*(vp)->v_op->vop_fid)(vp, fidp, ct); + VOPSTATS_UPDATE(vp, fid); + return (err); +} + +int +fop_rwlock( + vnode_t *vp, + int write_lock, + caller_context_t *ct) +{ + int ret; + + ret = ((*(vp)->v_op->vop_rwlock)(vp, write_lock, ct)); + VOPSTATS_UPDATE(vp, rwlock); + return (ret); +} + +void +fop_rwunlock( + vnode_t *vp, + int write_lock, + caller_context_t *ct) +{ + (*(vp)->v_op->vop_rwunlock)(vp, write_lock, ct); + VOPSTATS_UPDATE(vp, rwunlock); +} + +int +fop_seek( + vnode_t *vp, + offset_t ooff, + offset_t *noffp, + caller_context_t *ct) +{ + int err; + + err = (*(vp)->v_op->vop_seek)(vp, ooff, noffp, ct); + VOPSTATS_UPDATE(vp, seek); + return (err); +} + +int +fop_cmp( + vnode_t *vp1, + vnode_t *vp2, + caller_context_t *ct) +{ + int err; + + err = (*(vp1)->v_op->vop_cmp)(vp1, vp2, ct); + VOPSTATS_UPDATE(vp1, cmp); + return (err); +} + +int +fop_frlock( + vnode_t *vp, + int cmd, + flock64_t *bfp, + int flag, + offset_t offset, + struct flk_callback *flk_cbp, + cred_t *cr, + caller_context_t *ct) +{ + int err; + + VOPXID_MAP_CR(vp, cr); + + err = (*(vp)->v_op->vop_frlock) + (vp, cmd, bfp, flag, offset, flk_cbp, cr, ct); + VOPSTATS_UPDATE(vp, frlock); + return (err); +} + +int +fop_space( + vnode_t *vp, + int cmd, + flock64_t *bfp, + int flag, + offset_t offset, + cred_t *cr, + caller_context_t *ct) +{ + int err; + + VOPXID_MAP_CR(vp, cr); + + err = (*(vp)->v_op->vop_space)(vp, cmd, bfp, flag, offset, cr, ct); + VOPSTATS_UPDATE(vp, space); + return (err); +} + +int +fop_realvp( + vnode_t *vp, + vnode_t **vpp, + caller_context_t *ct) +{ + int err; + + err = (*(vp)->v_op->vop_realvp)(vp, vpp, ct); + VOPSTATS_UPDATE(vp, realvp); + return (err); +} + +int +fop_getpage( + vnode_t *vp, + offset_t off, + size_t len, + uint_t *protp, + page_t **plarr, + size_t plsz, + struct seg *seg, + caddr_t addr, + enum seg_rw rw, + cred_t *cr, + caller_context_t *ct) +{ + int err; + + VOPXID_MAP_CR(vp, cr); + + err = (*(vp)->v_op->vop_getpage) + (vp, off, len, protp, plarr, plsz, seg, addr, rw, cr, ct); + VOPSTATS_UPDATE(vp, getpage); + return (err); +} + +int +fop_putpage( + vnode_t *vp, + offset_t off, + size_t len, + int flags, + cred_t *cr, + caller_context_t *ct) +{ + int err; + + VOPXID_MAP_CR(vp, cr); + + err = (*(vp)->v_op->vop_putpage)(vp, off, len, flags, cr, ct); + VOPSTATS_UPDATE(vp, putpage); + return (err); +} + +int +fop_map( + vnode_t *vp, + offset_t off, + struct as *as, + caddr_t *addrp, + size_t len, + uchar_t prot, + uchar_t maxprot, + uint_t flags, + cred_t *cr, + caller_context_t *ct) +{ + int err; + + VOPXID_MAP_CR(vp, cr); + + err = (*(vp)->v_op->vop_map) + (vp, off, as, addrp, len, prot, maxprot, flags, cr, ct); + VOPSTATS_UPDATE(vp, map); + return (err); +} + +int +fop_addmap( + vnode_t *vp, + offset_t off, + struct as *as, + caddr_t addr, + size_t len, + uchar_t prot, + uchar_t maxprot, + uint_t flags, + cred_t *cr, + caller_context_t *ct) +{ + int error; + + VOPXID_MAP_CR(vp, cr); + + error = (*(vp)->v_op->vop_addmap) + (vp, off, as, addr, len, prot, maxprot, flags, cr, ct); + + VOPSTATS_UPDATE(vp, addmap); + return (error); +} + +int +fop_delmap( + vnode_t *vp, + offset_t off, + struct as *as, + caddr_t addr, + size_t len, + uint_t prot, + uint_t maxprot, + uint_t flags, + cred_t *cr, + caller_context_t *ct) +{ + int error; + + VOPXID_MAP_CR(vp, cr); + + error = (*(vp)->v_op->vop_delmap) + (vp, off, as, addr, len, prot, maxprot, flags, cr, ct); + + VOPSTATS_UPDATE(vp, delmap); + return (error); +} + + +int +fop_poll( + vnode_t *vp, + short events, + int anyyet, + short *reventsp, + struct pollhead **phpp, + caller_context_t *ct) +{ + int err; + + err = (*(vp)->v_op->vop_poll)(vp, events, anyyet, reventsp, phpp, ct); + VOPSTATS_UPDATE(vp, poll); + return (err); +} + +int +fop_dump( + vnode_t *vp, + caddr_t addr, + offset_t lbdn, + offset_t dblks, + caller_context_t *ct) +{ + int err; + + /* ensure lbdn and dblks can be passed safely to bdev_dump */ + if ((lbdn != (daddr_t)lbdn) || (dblks != (int)dblks)) + return (EIO); + + err = (*(vp)->v_op->vop_dump)(vp, addr, lbdn, dblks, ct); + VOPSTATS_UPDATE(vp, dump); + return (err); +} + +int +fop_pathconf( + vnode_t *vp, + int cmd, + ulong_t *valp, + cred_t *cr, + caller_context_t *ct) +{ + int err; + + VOPXID_MAP_CR(vp, cr); + + err = (*(vp)->v_op->vop_pathconf)(vp, cmd, valp, cr, ct); + VOPSTATS_UPDATE(vp, pathconf); + return (err); +} + +int +fop_pageio( + vnode_t *vp, + struct page *pp, + u_offset_t io_off, + size_t io_len, + int flags, + cred_t *cr, + caller_context_t *ct) +{ + int err; + + VOPXID_MAP_CR(vp, cr); + + err = (*(vp)->v_op->vop_pageio)(vp, pp, io_off, io_len, flags, cr, ct); + VOPSTATS_UPDATE(vp, pageio); + return (err); +} + +int +fop_dumpctl( + vnode_t *vp, + int action, + offset_t *blkp, + caller_context_t *ct) +{ + int err; + err = (*(vp)->v_op->vop_dumpctl)(vp, action, blkp, ct); + VOPSTATS_UPDATE(vp, dumpctl); + return (err); +} + +void +fop_dispose( + vnode_t *vp, + page_t *pp, + int flag, + int dn, + cred_t *cr, + caller_context_t *ct) +{ + /* Must do stats first since it's possible to lose the vnode */ + VOPSTATS_UPDATE(vp, dispose); + + VOPXID_MAP_CR(vp, cr); + + (*(vp)->v_op->vop_dispose)(vp, pp, flag, dn, cr, ct); +} + +int +fop_setsecattr( + vnode_t *vp, + vsecattr_t *vsap, + int flag, + cred_t *cr, + caller_context_t *ct) +{ + int err; + + VOPXID_MAP_CR(vp, cr); + + /* + * We're only allowed to skip the ACL check iff we used a 32 bit + * ACE mask with VOP_ACCESS() to determine permissions. + */ + if ((flag & ATTR_NOACLCHECK) && + vfs_has_feature(vp->v_vfsp, VFSFT_ACEMASKONACCESS) == 0) { + return (EINVAL); + } + err = (*(vp)->v_op->vop_setsecattr) (vp, vsap, flag, cr, ct); + VOPSTATS_UPDATE(vp, setsecattr); + return (err); +} + +int +fop_getsecattr( + vnode_t *vp, + vsecattr_t *vsap, + int flag, + cred_t *cr, + caller_context_t *ct) +{ + int err; + + /* + * We're only allowed to skip the ACL check iff we used a 32 bit + * ACE mask with VOP_ACCESS() to determine permissions. + */ + if ((flag & ATTR_NOACLCHECK) && + vfs_has_feature(vp->v_vfsp, VFSFT_ACEMASKONACCESS) == 0) { + return (EINVAL); + } + + VOPXID_MAP_CR(vp, cr); + + err = (*(vp)->v_op->vop_getsecattr) (vp, vsap, flag, cr, ct); + VOPSTATS_UPDATE(vp, getsecattr); + return (err); +} + +int +fop_shrlock( + vnode_t *vp, + int cmd, + struct shrlock *shr, + int flag, + cred_t *cr, + caller_context_t *ct) +{ + int err; + + VOPXID_MAP_CR(vp, cr); + + err = (*(vp)->v_op->vop_shrlock)(vp, cmd, shr, flag, cr, ct); + VOPSTATS_UPDATE(vp, shrlock); + return (err); +} + +int +fop_vnevent(vnode_t *vp, vnevent_t vnevent, vnode_t *dvp, char *fnm, + caller_context_t *ct) +{ + int err; + + err = (*(vp)->v_op->vop_vnevent)(vp, vnevent, dvp, fnm, ct); + VOPSTATS_UPDATE(vp, vnevent); + return (err); +} + +// fop_reqzcbuf +// fop_retzcbuf + +// vsd_defaultdestructor +// vsd_create, vsd_destroy +// vsd_get, vsd_set +// vsd_free, vsd_realloc + +static int +fs_reparse_mark(char *target, vattr_t *vap, xvattr_t *xvattr) +{ + return (-1); +} + +/* + * Function to check whether a symlink is a reparse point. + * Return B_TRUE if it is a reparse point, else return B_FALSE + */ +boolean_t +vn_is_reparse(vnode_t *vp, cred_t *cr, caller_context_t *ct) +{ + xvattr_t xvattr; + xoptattr_t *xoap; + + if ((vp->v_type != VLNK) || + !(vfs_has_feature(vp->v_vfsp, VFSFT_XVATTR))) + return (B_FALSE); + + xva_init(&xvattr); + xoap = xva_getxoptattr(&xvattr); + ASSERT(xoap); + XVA_SET_REQ(&xvattr, XAT_REPARSE); + + if (VOP_GETATTR(vp, &xvattr.xva_vattr, 0, cr, ct)) + return (B_FALSE); + + if ((!(xvattr.xva_vattr.va_mask & AT_XVATTR)) || + (!(XVA_ISSET_RTN(&xvattr, XAT_REPARSE)))) + return (B_FALSE); + + return (xoap->xoa_reparse ? B_TRUE : B_FALSE); +} diff --git a/usr/src/lib/smbclnt/libfksmbfs/common/fake_zone.c b/usr/src/lib/smbclnt/libfksmbfs/common/fake_zone.c new file mode 100644 index 0000000000..5593a8d542 --- /dev/null +++ b/usr/src/lib/smbclnt/libfksmbfs/common/fake_zone.c @@ -0,0 +1,76 @@ +/* + * 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 (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2015, Joyent Inc. All rights reserved. + * Copyright (c) 2016 by Delphix. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + */ + +/* + * Simulating just one zone here (the global zone) + */ + +#include +#include +#include + +static void *zone_specific_val; +static void *(*zkey_create)(zoneid_t); +// static void (*zkey_shutdown)(zoneid_t, void *); +// static void (*zkey_destroy)(zoneid_t, void *); + +/* ARGSUSED */ +void +zone_key_create(zone_key_t *keyp, void *(*create)(zoneid_t), + void (*shutdown)(zoneid_t, void *), void (*destroy)(zoneid_t, void *)) +{ + + zkey_create = create; + // zkey_shutdown = shutdown; + // zkey_destroy = destroy; + *keyp = 1; +} + +/* ARGSUSED */ +int +zone_key_delete(zone_key_t key) +{ + return (-1); +} + +/* ARGSUSED */ +int +zone_setspecific(zone_key_t key, zone_t *zone, const void *data) +{ + return (-1); +} + +/* ARGSUSED */ +void * +zone_getspecific(zone_key_t key, zone_t *zone) +{ + ASSERT(key == 1); + if (zone_specific_val == NULL) + zone_specific_val = (*zkey_create)(zone->zone_id); + return (zone_specific_val); +} diff --git a/usr/src/lib/smbclnt/libfksmbfs/common/fksmbfs_rwlock.c b/usr/src/lib/smbclnt/libfksmbfs/common/fksmbfs_rwlock.c new file mode 100644 index 0000000000..ee92e3ed67 --- /dev/null +++ b/usr/src/lib/smbclnt/libfksmbfs/common/fksmbfs_rwlock.c @@ -0,0 +1,235 @@ +/* + * 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 2017 Nexenta Systems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * Copyright (c) 1983,1984,1985,1986,1987,1988,1989 AT&T. + * All rights reserved. + */ + +/* + * A homegrown reader/writer lock implementation. It addresses + * two requirements not addressed by the system primitives. They + * are that the `enter" operation is optionally interruptible and + * that that they can be re`enter'ed by writers without deadlock. + * + * All of this was borrowed from NFS. + * See: uts/common/fs/nfs/nfs_subr.c + * + * XXX: Could we make this serve our needs instead? + * See: uts/common/os/rwstlock.c + * (and then use it for NFS too) + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + + +/* + * Only can return non-zero if intr != 0. + */ +int +smbfs_rw_enter_sig(smbfs_rwlock_t *l, krw_t rw, int intr) +{ + + mutex_enter(&l->lock); + + /* + * If this is a nested enter, then allow it. There + * must be as many exits as enters through. + */ + if (l->owner == curthread) { + /* lock is held for writing by current thread */ + ASSERT(rw == RW_READER || rw == RW_WRITER); + l->count--; + } else if (rw == RW_READER) { + /* + * While there is a writer active or writers waiting, + * then wait for them to finish up and move on. Then, + * increment the count to indicate that a reader is + * active. + */ + while (l->count < 0 || l->waiters > 0) { + if (intr) { + // lwp_nostop stuff... + (void) cv_wait_sig(&l->cv, &l->lock); + } else + cv_wait(&l->cv, &l->lock); + } + ASSERT(l->count < INT_MAX); +#ifdef SMBDEBUG + if ((l->count % 10000) == 9999) + cmn_err(CE_WARN, "smbfs_rw_enter_sig: count %d on" + "rwlock @ %p\n", l->count, (void *)&l); +#endif + l->count++; + } else { + ASSERT(rw == RW_WRITER); + /* + * While there are readers active or a writer + * active, then wait for all of the readers + * to finish or for the writer to finish. + * Then, set the owner field to curthread and + * decrement count to indicate that a writer + * is active. + */ + while (l->count > 0 || l->owner != NULL) { + l->waiters++; + if (intr) { + // lwp_nostop stuff... + if (!cv_wait_sig(&l->cv, &l->lock)) { + l->waiters--; + cv_broadcast(&l->cv); + mutex_exit(&l->lock); + return (EINTR); + } + } else + cv_wait(&l->cv, &l->lock); + l->waiters--; + } + l->owner = curthread; + l->count--; + } + + mutex_exit(&l->lock); + + return (0); +} + +/* + * If the lock is available, obtain it and return non-zero. If there is + * already a conflicting lock, return 0 immediately. + */ + +int +smbfs_rw_tryenter(smbfs_rwlock_t *l, krw_t rw) +{ + mutex_enter(&l->lock); + + /* + * If this is a nested enter, then allow it. There + * must be as many exits as enters through. + */ + if (l->owner == curthread) { + /* lock is held for writing by current thread */ + ASSERT(rw == RW_READER || rw == RW_WRITER); + l->count--; + } else if (rw == RW_READER) { + /* + * If there is a writer active or writers waiting, deny the + * lock. Otherwise, bump the count of readers. + */ + if (l->count < 0 || l->waiters > 0) { + mutex_exit(&l->lock); + return (0); + } + l->count++; + } else { + ASSERT(rw == RW_WRITER); + /* + * If there are readers active or a writer active, deny the + * lock. Otherwise, set the owner field to curthread and + * decrement count to indicate that a writer is active. + */ + if (l->count > 0 || l->owner != NULL) { + mutex_exit(&l->lock); + return (0); + } + l->owner = curthread; + l->count--; + } + + mutex_exit(&l->lock); + + return (1); +} + +void +smbfs_rw_exit(smbfs_rwlock_t *l) +{ + + mutex_enter(&l->lock); + /* + * If this is releasing a writer lock, then increment count to + * indicate that there is one less writer active. If this was + * the last of possibly nested writer locks, then clear the owner + * field as well to indicate that there is no writer active + * and wakeup any possible waiting writers or readers. + * + * If releasing a reader lock, then just decrement count to + * indicate that there is one less reader active. If this was + * the last active reader and there are writer(s) waiting, + * then wake up the first. + */ + if (l->owner != NULL) { + ASSERT(l->owner == curthread); + l->count++; + if (l->count == 0) { + l->owner = NULL; + cv_broadcast(&l->cv); + } + } else { + ASSERT(l->count > 0); + l->count--; + if (l->count == 0 && l->waiters > 0) + cv_broadcast(&l->cv); + } + mutex_exit(&l->lock); +} + +int +smbfs_rw_lock_held(smbfs_rwlock_t *l, krw_t rw) +{ + + if (rw == RW_READER) + return (l->count > 0); + ASSERT(rw == RW_WRITER); + return (l->count < 0); +} + +/* ARGSUSED */ +void +smbfs_rw_init(smbfs_rwlock_t *l, char *name, krw_type_t type, void *arg) +{ + + l->count = 0; + l->waiters = 0; + l->owner = NULL; + mutex_init(&l->lock, NULL, MUTEX_DEFAULT, NULL); + cv_init(&l->cv, NULL, CV_DEFAULT, NULL); +} + +void +smbfs_rw_destroy(smbfs_rwlock_t *l) +{ + + mutex_destroy(&l->lock); + cv_destroy(&l->cv); +} diff --git a/usr/src/lib/smbclnt/libfksmbfs/common/libfksmbfs.h b/usr/src/lib/smbclnt/libfksmbfs/common/libfksmbfs.h new file mode 100644 index 0000000000..e168b008af --- /dev/null +++ b/usr/src/lib/smbclnt/libfksmbfs/common/libfksmbfs.h @@ -0,0 +1,73 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + */ + +#ifndef _LIBFKSMBFS_H_ +#define _LIBFKSMBFS_H_ + +/* + * Declarations for exports in fake_vfs.c + */ + +#include +#include +#include +#include + +#ifndef MAXOFF32_T +#define MAXOFF32_T 0x7fffffff +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Need these visible outside _FAKE_KERNEL for the test CLI. + * In the kmod/lib build these duplicate declarations in vfs.h or + * vnode.h but that's OK as long as the declarations are identical. + */ +struct mounta; +struct stat64; +int fake_installfs(vfsdef_t *); +int fake_removefs(vfsdef_t *); +int fake_domount(char *, struct mounta *, struct vfs **); +int fake_dounmount(struct vfs *, int); +int fake_lookup(vnode_t *, char *, vnode_t **); +int fake_lookup_dir(char *, vnode_t **, char **); +int fake_stat(vnode_t *, struct stat64 *, int); +int fake_getdents(vnode_t *, offset_t *, void *, size_t); +ssize_t fake_pread(vnode_t *, void *, size_t, off_t); +ssize_t fake_pwrite(vnode_t *, void *, size_t, off_t); +int fake_unlink(char *, int); +int fake_rename(char *, char *); + +int vn_close_rele(vnode_t *vp, int flag); +int vn_open(char *pnamep, enum uio_seg seg, int filemode, int createmode, + struct vnode **vpp, enum create crwhy, mode_t umask); +int vn_create(char *pnamep, enum uio_seg seg, struct vattr *vap, + enum vcexcl excl, int mode, struct vnode **vpp, + enum create why, int flag, mode_t umask); + +void vn_rele(struct vnode *vp); + +/* In the real smbfs, these are _init(), _fini() */ +int fksmbfs_init(void); +int fksmbfs_fini(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBFKSMBFS_H_ */ diff --git a/usr/src/lib/smbclnt/libfksmbfs/common/llib-lfksmbfs b/usr/src/lib/smbclnt/libfksmbfs/common/llib-lfksmbfs new file mode 100644 index 0000000000..6e7f55f31d --- /dev/null +++ b/usr/src/lib/smbclnt/libfksmbfs/common/llib-lfksmbfs @@ -0,0 +1,19 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + */ + +/*LINTLIBRARY*/ +/*PROTOLIB1*/ + +#include diff --git a/usr/src/lib/smbclnt/libfksmbfs/common/mapfile-vers b/usr/src/lib/smbclnt/libfksmbfs/common/mapfile-vers new file mode 100644 index 0000000000..6e8b11a4ef --- /dev/null +++ b/usr/src/lib/smbclnt/libfksmbfs/common/mapfile-vers @@ -0,0 +1,68 @@ +# +# 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 (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2017 Nexenta Systems, Inc. All rights reserved. +# + +# +# MAPFILE HEADER START +# +# WARNING: STOP NOW. DO NOT MODIFY THIS FILE. +# Object versioning must comply with the rules detailed in +# +# usr/src/lib/README.mapfiles +# +# You should not be making modifications here until you've read the most current +# copy of that file. If you need help, contact a gatekeeper for guidance. +# +# MAPFILE HEADER END +# + +$mapfile_version 2 + +SYMBOL_VERSION SUNWprivate { + global: + fake_domount; + fake_dounmount; + fake_lookup; + fake_lookup_dir; + fake_getdents; + fake_pread; + fake_pwrite; + fake_rename; + fake_stat; + fake_unlink; + + fksmbfs_fini; + fksmbfs_init; + + fsop_root; + fsop_statfs; + fsop_sync; + + vn_close_rele; + vn_create; + vn_open; + vn_rele; + local: + *; +}; diff --git a/usr/src/lib/smbclnt/libfksmbfs/i386/Makefile b/usr/src/lib/smbclnt/libfksmbfs/i386/Makefile new file mode 100644 index 0000000000..6e1eb18522 --- /dev/null +++ b/usr/src/lib/smbclnt/libfksmbfs/i386/Makefile @@ -0,0 +1,20 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2017 Nexenta Systems, Inc. All rights reserved. +# + +include ../Makefile.com + +DYNFLAGS += -R/usr/lib/smbfs + +install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) diff --git a/usr/src/lib/smbclnt/libfksmbfs/sparc/Makefile b/usr/src/lib/smbclnt/libfksmbfs/sparc/Makefile new file mode 100644 index 0000000000..6e1eb18522 --- /dev/null +++ b/usr/src/lib/smbclnt/libfksmbfs/sparc/Makefile @@ -0,0 +1,20 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2017 Nexenta Systems, Inc. All rights reserved. +# + +include ../Makefile.com + +DYNFLAGS += -R/usr/lib/smbfs + +install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) diff --git a/usr/src/lib/smbclnt/libfksmbfs/sparcv9/Makefile b/usr/src/lib/smbclnt/libfksmbfs/sparcv9/Makefile new file mode 100644 index 0000000000..151660294b --- /dev/null +++ b/usr/src/lib/smbclnt/libfksmbfs/sparcv9/Makefile @@ -0,0 +1,24 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2017 Nexenta Systems, Inc. All rights reserved. +# + +MACH_LDLIBS += -L$(ROOT)/usr/lib/smbfs/$(MACH64) + +include ../Makefile.com +include ../../../Makefile.lib.64 + +DYNFLAGS += -R/usr/lib/smbfs/$(MACH64) +sparcv9_C_PICFLAGS= $(sparcv9_C_BIGPICFLAGS) + +install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64) -- cgit v1.2.3