On Tue, May 28, 2019 at 04:31:15PM -0400, Trond Myklebust wrote: > +char * > +nfsd_path_strip_root(char *pathname) > +{ > + const char *dir = nfsd_path_nfsd_rootdir(); > + char *ret; > + > + ret = strstr(pathname, dir); > + if (!ret || ret != pathname) > + return pathname; Shouldn't we return NULL or an error or something here? It seems a little strange not to care if the path began with root or not. I guess I need to look at the caller.... --b. > + return pathname + strlen(dir); > +} > + > +char * > +nfsd_path_prepend_dir(const char *dir, const char *pathname) > +{ > + size_t len, dirlen; > + char *ret; > + > + dirlen = strlen(dir); > + while (dirlen > 0 && dir[dirlen - 1] == '/') > + dirlen--; > + if (!dirlen) > + return NULL; > + len = dirlen + strlen(pathname) + 1; > + ret = xmalloc(len + 1); > + snprintf(ret, len, "%.*s/%s", (int)dirlen, dir, pathname); > + return ret; > +} > + > +static void > +nfsd_setup_workqueue(void) > +{ > + const char *rootdir = nfsd_path_nfsd_rootdir(); > + > + if (!rootdir) > + return; > + nfsd_wq = xthread_workqueue_alloc(); > + if (!nfsd_wq) > + return; > + xthread_workqueue_chroot(nfsd_wq, rootdir); > +} > + > +void > +nfsd_path_init(void) > +{ > + nfsd_setup_workqueue(); > +} > + > +struct nfsd_stat_data { > + const char *pathname; > + struct stat *statbuf; > + int ret; > + int err; > +}; > + > +static void > +nfsd_statfunc(void *data) > +{ > + struct nfsd_stat_data *d = data; > + > + d->ret = xstat(d->pathname, d->statbuf); > + if (d->ret < 0) > + d->err = errno; > +} > + > +static void > +nfsd_lstatfunc(void *data) > +{ > + struct nfsd_stat_data *d = data; > + > + d->ret = xlstat(d->pathname, d->statbuf); > + if (d->ret < 0) > + d->err = errno; > +} > + > +static int > +nfsd_run_stat(struct xthread_workqueue *wq, > + void (*func)(void *), > + const char *pathname, > + struct stat *statbuf) > +{ > + struct nfsd_stat_data data = { > + pathname, > + statbuf, > + 0, > + 0 > + }; > + xthread_work_run_sync(wq, func, &data); > + if (data.ret < 0) > + errno = data.err; > + return data.ret; > +} > + > +int > +nfsd_path_stat(const char *pathname, struct stat *statbuf) > +{ > + if (!nfsd_wq) > + return xstat(pathname, statbuf); > + return nfsd_run_stat(nfsd_wq, nfsd_statfunc, pathname, statbuf); > +} > + > +int > +nfsd_path_lstat(const char *pathname, struct stat *statbuf) > +{ > + if (!nfsd_wq) > + return xlstat(pathname, statbuf); > + return nfsd_run_stat(nfsd_wq, nfsd_lstatfunc, pathname, statbuf); > +} > diff --git a/support/misc/xstat.c b/support/misc/xstat.c > new file mode 100644 > index 000000000000..d092f73dfd65 > --- /dev/null > +++ b/support/misc/xstat.c > @@ -0,0 +1,33 @@ > +#include <sys/types.h> > +#include <fcntl.h> > +#include <sys/stat.h> > +#include <unistd.h> > + > +#include "config.h" > +#include "xstat.h" > + > +#ifdef HAVE_FSTATAT > + > +int xlstat(const char *pathname, struct stat *statbuf) > +{ > + return fstatat(AT_FDCWD, pathname, statbuf, AT_NO_AUTOMOUNT | > + AT_SYMLINK_NOFOLLOW); > +} > + > +int xstat(const char *pathname, struct stat *statbuf) > +{ > + return fstatat(AT_FDCWD, pathname, statbuf, AT_NO_AUTOMOUNT); > +} > + > +#else > + > +int xlstat(const char *pathname, struct stat *statbuf) > +{ > + return lstat(pathname, statbuf); > +} > + > +int xstat(const char *pathname, struct stat *statbuf) > +{ > + return stat(pathname, statbuf); > +} > +#endif > -- > 2.21.0