diff options
author | rodrigc <rodrigc@FreeBSD.org> | 2005-11-09 02:26:38 +0000 |
---|---|---|
committer | rodrigc <rodrigc@FreeBSD.org> | 2005-11-09 02:26:38 +0000 |
commit | 2cbc12617e8c6974b4bda15456acae526d368800 (patch) | |
tree | 8eddfac7b29b5a7fad453c44b20affc562348555 /sys/kern | |
parent | 709559d97f388b2395bb9ba4b76d96975cbb5113 (diff) | |
download | FreeBSD-src-2cbc12617e8c6974b4bda15456acae526d368800.zip FreeBSD-src-2cbc12617e8c6974b4bda15456acae526d368800.tar.gz |
For nmount(), allow a text string error message to be propagated back
to user-space if a parameter named "errmsg" is passed into the iovec.
Used in conjunction with vfs_mount_error(), more useful error messages
than errno can be passed back to userspace when mounting a filesystem
fails.
Discussed with: phk, pjd
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/vfs_mount.c | 39 |
1 files changed, 37 insertions, 2 deletions
diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c index 508fd7b..449231f 100644 --- a/sys/kern/vfs_mount.c +++ b/sys/kern/vfs_mount.c @@ -390,6 +390,18 @@ nmount(td, uap) iov++; } error = vfs_donmount(td, uap->flags, auio); + + /* copyout the errmsg */ + for (i = 0; (error != 0) && (i < iovcnt); i += 2) { + const char *name = (const char *)auio->uio_iov[i].iov_base; + if (!strcmp(name, "errmsg")) { + copyout(auio->uio_iov[i+1].iov_base, + uap->iovp[i+1].iov_base, uap->iovp[i+1].iov_len); + + break; + } + } + free(auio, M_IOV); return (error); } @@ -464,8 +476,15 @@ static int vfs_donmount(struct thread *td, int fsflags, struct uio *fsoptions) { struct vfsoptlist *optlist; + struct iovec *iov_errmsg = NULL; char *fstype, *fspath; int error, fstypelen, fspathlen; + int i; + + for (i = 0; i < fsoptions->uio_iovcnt; i += 2) { + if (!strcmp((char *)fsoptions->uio_iov[i].iov_base, "errmsg")) + iov_errmsg = &fsoptions->uio_iov[i+1]; + } error = vfs_buildopts(fsoptions, &optlist); if (error) @@ -480,12 +499,18 @@ vfs_donmount(struct thread *td, int fsflags, struct uio *fsoptions) error = vfs_getopt(optlist, "fstype", (void **)&fstype, &fstypelen); if (error || fstype[fstypelen - 1] != '\0') { error = EINVAL; + if (iov_errmsg) + strncpy((char *)iov_errmsg->iov_base, "Invalid fstype", + iov_errmsg->iov_len); goto bail; } fspathlen = 0; error = vfs_getopt(optlist, "fspath", (void **)&fspath, &fspathlen); if (error || fspath[fspathlen - 1] != '\0') { error = EINVAL; + if (iov_errmsg != NULL) + strncpy((char *)iov_errmsg->iov_base, "Invalid fspath", + iov_errmsg->iov_len); goto bail; } @@ -503,6 +528,17 @@ vfs_donmount(struct thread *td, int fsflags, struct uio *fsoptions) error = vfs_domount(td, fstype, fspath, fsflags, optlist); mtx_unlock(&Giant); bail: + if (error && iov_errmsg != NULL) { + /* save the errmsg */ + char *errmsg; + int len, ret; + ret = vfs_getopt(optlist, "errmsg", (void **)&errmsg, &len); + if(ret == 0 && len > 0) + strncpy((char *)iov_errmsg->iov_base, errmsg, + iov_errmsg->iov_len); + + } + if (error) vfs_freeopts(optlist); return (error); @@ -1195,9 +1231,8 @@ vfs_mount_error(struct mount *mp, const char *fmt, ...) char *errmsg; error = vfs_getopt(moptlist, "errmsg", (void **)&errmsg, &len); - if (error || errmsg == NULL || len <= 0) { + if (error || errmsg == NULL || len <= 0) return; - } va_start(ap, fmt); vsnprintf(errmsg, (size_t)len, fmt, ap); |