On Wed, Oct 19, 2011 at 04:42:57PM +0200, Michal Privoznik wrote: > This function checks if a given path is accessible under > given uid and gid. > --- > src/util/util.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ > src/util/util.h | 3 ++ > 2 files changed, 79 insertions(+), 0 deletions(-) > > diff --git a/src/util/util.c b/src/util/util.c > index dac616b..09d6281 100644 > --- a/src/util/util.c > +++ b/src/util/util.c > @@ -671,6 +671,70 @@ virFileIsExecutable(const char *file) > } > > #ifndef WIN32 > +/* Check that a file is accessible under certain > + * user & gid. > + * @mode can be R_OK, W_OK, X_OK or F_OK. > + * see 'man accesss' for more details. > + * Returns 0 on success, -errno on fail, > + * >0 on signaled child. > + */ > +int > +virFileAccessibleAs(const char *path, int mode, > + uid_t uid, gid_t gid) > +{ > + pid_t pid; > + int waitret, status, ret = 0; > + int forkRet; > + > + forkRet = virFork(&pid); > + > + if (pid < 0) { > + return -errno; > + } virFork() already raises a proper libvirt error on failure, so returning 'errno' too is a little misleading / redundant. Just return '-1' on error here & throughout the function > + > + if (pid) { /* parent */ > + do { > + if ((waitret = waitpid(pid, &status, 0)) < 0) { > + ret = -errno; > + virKillProcess(pid, SIGKILL); > + return ret; > + } > + } while (!WIFEXITED(status) && !WIFSIGNALED(status)); > + > + /* child actually returns positive value > + * anded by 0xFF (see man waitpid @ WEXITSTATUS) > + */ > + > + if (WIFSIGNALED(status)) > + return WTERMSIG(status); > + > + return -WEXITSTATUS(status); > + } > + > + /* child */ > + > + if (forkRet < 0) { > + ret = errno; > + goto childerror; > + } > + > + if (virSetUIDGID(uid, gid) < 0) { > + ret = errno; > + goto childerror; > + } > + > + if (access(path, mode) < 0) > + ret = errno; > + > +childerror: > + if ((ret & 0xFF) != ret) { > + VIR_WARN("unable to pass desired return value %d", ret); > + ret = 0xFF; > + } > + > + _exit(ret); > +} > + > /* return -errno on failure, or 0 on success */ > static int > virFileOpenAsNoFork(const char *path, int openflags, mode_t mode, > @@ -993,6 +1057,18 @@ childerror: > > #else /* WIN32 */ > > +int > +virFileAccessibleAs(const char *path ATTRIBUTE_UNUSED, > + int mode ATTRIBUTE_UNUSED, > + uid_t uid ATTRIBUTE_UNUSED, > + git_t gid ATTRIBUTE_UNUSED) > +{ > + virUtilError(VIR_ERR_INTERNAL_ERROR, > + "%s", _("virFileAccessibleAs is not implemented for WIN32")); > + > + return -ENOSYS; > +} Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list