diff options
author | wollman <wollman@FreeBSD.org> | 1994-09-22 01:07:37 +0000 |
---|---|---|
committer | wollman <wollman@FreeBSD.org> | 1994-09-22 01:07:37 +0000 |
commit | 6c7f19942f7afda8224cd0d083cde770c20e3a02 (patch) | |
tree | e28394cb93d13ad2a5e9d42da6e310addf31edd2 /lib | |
parent | 57d5fc27aeeacccb0bf162a0c76960fcee592e70 (diff) | |
download | FreeBSD-src-6c7f19942f7afda8224cd0d083cde770c20e3a02.zip FreeBSD-src-6c7f19942f7afda8224cd0d083cde770c20e3a02.tar.gz |
Added VFS functions: getvfsvbyname, getvfsbytype, getvfsent, setvfsent,
endvfsent, vfsisloadable, vfsload.
Someday these will even be documented.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libc/gen/Makefile.inc | 2 | ||||
-rw-r--r-- | lib/libc/gen/getvfsent.c | 234 |
2 files changed, 235 insertions, 1 deletions
diff --git a/lib/libc/gen/Makefile.inc b/lib/libc/gen/Makefile.inc index f6e0346..fb9cb58 100644 --- a/lib/libc/gen/Makefile.inc +++ b/lib/libc/gen/Makefile.inc @@ -17,7 +17,7 @@ SRCS+= alarm.c assert.c clock.c closedir.c confstr.c crypt.c ctermid.c \ sigsetjmp.c sigsetops.c sleep.c sysconf.c sysctl.c syslog.c \ telldir.c termios.c time.c times.c timezone.c ttyname.c ttyslot.c \ ualarm.c uname.c unvis.c usleep.c utime.c valloc.c vis.c wait.c \ - wait3.c waitpid.c + wait3.c waitpid.c getvfsent.c # machine-dependent gen sources .include "${.CURDIR}/${MACHINE}/gen/Makefile.inc" diff --git a/lib/libc/gen/getvfsent.c b/lib/libc/gen/getvfsent.c new file mode 100644 index 0000000..4bf247d --- /dev/null +++ b/lib/libc/gen/getvfsent.c @@ -0,0 +1,234 @@ +/* + * getvfsent.c - get a listing of installed filesystems + * Written September 1994 by Garrett A. Wollman + * This file is in the public domain. + */ + +#include <sys/param.h> +#include <sys/types.h> +#include <sys/mount.h> +#include <sys/sysctl.h> +#include <unistd.h> +#include <sys/file.h> +#include <sys/wait.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <paths.h> + +static struct vfsconf *_vfslist = 0; +static struct vfsconf _vfsconf; +static size_t _vfslistlen = 0; +static int _vfs_keeplist = 0; +static int _vfs_index = 0; + +static int +initvfs(void) +{ + int mib[2] = { CTL_FS, FS_VFSCONF }; + size_t size = 0; + int rv; + + rv = sysctl(mib, 2, (void *)0, &size, (void *)0, (size_t)0); + if(rv < 0) + return 0; + + if(_vfslist) + free(_vfslist); + _vfslist = malloc(size); + if(!_vfslist) + return 0; + + rv = sysctl(mib, 2, _vfslist, &size, (void *)0, (size_t)0); + if(rv < 0) { + free(_vfslist); + _vfslist = 0; + return 0; + } + + _vfslistlen = size / sizeof _vfslist[0]; + return 1; +} + +struct vfsconf * +getvfsent(void) +{ + if(!_vfslist && !initvfs()) { + return 0; + } + + do { + if(_vfs_index > _vfslistlen) { + return 0; + } + + _vfsconf = _vfslist[_vfs_index++]; + } while(!_vfsconf.vfc_vfsops); + + if(!_vfs_keeplist) { + free(_vfslist); + _vfslist = 0; + } + return &_vfsconf; +} + +struct vfsconf * +getvfsbyname(const char *name) +{ + int i; + + if(!_vfslist && !initvfs()) { + return 0; + } + + for(i = 0; i < _vfslistlen; i++) { + if( ! strcmp(_vfslist[i].vfc_name, name) ) + break; + } + + if(!_vfs_keeplist) { + free(_vfslist); + _vfslist = 0; + } + + if(i < _vfslistlen) { + _vfsconf = _vfslist[i]; + return &_vfsconf; + } else { + return 0; + } +} + +struct vfsconf * +getvfsbytype(int type) +{ + int i; + + if(!_vfslist && !initvfs()) { + return 0; + } + + for(i = 0; i < _vfslistlen; i++) { + if(_vfslist[i].vfc_index == type) + break; + } + + if(!_vfs_keeplist) { + free(_vfslist); + _vfslist = 0; + } + + if(i < _vfslistlen) { + _vfsconf = _vfslist[i]; + return &_vfsconf; + } else { + return 0; + } +} + +void +setvfsent(int keep) +{ + if(_vfslist && !keep) { + free(_vfslist); + _vfslist = 0; + } + + _vfs_keeplist = keep; + _vfs_index = 0; +} + +void +endvfsent(void) +{ + if(_vfslist) { + free(_vfslist); + _vfslist = 0; + } + + _vfs_index = 0; +} + +static const char *vfs_lkmdirs[] = { + "/lkm", + "/usr/lkm", + 0, + 0 +}; +#define NLKMDIRS ((sizeof vfs_lkmdirs) / (sizeof vfs_lkmdirs[0])) + +static const char * +vfspath(const char *name) +{ + static char pnbuf[MAXPATHLEN]; + char *userdir = getenv("LKMDIR"); + int i; + + if(userdir) { + vfs_lkmdirs[NLKMDIRS - 2] = userdir; + } + + for(i = 0; vfs_lkmdirs[i]; i++) { + snprintf(pnbuf, sizeof pnbuf, "%s/%s_mod.o", vfs_lkmdirs[i], name); + if( ! access(pnbuf, R_OK) ) + return pnbuf; + } + + return 0; +} + +int +vfsisloadable(const char *name) +{ + return !!vfspath(name); +} + +int +vfsload(const char *name) +{ + const char *path = vfspath(name); + char name_mod[sizeof("_mod") + strlen(name)]; + pid_t pid; + int status; + + if(!path) { + errno = ENOENT; + return -1; + } + + pid = fork(); + if(pid < 0) + return -1; + + if(pid > 0) { + waitpid(pid, &status, 0); + if(WIFEXITED(status)) { + errno = WEXITSTATUS(status); + return errno ? -1 : 0; + } + errno = EINVAL; /* not enough errno values, >sigh< */ + return -1; + } + + status = -1; + if(getenv("TMPDIR")) { + status = chdir(getenv("TMPDIR")); + } + if(status) { + status = chdir(_PATH_VARTMP); + } + if(status) { + status = chdir(_PATH_TMP); + } + if(status) { + exit(status ? errno : 0); + } + + snprintf(name_mod, sizeof name_mod, "%s%s", name, "_mod"); + status = execlp("modload", "modload", "-e", name_mod, "-o", name_mod, + path, (const char *)0); + + exit(status ? errno : 0); +} + |