]> xenbits.xensource.com Git - libvirt.git/commitdiff
util: move virFile* functions from virutil.c to virfile.c
authorLaine Stump <laine@laine.org>
Thu, 9 May 2013 18:59:04 +0000 (14:59 -0400)
committerLaine Stump <laine@laine.org>
Fri, 10 May 2013 17:09:30 +0000 (13:09 -0400)
These all existed before virfile.c was created, and for some reason
weren't moved.

This is mostly straightfoward, although the syntax rule prohibiting
write() had to be changed to have an exception for virfile.c instead
of virutil.c.

This movement pointed out that there is a function called
virBuildPath(), and another almost identical function called
virFileBuildPath(). They really should be a single function, which
I'll take care of as soon as I figure out what the arglist should look
like.

42 files changed:
cfg.mk
src/esx/esx_driver.c
src/esx/esx_storage_backend_vmfs.c
src/libvirt.c
src/libvirt_private.syms
src/node_device/node_device_driver.c
src/node_device/node_device_udev.c
src/parallels/parallels_driver.c
src/parallels/parallels_network.c
src/parallels/parallels_storage.c
src/rpc/virnetsshsession.c
src/rpc/virnettlscontext.c
src/security/security_dac.c
src/storage/parthelper.c
src/storage/storage_backend_disk.c
src/util/virebtables.c
src/util/virfile.c
src/util/virfile.h
src/util/virhook.c
src/util/viriptables.c
src/util/virkeyfile.c
src/util/virnetdevveth.c
src/util/virsysinfo.c
src/util/virusb.c
src/util/virutil.c
src/util/virutil.h
src/vbox/vbox_XPCOMCGlue.c
src/vmx/vmx.c
src/xen/xm_internal.c
tests/eventtest.c
tests/libvirtdconftest.c
tests/securityselinuxtest.c
tests/virlockspacetest.c
tests/virportallocatortest.c
tests/virstoragetest.c
tools/virsh-interface.c
tools/virsh-network.c
tools/virsh-nodedev.c
tools/virsh-nwfilter.c
tools/virsh-pool.c
tools/virsh-secret.c
tools/virsh-snapshot.c

diff --git a/cfg.mk b/cfg.mk
index 227c18b60196db8391c60353aa2075ebb4acc64f..0bf5bfc1b629b65cd70a8124c43a3593674a292d 100644 (file)
--- a/cfg.mk
+++ b/cfg.mk
@@ -841,7 +841,7 @@ $(srcdir)/src/remote/remote_client_bodies.h: $(srcdir)/src/remote/remote_protoco
 # List all syntax-check exemptions:
 exclude_file_name_regexp--sc_avoid_strcase = ^tools/virsh\.h$$
 
-_src1=libvirt|fdstream|qemu/qemu_monitor|util/(vircommand|virutil)|xen/xend_internal|rpc/virnetsocket|lxc/lxc_controller|locking/lock_daemon
+_src1=libvirt|fdstream|qemu/qemu_monitor|util/(vircommand|virfile)|xen/xend_internal|rpc/virnetsocket|lxc/lxc_controller|locking/lock_daemon
 _test1=shunloadtest|virnettlscontexttest|vircgroupmock
 exclude_file_name_regexp--sc_avoid_write = \
   ^(src/($(_src1))|daemon/libvirtd|tools/console|tests/($(_test1)))\.c$$
index 6979fbffde336ac54773627ea80b182b85844337..b23e7f6cf2ec96a90d39e5a16a1356ef42898f9b 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * esx_driver.c: core driver functions for managing VMware ESX hosts
  *
- * Copyright (C) 2010-2012 Red Hat, Inc.
+ * Copyright (C) 2010-2013 Red Hat, Inc.
  * Copyright (C) 2009-2013 Matthias Bolte <matthias.bolte@googlemail.com>
  * Copyright (C) 2009 Maximilian Wilhelm <max@rfc2324.org>
  *
@@ -29,6 +29,7 @@
 #include "snapshot_conf.h"
 #include "virauth.h"
 #include "viralloc.h"
+#include "virfile.h"
 #include "virlog.h"
 #include "viruuid.h"
 #include "vmx.h"
@@ -44,8 +45,8 @@
 #include "esx_vi.h"
 #include "esx_vi_methods.h"
 #include "esx_util.h"
-#include "viruri.h"
 #include "virstring.h"
+#include "viruri.h"
 
 #define VIR_FROM_THIS VIR_FROM_ESX
 
index 63974abcf6f7f640e55e870a90c4769894c9ba6c..3b4d73a126e542c3c061aac524c0fb809cade0c5 100644 (file)
@@ -32,6 +32,7 @@
 #include "internal.h"
 #include "md5.h"
 #include "viralloc.h"
+#include "virfile.h"
 #include "virlog.h"
 #include "viruuid.h"
 #include "storage_conf.h"
index ab75110821914fa55066b5bcc2e353c9bbd6d736..2b3515e32c5cc1706b4343f38a5aabf1bf8fa4b6 100644 (file)
@@ -59,6 +59,7 @@
 # include "rpc/virnettlscontext.h"
 #endif
 #include "vircommand.h"
+#include "virfile.h"
 #include "virrandom.h"
 #include "viruri.h"
 #include "virthread.h"
index bb70595e0b4a258f3b567019cac671e80222b3b2..2d7fe5b40f4b2b28648d0da6c5fe1ee954b0ce00 100644 (file)
@@ -1271,18 +1271,51 @@ virEventPollUpdateTimeout;
 
 
 # util/virfile.h
+saferead;
+safewrite;
+safezero;
+virBuildPathInternal;
+virDirCreate;
+virFileAbsPath;
+virFileAccessibleAs;
+virFileBuildPath;
 virFileClose;
 virFileDeleteTree;
 virFileDirectFdFlag;
+virFileExists;
 virFileFclose;
 virFileFdopen;
+virFileFindMountPoint;
+virFileHasSuffix;
+virFileIsAbsPath;
+virFileIsDir;
+virFileIsExecutable;
+virFileIsLink;
+virFileLinkPointsTo;
+virFileLock;
 virFileLoopDeviceAssociate;
+virFileMakePath;
+virFileMakePathWithMode;
+virFileMatchesNameSuffix;
+virFileOpenAs;
+virFileOpenTty;
+virFileReadAll;
+virFileReadLimFD;
+virFileResolveAllLinks;
+virFileResolveLink;
 virFileRewrite;
+virFileSanitizePath;
+virFileSkipRoot;
+virFileStripSuffix;
 virFileTouch;
+virFileUnlock;
 virFileUpdatePerm;
+virFileWaitForDevices;
 virFileWrapperFdClose;
 virFileWrapperFdFree;
 virFileWrapperFdNew;
+virFileWriteStr;
+virFindFileInPath;
 
 
 # util/virhash.h
@@ -1861,44 +1894,11 @@ virUSBDeviceSetUsedBy;
 
 
 # util/virutil.h
-saferead;
-safewrite;
-safezero;
-virBuildPathInternal;
 virCompareLimitUlong;
-virDirCreate;
 virDoubleToStr;
 virEnumFromString;
 virEnumToString;
-virFileAbsPath;
-virFileAccessibleAs;
-virFileBuildPath;
-virFileExists;
-virFileFindMountPoint;
-virFileHasSuffix;
-virFileIsAbsPath;
-virFileIsDir;
-virFileIsExecutable;
-virFileIsLink;
-virFileLinkPointsTo;
-virFileLock;
-virFileMakePath;
-virFileMakePathWithMode;
-virFileMatchesNameSuffix;
-virFileOpenAs;
-virFileOpenTty;
-virFileReadAll;
-virFileReadLimFD;
-virFileResolveAllLinks;
-virFileResolveLink;
-virFileSanitizePath;
-virFileSkipRoot;
-virFileStripSuffix;
-virFileUnlock;
-virFileWaitForDevices;
-virFileWriteStr;
 virFindFCHostCapableVport;
-virFindFileInPath;
 virFormatIntDecimal;
 virGetDeviceID;
 virGetDeviceUnprivSGIO;
index c596901747493d82e006eec946a3cbee705e1755..52586b898a3ecfd8e74fa36b808f8397d6dd68e4 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * node_device.c: node device enumeration
  *
- * Copyright (C) 2010-2011 Red Hat, Inc.
+ * Copyright (C) 2010-2013 Red Hat, Inc.
  * Copyright (C) 2008 Virtual Iron Software, Inc.
  * Copyright (C) 2008 David F. Lively
  *
@@ -32,6 +32,7 @@
 #include "virerror.h"
 #include "datatypes.h"
 #include "viralloc.h"
+#include "virfile.h"
 #include "virlog.h"
 #include "virstring.h"
 #include "node_device_conf.h"
index 7036c8ca02dcff8442ccc95fc948ad48e9f54cbb..4aeaed5a8fa471c94fc139a26f6611cb494d9742 100644 (file)
@@ -37,6 +37,7 @@
 #include "viralloc.h"
 #include "viruuid.h"
 #include "virbuffer.h"
+#include "virfile.h"
 #include "virpci.h"
 #include "virstring.h"
 
index 74a52f0d7adb7f65d92313385a756900d4557a55..b7c4ec4ff3af50909358e921d17434d8f16c2d24 100644 (file)
@@ -45,6 +45,7 @@
 #include "virlog.h"
 #include "vircommand.h"
 #include "configmake.h"
+#include "virfile.h"
 #include "virstoragefile.h"
 #include "nodeinfo.h"
 #include "c-ctype.h"
index 2e5523b0310c1717828fbd842df29cc96e6e0c76..8990609095ba49c2b2ae0cd52486b75c14ec0080 100644 (file)
@@ -27,6 +27,7 @@
 #include "dirname.h"
 #include "viralloc.h"
 #include "virerror.h"
+#include "virfile.h"
 #include "md5.h"
 #include "parallels_utils.h"
 #include "virstring.h"
index 6a02fd6523981bafaa20f38deb244ad6bc76ddf4..3d55e82e058679fd71cb97879f4d7b207497f567 100644 (file)
@@ -36,6 +36,7 @@
 #include "configmake.h"
 #include "virstoragefile.h"
 #include "virerror.h"
+#include "virfile.h"
 #include "parallels_utils.h"
 #include "virstring.h"
 
index 27750fc66bbba69c5f2df45105a6842387dd1212..189d9289aa8ab321b6cb3ba4bb0a21dafb51877c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * virnetsshsession.c: ssh network transport provider based on libssh2
  *
- * Copyright (C) 2012 Red Hat, Inc.
+ * Copyright (C) 2012-2013 Red Hat, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -33,6 +33,7 @@
 #include "virthread.h"
 #include "virutil.h"
 #include "virerror.h"
+#include "virfile.h"
 #include "virobject.h"
 #include "virstring.h"
 
index 7f5975dcffc58fe2154d37710ccf419f3875f32d..1a7ccb8732f23461f81a87225e0ba06a5b6ffc7e 100644 (file)
@@ -33,6 +33,7 @@
 
 #include "viralloc.h"
 #include "virerror.h"
+#include "virfile.h"
 #include "virutil.h"
 #include "virlog.h"
 #include "virthread.h"
index cd214d886063f9fc11d80dd5f851262d6a798985..16cce0ea14750ef7bd188d5ce6714e4cfcbd320a 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "security_dac.h"
 #include "virerror.h"
+#include "virfile.h"
 #include "viralloc.h"
 #include "virlog.h"
 #include "virpci.h"
index 038487ad8acbd6507d0603e21e0623cc24c7815f..c04f1bdd3d53109462fa069de18231f989e49b5b 100644 (file)
@@ -10,7 +10,7 @@
  * in a reliable fashion if merely after a list of partitions & sizes,
  * though it is fine for creating partitions.
  *
- * Copyright (C) 2007-2008, 2010 Red Hat, Inc.
+ * Copyright (C) 2007-2008, 2010, 2013 Red Hat, Inc.
  * Copyright (C) 2007-2008 Daniel P. Berrange
  *
  * This library is free software; you can redistribute it and/or
@@ -42,6 +42,7 @@
 #include <locale.h>
 
 #include "virutil.h"
+#include "virfile.h"
 #include "c-ctype.h"
 #include "configmake.h"
 #include "virstring.h"
index 52bd57265151bf6141bac56e1d19d3a58001ca22..09c2d2c3029a4a3b4b584693486b77337e81e6b0 100644 (file)
@@ -32,6 +32,7 @@
 #include "storage_backend_disk.h"
 #include "viralloc.h"
 #include "vircommand.h"
+#include "virfile.h"
 #include "configmake.h"
 #include "virstring.h"
 
index 6bc6fed3ca88679438f6ddd790e61e80897b6395..3834ea88a29ef927bc7b1d9b994d796e56b521b1 100644 (file)
@@ -46,6 +46,7 @@
 #include "vircommand.h"
 #include "viralloc.h"
 #include "virerror.h"
+#include "virfile.h"
 #include "virlog.h"
 #include "virthread.h"
 #include "virstring.h"
index 25a0501cdf179b1700fc9d5117ce7cad127f1440..1491f27adacaed0c29707433c7386344f784c741 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * virfile.c: safer file handling
  *
- * Copyright (C) 2010-2012 Red Hat, Inc.
+ * Copyright (C) 2010-2013 Red Hat, Inc.
  * Copyright (C) 2010 IBM Corporation
  * Copyright (C) 2010 Stefan Berger
  * Copyright (C) 2010 Eric Blake
 #include <config.h>
 #include "internal.h"
 
-#include "virfile.h"
-
+#include <passfd.h>
 #include <fcntl.h>
+#include <pty.h>
 #include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
 #include <unistd.h>
 #include <dirent.h>
+#include <dirname.h>
+#if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
+# include <mntent.h>
+#endif
+#include <stdlib.h>
 
 #if defined(__linux__) && HAVE_DECL_LO_FLAGS_AUTOCLEAR
 # include <linux/loop.h>
 # include <sys/ioctl.h>
 #endif
 
-#include "vircommand.h"
 #include "configmake.h"
 #include "viralloc.h"
+#include "vircommand.h"
 #include "virerror.h"
+#include "virfile.h"
 #include "virlog.h"
+#include "virprocess.h"
 #include "virstring.h"
+#include "virstoragefile.h"
+#include "virutil.h"
 
 #define VIR_FROM_THIS VIR_FROM_NONE
 
@@ -728,3 +740,1431 @@ cleanup:
     closedir(dh);
     return ret;
 }
+
+int
+virFileStripSuffix(char *str, const char *suffix)
+{
+    int len = strlen(str);
+    int suffixlen = strlen(suffix);
+
+    if (len < suffixlen)
+        return 0;
+
+    if (!STREQ(str + len - suffixlen, suffix))
+        return 0;
+
+    str[len-suffixlen] = '\0';
+
+    return 1;
+}
+
+
+/* Like read(), but restarts after EINTR.  Doesn't play
+ * nicely with nonblocking FD and EAGAIN, in which case
+ * you want to use bare read(). Or even use virSocket()
+ * if the FD is related to a socket rather than a plain
+ * file or pipe. */
+ssize_t
+saferead(int fd, void *buf, size_t count)
+{
+    size_t nread = 0;
+    while (count > 0) {
+        ssize_t r = read(fd, buf, count);
+        if (r < 0 && errno == EINTR)
+            continue;
+        if (r < 0)
+            return r;
+        if (r == 0)
+            return nread;
+        buf = (char *)buf + r;
+        count -= r;
+        nread += r;
+    }
+    return nread;
+}
+
+/* Like write(), but restarts after EINTR. Doesn't play
+ * nicely with nonblocking FD and EAGAIN, in which case
+ * you want to use bare write(). Or even use virSocket()
+ * if the FD is related to a socket rather than a plain
+ * file or pipe. */
+ssize_t
+safewrite(int fd, const void *buf, size_t count)
+{
+    size_t nwritten = 0;
+    while (count > 0) {
+        ssize_t r = write(fd, buf, count);
+
+        if (r < 0 && errno == EINTR)
+            continue;
+        if (r < 0)
+            return r;
+        if (r == 0)
+            return nwritten;
+        buf = (const char *)buf + r;
+        count -= r;
+        nwritten += r;
+    }
+    return nwritten;
+}
+
+#ifdef HAVE_POSIX_FALLOCATE
+int
+safezero(int fd, off_t offset, off_t len)
+{
+    int ret = posix_fallocate(fd, offset, len);
+    if (ret == 0)
+        return 0;
+    errno = ret;
+    return -1;
+}
+#else
+
+# ifdef HAVE_MMAP
+int
+safezero(int fd, off_t offset, off_t len)
+{
+    int r;
+    char *buf;
+
+    /* memset wants the mmap'ed file to be present on disk so create a
+     * sparse file
+     */
+    r = ftruncate(fd, offset + len);
+    if (r < 0)
+        return -1;
+
+    buf = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset);
+    if (buf == MAP_FAILED)
+        return -1;
+
+    memset(buf, 0, len);
+    munmap(buf, len);
+
+    return 0;
+}
+
+# else /* HAVE_MMAP */
+
+int
+safezero(int fd, off_t offset, off_t len)
+{
+    int r;
+    char *buf;
+    unsigned long long remain, bytes;
+
+    if (lseek(fd, offset, SEEK_SET) < 0)
+        return -1;
+
+    /* Split up the write in small chunks so as not to allocate lots of RAM */
+    remain = len;
+    bytes = 1024 * 1024;
+
+    r = VIR_ALLOC_N(buf, bytes);
+    if (r < 0) {
+        errno = ENOMEM;
+        return -1;
+    }
+
+    while (remain) {
+        if (bytes > remain)
+            bytes = remain;
+
+        r = safewrite(fd, buf, bytes);
+        if (r < 0) {
+            VIR_FREE(buf);
+            return -1;
+        }
+
+        /* safewrite() guarantees all data will be written */
+        remain -= bytes;
+    }
+    VIR_FREE(buf);
+    return 0;
+}
+# endif /* HAVE_MMAP */
+#endif /* HAVE_POSIX_FALLOCATE */
+
+
+#if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
+/* search /proc/mounts for mount point of *type; return pointer to
+ * malloc'ed string of the path if found, otherwise return NULL
+ * with errno set to an appropriate value.
+ */
+char *
+virFileFindMountPoint(const char *type)
+{
+    FILE *f;
+    struct mntent mb;
+    char mntbuf[1024];
+    char *ret = NULL;
+
+    f = setmntent("/proc/mounts", "r");
+    if (!f)
+        return NULL;
+
+    while (getmntent_r(f, &mb, mntbuf, sizeof(mntbuf))) {
+        if (STREQ(mb.mnt_type, type)) {
+            ret = strdup(mb.mnt_dir);
+            goto cleanup;
+        }
+    }
+
+    if (!ret)
+        errno = ENOENT;
+
+cleanup:
+    endmntent(f);
+
+    return ret;
+}
+
+#else /* defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R */
+
+char *
+virFileFindMountPoint(const char *type ATTRIBUTE_UNUSED)
+{
+    errno = ENOSYS;
+
+    return NULL;
+}
+
+#endif /* defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R */
+
+int
+virBuildPathInternal(char **path, ...)
+{
+    char *path_component = NULL;
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+    va_list ap;
+    int ret = 0;
+
+    va_start(ap, path);
+
+    path_component = va_arg(ap, char *);
+    virBufferAdd(&buf, path_component, -1);
+
+    while ((path_component = va_arg(ap, char *)) != NULL)
+    {
+        virBufferAddChar(&buf, '/');
+        virBufferAdd(&buf, path_component, -1);
+    }
+
+    va_end(ap);
+
+    *path = virBufferContentAndReset(&buf);
+    if (*path == NULL) {
+        ret = -1;
+    }
+
+    return ret;
+}
+
+/* Like gnulib's fread_file, but read no more than the specified maximum
+   number of bytes.  If the length of the input is <= max_len, and
+   upon error while reading that data, it works just like fread_file.  */
+static char *
+saferead_lim(int fd, size_t max_len, size_t *length)
+{
+    char *buf = NULL;
+    size_t alloc = 0;
+    size_t size = 0;
+    int save_errno;
+
+    for (;;) {
+        int count;
+        int requested;
+
+        if (size + BUFSIZ + 1 > alloc) {
+            alloc += alloc / 2;
+            if (alloc < size + BUFSIZ + 1)
+                alloc = size + BUFSIZ + 1;
+
+            if (VIR_REALLOC_N(buf, alloc) < 0) {
+                save_errno = errno;
+                break;
+            }
+        }
+
+        /* Ensure that (size + requested <= max_len); */
+        requested = MIN(size < max_len ? max_len - size : 0,
+                        alloc - size - 1);
+        count = saferead(fd, buf + size, requested);
+        size += count;
+
+        if (count != requested || requested == 0) {
+            save_errno = errno;
+            if (count < 0)
+                break;
+            buf[size] = '\0';
+            *length = size;
+            return buf;
+        }
+    }
+
+    VIR_FREE(buf);
+    errno = save_errno;
+    return NULL;
+}
+
+/* A wrapper around saferead_lim that maps a failure due to
+   exceeding the maximum size limitation to EOVERFLOW.  */
+int
+virFileReadLimFD(int fd, int maxlen, char **buf)
+{
+    size_t len;
+    char *s;
+
+    if (maxlen <= 0) {
+        errno = EINVAL;
+        return -1;
+    }
+    s = saferead_lim(fd, maxlen+1, &len);
+    if (s == NULL)
+        return -1;
+    if (len > maxlen || (int)len != len) {
+        VIR_FREE(s);
+        /* There was at least one byte more than MAXLEN.
+           Set errno accordingly. */
+        errno = EOVERFLOW;
+        return -1;
+    }
+    *buf = s;
+    return len;
+}
+
+int
+virFileReadAll(const char *path, int maxlen, char **buf)
+{
+    int fd = open(path, O_RDONLY);
+    if (fd < 0) {
+        virReportSystemError(errno, _("Failed to open file '%s'"), path);
+        return -1;
+    }
+
+    int len = virFileReadLimFD(fd, maxlen, buf);
+    VIR_FORCE_CLOSE(fd);
+    if (len < 0) {
+        virReportSystemError(errno, _("Failed to read file '%s'"), path);
+        return -1;
+    }
+
+    return len;
+}
+
+/* Truncate @path and write @str to it.  If @mode is 0, ensure that
+   @path exists; otherwise, use @mode if @path must be created.
+   Return 0 for success, nonzero for failure.
+   Be careful to preserve any errno value upon failure. */
+int
+virFileWriteStr(const char *path, const char *str, mode_t mode)
+{
+    int fd;
+
+    if (mode)
+        fd = open(path, O_WRONLY|O_TRUNC|O_CREAT, mode);
+    else
+        fd = open(path, O_WRONLY|O_TRUNC);
+    if (fd == -1)
+        return -1;
+
+    if (safewrite(fd, str, strlen(str)) < 0) {
+        VIR_FORCE_CLOSE(fd);
+        return -1;
+    }
+
+    /* Use errno from failed close only if there was no write error.  */
+    if (VIR_CLOSE(fd) != 0)
+        return -1;
+
+    return 0;
+}
+
+int
+virFileMatchesNameSuffix(const char *file,
+                         const char *name,
+                         const char *suffix)
+{
+    int filelen = strlen(file);
+    int namelen = strlen(name);
+    int suffixlen = strlen(suffix);
+
+    if (filelen == (namelen + suffixlen) &&
+        STREQLEN(file, name, namelen) &&
+        STREQLEN(file + namelen, suffix, suffixlen))
+        return 1;
+    else
+        return 0;
+}
+
+int
+virFileHasSuffix(const char *str,
+                 const char *suffix)
+{
+    int len = strlen(str);
+    int suffixlen = strlen(suffix);
+
+    if (len < suffixlen)
+        return 0;
+
+    return STRCASEEQ(str + len - suffixlen, suffix);
+}
+
+#define SAME_INODE(Stat_buf_1, Stat_buf_2) \
+  ((Stat_buf_1).st_ino == (Stat_buf_2).st_ino \
+   && (Stat_buf_1).st_dev == (Stat_buf_2).st_dev)
+
+/* Return nonzero if checkLink and checkDest
+   refer to the same file.  Otherwise, return 0.  */
+int
+virFileLinkPointsTo(const char *checkLink,
+                    const char *checkDest)
+{
+    struct stat src_sb;
+    struct stat dest_sb;
+
+    return (stat(checkLink, &src_sb) == 0
+            && stat(checkDest, &dest_sb) == 0
+            && SAME_INODE(src_sb, dest_sb));
+}
+
+
+static int
+virFileResolveLinkHelper(const char *linkpath,
+                         bool intermediatePaths,
+                         char **resultpath)
+{
+    struct stat st;
+
+    *resultpath = NULL;
+
+    /* We don't need the full canonicalization of intermediate
+     * directories, if linkpath is absolute and the basename is
+     * already a non-symlink.  */
+    if (IS_ABSOLUTE_FILE_NAME(linkpath) && !intermediatePaths) {
+        if (lstat(linkpath, &st) < 0)
+            return -1;
+
+        if (!S_ISLNK(st.st_mode)) {
+            if (!(*resultpath = strdup(linkpath)))
+                return -1;
+            return 0;
+        }
+    }
+
+    *resultpath = canonicalize_file_name(linkpath);
+
+    return *resultpath == NULL ? -1 : 0;
+}
+
+/*
+ * Attempt to resolve a symbolic link, returning an
+ * absolute path where only the last component is guaranteed
+ * not to be a symlink.
+ *
+ * Return 0 if path was not a symbolic, or the link was
+ * resolved. Return -1 with errno set upon error
+ */
+int
+virFileResolveLink(const char *linkpath, char **resultpath)
+{
+    return virFileResolveLinkHelper(linkpath, false, resultpath);
+}
+
+/*
+ * Attempt to resolve a symbolic link, returning an
+ * absolute path where every component is guaranteed
+ * not to be a symlink.
+ *
+ * Return 0 if path was not a symbolic, or the link was
+ * resolved. Return -1 with errno set upon error
+ */
+int
+virFileResolveAllLinks(const char *linkpath, char **resultpath)
+{
+    return virFileResolveLinkHelper(linkpath, true, resultpath);
+}
+
+/*
+ * Check whether the given file is a link.
+ * Returns 1 in case of the file being a link, 0 in case it is not
+ * a link and the negative errno in all other cases.
+ */
+int
+virFileIsLink(const char *linkpath)
+{
+    struct stat st;
+
+    if (lstat(linkpath, &st) < 0)
+        return -errno;
+
+    return S_ISLNK(st.st_mode) != 0;
+}
+
+
+/*
+ * Finds a requested executable file in the PATH env. e.g.:
+ * "kvm-img" will return "/usr/bin/kvm-img"
+ *
+ * You must free the result
+ */
+char *
+virFindFileInPath(const char *file)
+{
+    char *path = NULL;
+    char *pathiter;
+    char *pathseg;
+    char *fullpath = NULL;
+
+    if (file == NULL)
+        return NULL;
+
+    /* if we are passed an absolute path (starting with /), return a
+     * copy of that path, after validating that it is executable
+     */
+    if (IS_ABSOLUTE_FILE_NAME(file)) {
+        if (virFileIsExecutable(file))
+            return strdup(file);
+        else
+            return NULL;
+    }
+
+    /* If we are passed an anchored path (containing a /), then there
+     * is no path search - it must exist in the current directory
+     */
+    if (strchr(file, '/')) {
+        if (virFileIsExecutable(file))
+            ignore_value(virFileAbsPath(file, &path));
+        return path;
+    }
+
+    /* copy PATH env so we can tweak it */
+    path = getenv("PATH");
+
+    if (path == NULL || (path = strdup(path)) == NULL)
+        return NULL;
+
+    /* for each path segment, append the file to search for and test for
+     * it. return it if found.
+     */
+    pathiter = path;
+    while ((pathseg = strsep(&pathiter, ":")) != NULL) {
+        if (virAsprintf(&fullpath, "%s/%s", pathseg, file) < 0 ||
+            virFileIsExecutable(fullpath))
+            break;
+        VIR_FREE(fullpath);
+    }
+
+    VIR_FREE(path);
+    return fullpath;
+}
+
+bool
+virFileIsDir(const char *path)
+{
+    struct stat s;
+    return (stat(path, &s) == 0) && S_ISDIR(s.st_mode);
+}
+
+bool
+virFileExists(const char *path)
+{
+    return access(path, F_OK) == 0;
+}
+
+/* Check that a file is regular and has executable bits.  If false is
+ * returned, errno is valid.
+ *
+ * Note: In the presence of ACLs, this may return true for a file that
+ * would actually fail with EACCES for a given user, or false for a
+ * file that the user could actually execute, but setups with ACLs
+ * that weird are unusual. */
+bool
+virFileIsExecutable(const char *file)
+{
+    struct stat sb;
+
+    /* We would also want to check faccessat if we cared about ACLs,
+     * but we don't.  */
+    if (stat(file, &sb) < 0)
+        return false;
+    if (S_ISREG(sb.st_mode) && (sb.st_mode & 0111) != 0)
+        return true;
+    errno = S_ISDIR(sb.st_mode) ? EISDIR : EACCES;
+    return false;
+}
+
+#ifndef WIN32
+/* Check that a file is accessible under certain
+ * user & gid.
+ * @mode can be F_OK, or a bitwise combination of R_OK, W_OK, and X_OK.
+ * see 'man access' for more details.
+ * Returns 0 on success, -1 on fail with errno set.
+ */
+int
+virFileAccessibleAs(const char *path, int mode,
+                    uid_t uid, gid_t gid)
+{
+    pid_t pid = 0;
+    int status, ret = 0;
+    int forkRet = 0;
+
+    if (uid == getuid() &&
+        gid == getgid())
+        return access(path, mode);
+
+    forkRet = virFork(&pid);
+
+    if (pid < 0) {
+        return -1;
+    }
+
+    if (pid) { /* parent */
+        if (virProcessWait(pid, &status) < 0) {
+            /* virProcessWait() already
+             * reported error */
+            return -1;
+        }
+
+        if (!WIFEXITED(status)) {
+            errno = EINTR;
+            return -1;
+        }
+
+        if (status) {
+            errno = WEXITSTATUS(status);
+            return -1;
+        }
+
+        return 0;
+    }
+
+    /* child.
+     * Return positive value here. Parent
+     * will change it to negative one. */
+
+    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);
+}
+
+/* virFileOpenForceOwnerMode() - an internal utility function called
+ * only by virFileOpenAs().  Sets the owner and mode of the file
+ * opened as "fd" if it's not correct AND the flags say it should be
+ * forced. */
+static int
+virFileOpenForceOwnerMode(const char *path, int fd, mode_t mode,
+                          uid_t uid, gid_t gid, unsigned int flags)
+{
+    int ret = 0;
+    struct stat st;
+
+    if (!(flags & (VIR_FILE_OPEN_FORCE_OWNER | VIR_FILE_OPEN_FORCE_MODE)))
+        return 0;
+
+    if (fstat(fd, &st) == -1) {
+        ret = -errno;
+        virReportSystemError(errno, _("stat of '%s' failed"), path);
+        return ret;
+    }
+    /* NB: uid:gid are never "-1" (default) at this point - the caller
+     * has always changed -1 to the value of get[gu]id().
+    */
+    if ((flags & VIR_FILE_OPEN_FORCE_OWNER) &&
+        ((st.st_uid != uid) || (st.st_gid != gid)) &&
+        (fchown(fd, uid, gid) < 0)) {
+        ret = -errno;
+        virReportSystemError(errno,
+                             _("cannot chown '%s' to (%u, %u)"),
+                             path, (unsigned int) uid,
+                             (unsigned int) gid);
+        return ret;
+    }
+    if ((flags & VIR_FILE_OPEN_FORCE_MODE) &&
+        ((mode & (S_IRWXU|S_IRWXG|S_IRWXO)) !=
+         (st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO))) &&
+        (fchmod(fd, mode) < 0)) {
+        ret = -errno;
+        virReportSystemError(errno,
+                             _("cannot set mode of '%s' to %04o"),
+                             path, mode);
+        return ret;
+    }
+    return ret;
+}
+
+/* virFileOpenForked() - an internal utility function called only by
+ * virFileOpenAs(). It forks, then the child does setuid+setgid to
+ * given uid:gid and attempts to open the file, while the parent just
+ * calls recvfd to get the open fd back from the child. returns the
+ * fd, or -errno if there is an error. */
+static int
+virFileOpenForked(const char *path, int openflags, mode_t mode,
+                  uid_t uid, gid_t gid, unsigned int flags)
+{
+    pid_t pid;
+    int waitret, status, ret = 0;
+    int fd = -1;
+    int pair[2] = { -1, -1 };
+    int forkRet;
+
+    /* parent is running as root, but caller requested that the
+     * file be opened as some other user and/or group). The
+     * following dance avoids problems caused by root-squashing
+     * NFS servers. */
+
+    if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) < 0) {
+        ret = -errno;
+        virReportSystemError(errno,
+                             _("failed to create socket needed for '%s'"),
+                             path);
+        return ret;
+    }
+
+    forkRet = virFork(&pid);
+    if (pid < 0)
+        return -errno;
+
+    if (pid == 0) {
+
+        /* child */
+
+        VIR_FORCE_CLOSE(pair[0]); /* preserves errno */
+        if (forkRet < 0) {
+            /* error encountered and logged in virFork() after the fork. */
+            ret = -errno;
+            goto childerror;
+        }
+
+        /* set desired uid/gid, then attempt to create the file */
+
+        if (virSetUIDGID(uid, gid) < 0) {
+            ret = -errno;
+            goto childerror;
+        }
+
+        if ((fd = open(path, openflags, mode)) < 0) {
+            ret = -errno;
+            virReportSystemError(errno,
+                                 _("child process failed to create file '%s'"),
+                                 path);
+            goto childerror;
+        }
+
+        /* File is successfully open. Set permissions if requested. */
+        ret = virFileOpenForceOwnerMode(path, fd, mode, uid, gid, flags);
+        if (ret < 0)
+            goto childerror;
+
+        do {
+            ret = sendfd(pair[1], fd);
+        } while (ret < 0 && errno == EINTR);
+
+        if (ret < 0) {
+            ret = -errno;
+            virReportSystemError(errno, "%s",
+                                 _("child process failed to send fd to parent"));
+            goto childerror;
+        }
+
+    childerror:
+        /* ret tracks -errno on failure, but exit value must be positive.
+         * If the child exits with EACCES, then the parent tries again.  */
+        /* XXX This makes assumptions about errno being < 255, which is
+         * not true on Hurd.  */
+        VIR_FORCE_CLOSE(pair[1]);
+        if (ret < 0) {
+            VIR_FORCE_CLOSE(fd);
+        }
+        ret = -ret;
+        if ((ret & 0xff) != ret) {
+            VIR_WARN("unable to pass desired return value %d", ret);
+            ret = 0xff;
+        }
+        _exit(ret);
+    }
+
+    /* parent */
+
+    VIR_FORCE_CLOSE(pair[1]);
+
+    do {
+        fd = recvfd(pair[0], 0);
+    } while (fd < 0 && errno == EINTR);
+    VIR_FORCE_CLOSE(pair[0]); /* NB: this preserves errno */
+
+    if (fd < 0 && errno != EACCES) {
+        ret = -errno;
+        while (waitpid(pid, NULL, 0) == -1 && errno == EINTR);
+        return ret;
+    }
+
+    /* wait for child to complete, and retrieve its exit code */
+    while ((waitret = waitpid(pid, &status, 0) == -1)
+           && (errno == EINTR));
+    if (waitret == -1) {
+        ret = -errno;
+        virReportSystemError(errno,
+                             _("failed to wait for child creating '%s'"),
+                             path);
+        VIR_FORCE_CLOSE(fd);
+        return ret;
+    }
+    if (!WIFEXITED(status) || (ret = -WEXITSTATUS(status)) == -EACCES ||
+        fd == -1) {
+        /* fall back to the simpler method, which works better in
+         * some cases */
+        VIR_FORCE_CLOSE(fd);
+        if (flags & VIR_FILE_OPEN_NOFORK) {
+            /* If we had already tried opening w/o fork+setuid and
+             * failed, no sense trying again. Just set return the
+             * original errno that we got at that time (by
+             * definition, always either EACCES or EPERM - EACCES
+             * is close enough).
+             */
+            return -EACCES;
+        }
+        if ((fd = open(path, openflags, mode)) < 0)
+            return -errno;
+        ret = virFileOpenForceOwnerMode(path, fd, mode, uid, gid, flags);
+        if (ret < 0) {
+            VIR_FORCE_CLOSE(fd);
+            return ret;
+        }
+    }
+    return fd;
+}
+
+/**
+ * virFileOpenAs:
+ * @path: file to open or create
+ * @openflags: flags to pass to open
+ * @mode: mode to use on creation or when forcing permissions
+ * @uid: uid that should own file on creation
+ * @gid: gid that should own file
+ * @flags: bit-wise or of VIR_FILE_OPEN_* flags
+ *
+ * Open @path, and return an fd to the open file. @openflags contains
+ * the flags normally passed to open(2), while those in @flags are
+ * used internally. If @flags includes VIR_FILE_OPEN_NOFORK, then try
+ * opening the file while executing with the current uid:gid
+ * (i.e. don't fork+setuid+setgid before the call to open()).  If
+ * @flags includes VIR_FILE_OPEN_FORK, then try opening the file while
+ * the effective user id is @uid (by forking a child process); this
+ * allows one to bypass root-squashing NFS issues; NOFORK is always
+ * tried before FORK (the absence of both flags is treated identically
+ * to (VIR_FILE_OPEN_NOFORK | VIR_FILE_OPEN_FORK)). If @flags includes
+ * VIR_FILE_OPEN_FORCE_OWNER, then ensure that @path is owned by
+ * uid:gid before returning (even if it already existed with a
+ * different owner). If @flags includes VIR_FILE_OPEN_FORCE_MODE,
+ * ensure it has those permissions before returning (again, even if
+ * the file already existed with different permissions).
+ *
+ * The return value (if non-negative) is the file descriptor, left
+ * open.  Returns -errno on failure.
+ */
+int
+virFileOpenAs(const char *path, int openflags, mode_t mode,
+              uid_t uid, gid_t gid, unsigned int flags)
+{
+    int ret = 0, fd = -1;
+
+    /* allow using -1 to mean "current value" */
+    if (uid == (uid_t) -1)
+        uid = getuid();
+    if (gid == (gid_t) -1)
+        gid = getgid();
+
+    /* treat absence of both flags as presence of both for simpler
+     * calling. */
+    if (!(flags & (VIR_FILE_OPEN_NOFORK|VIR_FILE_OPEN_FORK)))
+        flags |= VIR_FILE_OPEN_NOFORK|VIR_FILE_OPEN_FORK;
+
+    if ((flags & VIR_FILE_OPEN_NOFORK)
+        || (getuid() != 0)
+        || ((uid == 0) && (gid == 0))) {
+
+        if ((fd = open(path, openflags, mode)) < 0) {
+            ret = -errno;
+            if (!(flags & VIR_FILE_OPEN_FORK))
+                goto error;
+        } else {
+            ret = virFileOpenForceOwnerMode(path, fd, mode, uid, gid, flags);
+            if (ret < 0)
+                goto error;
+        }
+    }
+
+    /* If we either 1) didn't try opening as current user at all, or
+     * 2) failed, and errno/virStorageFileIsSharedFS indicate we might
+     * be successful if we try as a different uid, then try doing
+     * fork+setuid+setgid before opening.
+     */
+    if ((fd < 0) && (flags & VIR_FILE_OPEN_FORK)) {
+
+        if (ret < 0) {
+            /* An open(2) that failed due to insufficient permissions
+             * could return one or the other of these depending on OS
+             * version and circumstances. Any other errno indicates a
+             * problem that couldn't be remedied by fork+setuid
+             * anyway. */
+            if (ret != -EACCES && ret != -EPERM)
+                goto error;
+
+            /* On Linux we can also verify the FS-type of the
+             * directory.  (this is a NOP on other platforms). */
+            if (virStorageFileIsSharedFS(path) <= 0)
+                goto error;
+        }
+
+        /* passed all prerequisites - retry the open w/fork+setuid */
+        if ((fd = virFileOpenForked(path, openflags, mode, uid, gid, flags)) < 0) {
+            ret = fd;
+            goto error;
+        }
+    }
+
+    /* File is successfully opened */
+    return fd;
+
+error:
+    if (fd >= 0) {
+        /* some other failure after the open succeeded */
+        VIR_FORCE_CLOSE(fd);
+    }
+    /* whoever failed the open last has already set ret = -errno */
+    return ret;
+}
+
+/* return -errno on failure, or 0 on success */
+static int
+virDirCreateNoFork(const char *path,
+                   mode_t mode, uid_t uid, gid_t gid,
+                   unsigned int flags)
+{
+    int ret = 0;
+    struct stat st;
+
+    if ((mkdir(path, mode) < 0)
+        && !((errno == EEXIST) && (flags & VIR_DIR_CREATE_ALLOW_EXIST))) {
+        ret = -errno;
+        virReportSystemError(errno, _("failed to create directory '%s'"),
+                             path);
+        goto error;
+    }
+
+    if (stat(path, &st) == -1) {
+        ret = -errno;
+        virReportSystemError(errno, _("stat of '%s' failed"), path);
+        goto error;
+    }
+    if (((st.st_uid != uid) || (st.st_gid != gid))
+        && (chown(path, uid, gid) < 0)) {
+        ret = -errno;
+        virReportSystemError(errno, _("cannot chown '%s' to (%u, %u)"),
+                             path, (unsigned int) uid, (unsigned int) gid);
+        goto error;
+    }
+    if ((flags & VIR_DIR_CREATE_FORCE_PERMS)
+        && (chmod(path, mode) < 0)) {
+        ret = -errno;
+        virReportSystemError(errno,
+                             _("cannot set mode of '%s' to %04o"),
+                             path, mode);
+        goto error;
+    }
+error:
+    return ret;
+}
+
+/* return -errno on failure, or 0 on success */
+int
+virDirCreate(const char *path,
+             mode_t mode, uid_t uid, gid_t gid,
+             unsigned int flags)
+{
+    struct stat st;
+    pid_t pid;
+    int waitret;
+    int status, ret = 0;
+
+    /* allow using -1 to mean "current value" */
+    if (uid == (uid_t) -1)
+        uid = getuid();
+    if (gid == (gid_t) -1)
+        gid = getgid();
+
+    if ((!(flags & VIR_DIR_CREATE_AS_UID))
+        || (getuid() != 0)
+        || ((uid == 0) && (gid == 0))
+        || ((flags & VIR_DIR_CREATE_ALLOW_EXIST) && (stat(path, &st) >= 0))) {
+        return virDirCreateNoFork(path, mode, uid, gid, flags);
+    }
+
+    int forkRet = virFork(&pid);
+
+    if (pid < 0) {
+        ret = -errno;
+        return ret;
+    }
+
+    if (pid) { /* parent */
+        /* wait for child to complete, and retrieve its exit code */
+        while ((waitret = waitpid(pid, &status, 0) == -1)  && (errno == EINTR));
+        if (waitret == -1) {
+            ret = -errno;
+            virReportSystemError(errno,
+                                 _("failed to wait for child creating '%s'"),
+                                 path);
+            goto parenterror;
+        }
+        if (!WIFEXITED(status) || (ret = -WEXITSTATUS(status)) == -EACCES) {
+            /* fall back to the simpler method, which works better in
+             * some cases */
+            return virDirCreateNoFork(path, mode, uid, gid, flags);
+        }
+parenterror:
+        return ret;
+    }
+
+    /* child */
+
+    if (forkRet < 0) {
+        /* error encountered and logged in virFork() after the fork. */
+        goto childerror;
+    }
+
+    /* set desired uid/gid, then attempt to create the directory */
+
+    if (virSetUIDGID(uid, gid) < 0) {
+        ret = -errno;
+        goto childerror;
+    }
+    if (mkdir(path, mode) < 0) {
+        ret = -errno;
+        if (ret != -EACCES) {
+            /* in case of EACCES, the parent will retry */
+            virReportSystemError(errno, _("child failed to create directory '%s'"),
+                                 path);
+        }
+        goto childerror;
+    }
+    /* check if group was set properly by creating after
+     * setgid. If not, try doing it with chown */
+    if (stat(path, &st) == -1) {
+        ret = -errno;
+        virReportSystemError(errno,
+                             _("stat of '%s' failed"), path);
+        goto childerror;
+    }
+    if ((st.st_gid != gid) && (chown(path, (uid_t) -1, gid) < 0)) {
+        ret = -errno;
+        virReportSystemError(errno,
+                             _("cannot chown '%s' to group %u"),
+                             path, (unsigned int) gid);
+        goto childerror;
+    }
+    if ((flags & VIR_DIR_CREATE_FORCE_PERMS)
+        && chmod(path, mode) < 0) {
+        virReportSystemError(errno,
+                             _("cannot set mode of '%s' to %04o"),
+                             path, mode);
+        goto childerror;
+    }
+childerror:
+    _exit(ret);
+}
+
+#else /* WIN32 */
+
+int
+virFileAccessibleAs(const char *path,
+                    int mode,
+                    uid_t uid ATTRIBUTE_UNUSED,
+                    gid_t gid ATTRIBUTE_UNUSED)
+{
+
+    VIR_WARN("Ignoring uid/gid due to WIN32");
+
+    return access(path, mode);
+}
+
+/* return -errno on failure, or 0 on success */
+int
+virFileOpenAs(const char *path ATTRIBUTE_UNUSED,
+              int openflags ATTRIBUTE_UNUSED,
+              mode_t mode ATTRIBUTE_UNUSED,
+              uid_t uid ATTRIBUTE_UNUSED,
+              gid_t gid ATTRIBUTE_UNUSED,
+              unsigned int flags_unused ATTRIBUTE_UNUSED)
+{
+    virReportError(VIR_ERR_INTERNAL_ERROR,
+                   "%s", _("virFileOpenAs is not implemented for WIN32"));
+
+    return -ENOSYS;
+}
+
+int
+virDirCreate(const char *path ATTRIBUTE_UNUSED,
+             mode_t mode ATTRIBUTE_UNUSED,
+             uid_t uid ATTRIBUTE_UNUSED,
+             gid_t gid ATTRIBUTE_UNUSED,
+             unsigned int flags_unused ATTRIBUTE_UNUSED)
+{
+    virReportError(VIR_ERR_INTERNAL_ERROR,
+                   "%s", _("virDirCreate is not implemented for WIN32"));
+
+    return -ENOSYS;
+}
+#endif /* WIN32 */
+
+static int
+virFileMakePathHelper(char *path, mode_t mode)
+{
+    struct stat st;
+    char *p;
+
+    VIR_DEBUG("path=%s mode=0%o", path, mode);
+
+    if (stat(path, &st) >= 0) {
+        if (S_ISDIR(st.st_mode))
+            return 0;
+
+        errno = ENOTDIR;
+        return -1;
+    }
+
+    if (errno != ENOENT)
+        return -1;
+
+    if ((p = strrchr(path, '/')) == NULL) {
+        errno = EINVAL;
+        return -1;
+    }
+
+    if (p != path) {
+        *p = '\0';
+
+        if (virFileMakePathHelper(path, mode) < 0)
+            return -1;
+
+        *p = '/';
+    }
+
+    if (mkdir(path, mode) < 0 && errno != EEXIST)
+        return -1;
+
+    return 0;
+}
+
+/**
+ * Creates the given directory with mode 0777 if it's not already existing.
+ *
+ * Returns 0 on success, or -1 if an error occurred (in which case, errno
+ * is set appropriately).
+ */
+int
+virFileMakePath(const char *path)
+{
+    return virFileMakePathWithMode(path, 0777);
+}
+
+int
+virFileMakePathWithMode(const char *path,
+                        mode_t mode)
+{
+    int ret = -1;
+    char *tmp;
+
+    if ((tmp = strdup(path)) == NULL)
+        goto cleanup;
+
+    ret = virFileMakePathHelper(tmp, mode);
+
+cleanup:
+    VIR_FREE(tmp);
+    return ret;
+}
+
+/* Build up a fully qualified path for a config file to be
+ * associated with a persistent guest or network */
+char *
+virFileBuildPath(const char *dir, const char *name, const char *ext)
+{
+    char *path;
+
+    if (ext == NULL) {
+        if (virAsprintf(&path, "%s/%s", dir, name) < 0) {
+            virReportOOMError();
+            return NULL;
+        }
+    } else {
+        if (virAsprintf(&path, "%s/%s%s", dir, name, ext) < 0) {
+            virReportOOMError();
+            return NULL;
+        }
+    }
+
+    return path;
+}
+
+/* Open a non-blocking master side of a pty.  If ttyName is not NULL,
+ * then populate it with the name of the slave.  If rawmode is set,
+ * also put the master side into raw mode before returning.  */
+#ifndef WIN32
+int
+virFileOpenTty(int *ttymaster, char **ttyName, int rawmode)
+{
+    /* XXX A word of caution - on some platforms (Solaris and HP-UX),
+     * additional ioctl() calls are needs after opening the slave
+     * before it will cause isatty() to return true.  Should we make
+     * virFileOpenTty also return the opened slave fd, so the caller
+     * doesn't have to worry about that mess?  */
+    int ret = -1;
+    int slave = -1;
+    char *name = NULL;
+
+    /* Unfortunately, we can't use the name argument of openpty, since
+     * there is no guarantee on how large the buffer has to be.
+     * Likewise, we can't use the termios argument: we have to use
+     * read-modify-write since there is no portable way to initialize
+     * a struct termios without use of tcgetattr.  */
+    if (openpty(ttymaster, &slave, NULL, NULL, NULL) < 0)
+        return -1;
+
+    /* What a shame that openpty cannot atomically set FD_CLOEXEC, but
+     * that using posix_openpt/grantpt/unlockpt/ptsname is not
+     * thread-safe, and that ptsname_r is not portable.  */
+    if (virSetNonBlock(*ttymaster) < 0 ||
+        virSetCloseExec(*ttymaster) < 0)
+        goto cleanup;
+
+    /* While Linux supports tcgetattr on either the master or the
+     * slave, Solaris requires it to be on the slave.  */
+    if (rawmode) {
+        struct termios ttyAttr;
+        if (tcgetattr(slave, &ttyAttr) < 0)
+            goto cleanup;
+
+        cfmakeraw(&ttyAttr);
+
+        if (tcsetattr(slave, TCSADRAIN, &ttyAttr) < 0)
+            goto cleanup;
+    }
+
+    /* ttyname_r on the slave is required by POSIX, while ptsname_r on
+     * the master is a glibc extension, and the POSIX ptsname is not
+     * thread-safe.  Since openpty gave us both descriptors, guess
+     * which way we will determine the name?  :)  */
+    if (ttyName) {
+        /* Initial guess of 64 is generally sufficient; rely on ERANGE
+         * to tell us if we need to grow.  */
+        size_t len = 64;
+        int rc;
+
+        if (VIR_ALLOC_N(name, len) < 0)
+            goto cleanup;
+
+        while ((rc = ttyname_r(slave, name, len)) == ERANGE) {
+            if (VIR_RESIZE_N(name, len, len, len) < 0)
+                goto cleanup;
+        }
+        if (rc != 0) {
+            errno = rc;
+            goto cleanup;
+        }
+        *ttyName = name;
+        name = NULL;
+    }
+
+    ret = 0;
+
+cleanup:
+    if (ret != 0)
+        VIR_FORCE_CLOSE(*ttymaster);
+    VIR_FORCE_CLOSE(slave);
+    VIR_FREE(name);
+
+    return ret;
+}
+#else /* WIN32 */
+int
+virFileOpenTty(int *ttymaster ATTRIBUTE_UNUSED,
+               char **ttyName ATTRIBUTE_UNUSED,
+               int rawmode ATTRIBUTE_UNUSED)
+{
+    /* mingw completely lacks pseudo-terminals, and the gnulib
+     * replacements are not (yet) license compatible.  */
+    errno = ENOSYS;
+    return -1;
+}
+#endif /* WIN32 */
+
+bool
+virFileIsAbsPath(const char *path)
+{
+    if (!path)
+        return false;
+
+    if (VIR_FILE_IS_DIR_SEPARATOR(path[0]))
+        return true;
+
+#ifdef WIN32
+    if (c_isalpha(path[0]) &&
+        path[1] == ':' &&
+        VIR_FILE_IS_DIR_SEPARATOR(path[2]))
+        return true;
+#endif
+
+    return false;
+}
+
+
+const char *
+virFileSkipRoot(const char *path)
+{
+#ifdef WIN32
+    /* Skip \\server\share or //server/share */
+    if (VIR_FILE_IS_DIR_SEPARATOR(path[0]) &&
+        VIR_FILE_IS_DIR_SEPARATOR(path[1]) &&
+        path[2] &&
+        !VIR_FILE_IS_DIR_SEPARATOR(path[2]))
+    {
+        const char *p = strchr(path + 2, VIR_FILE_DIR_SEPARATOR);
+        const char *q = strchr(path + 2, '/');
+
+        if (p == NULL || (q != NULL && q < p))
+            p = q;
+
+        if (p && p > path + 2 && p[1]) {
+            path = p + 1;
+
+            while (path[0] &&
+                   !VIR_FILE_IS_DIR_SEPARATOR(path[0]))
+                path++;
+
+            /* Possibly skip a backslash after the share name */
+            if (VIR_FILE_IS_DIR_SEPARATOR(path[0]))
+                path++;
+
+            return path;
+        }
+    }
+#endif
+
+    /* Skip initial slashes */
+    if (VIR_FILE_IS_DIR_SEPARATOR(path[0])) {
+        while (VIR_FILE_IS_DIR_SEPARATOR(path[0]))
+            path++;
+
+        return path;
+    }
+
+#ifdef WIN32
+    /* Skip X:\ */
+    if (c_isalpha(path[0]) &&
+        path[1] == ':' &&
+        VIR_FILE_IS_DIR_SEPARATOR(path[2]))
+        return path + 3;
+#endif
+
+    return path;
+}
+
+
+
+/*
+ * Creates an absolute path for a potentially relative path.
+ * Return 0 if the path was not relative, or on success.
+ * Return -1 on error.
+ *
+ * You must free the result.
+ */
+int
+virFileAbsPath(const char *path, char **abspath)
+{
+    char *buf;
+
+    if (path[0] == '/') {
+        if (!(*abspath = strdup(path)))
+            return -1;
+    } else {
+        buf = getcwd(NULL, 0);
+        if (buf == NULL)
+            return -1;
+
+        if (virAsprintf(abspath, "%s/%s", buf, path) < 0) {
+            VIR_FREE(buf);
+            return -1;
+        }
+        VIR_FREE(buf);
+    }
+
+    return 0;
+}
+
+/* Remove spurious / characters from a path. The result must be freed */
+char *
+virFileSanitizePath(const char *path)
+{
+    const char *cur = path;
+    char *cleanpath;
+    int idx = 0;
+
+    cleanpath = strdup(path);
+    if (!cleanpath) {
+        virReportOOMError();
+        return NULL;
+    }
+
+    /* Need to sanitize:
+     * //           -> //
+     * ///          -> /
+     * /../foo      -> /../foo
+     * /foo///bar/  -> /foo/bar
+     */
+
+    /* Starting with // is valid posix, but ///foo == /foo */
+    if (cur[0] == '/' && cur[1] == '/' && cur[2] != '/') {
+        idx = 2;
+        cur += 2;
+    }
+
+    /* Sanitize path in place */
+    while (*cur != '\0') {
+        if (*cur != '/') {
+            cleanpath[idx++] = *cur++;
+            continue;
+        }
+
+        /* Skip all extra / */
+        while (*++cur == '/')
+            continue;
+
+        /* Don't add a trailing / */
+        if (idx != 0 && *cur == '\0')
+            break;
+
+        cleanpath[idx++] = '/';
+    }
+    cleanpath[idx] = '\0';
+
+    return cleanpath;
+}
index 5f0dd2ba2a3553c0fc045bd8c307cb6b590b557e..bd353315f9cf358b38e9f33367902930a86068c6 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * virfile.h: safer file handling
  *
- * Copyright (C) 2010-2011 Red Hat, Inc.
+ * Copyright (C) 2010-2011, 2013 Red Hat, Inc.
  * Copyright (C) 2010 IBM Corporation
  * Copyright (C) 2010 Stefan Berger
  * Copyright (C) 2010 Eric Blake
@@ -23,8 +23,8 @@
  */
 
 
-#ifndef __VIR_FILES_H_
-# define __VIR_FILES_H_
+#ifndef __VIR_FILE_H_
+# define __VIR_FILE_H_
 
 # include <stdio.h>
 
@@ -36,6 +36,12 @@ typedef enum virFileCloseFlags {
     VIR_FILE_CLOSE_DONT_LOG = 1 << 2,
 } virFileCloseFlags;
 
+ssize_t saferead(int fd, void *buf, size_t count) ATTRIBUTE_RETURN_CHECK;
+ssize_t safewrite(int fd, const void *buf, size_t count)
+    ATTRIBUTE_RETURN_CHECK;
+int safezero(int fd, off_t offset, off_t len)
+    ATTRIBUTE_RETURN_CHECK;
+
 /* Don't call these directly - use the macros below */
 int virFileClose(int *fdptr, virFileCloseFlags flags)
         ATTRIBUTE_RETURN_CHECK;
@@ -110,4 +116,111 @@ int virFileLoopDeviceAssociate(const char *file,
 
 int virFileDeleteTree(const char *dir);
 
-#endif /* __VIR_FILES_H */
+int virFileReadLimFD(int fd, int maxlen, char **buf) ATTRIBUTE_RETURN_CHECK;
+
+int virFileReadAll(const char *path, int maxlen, char **buf) ATTRIBUTE_RETURN_CHECK;
+
+int virFileWriteStr(const char *path, const char *str, mode_t mode)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
+
+int virFileMatchesNameSuffix(const char *file,
+                             const char *name,
+                             const char *suffix);
+
+int virFileHasSuffix(const char *str,
+                     const char *suffix);
+
+int virFileStripSuffix(char *str,
+                       const char *suffix) ATTRIBUTE_RETURN_CHECK;
+
+int virFileLinkPointsTo(const char *checkLink,
+                        const char *checkDest);
+
+int virFileResolveLink(const char *linkpath,
+                       char **resultpath) ATTRIBUTE_RETURN_CHECK;
+int virFileResolveAllLinks(const char *linkpath,
+                           char **resultpath) ATTRIBUTE_RETURN_CHECK;
+
+int virFileIsLink(const char *linkpath)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
+
+char *virFindFileInPath(const char *file);
+
+bool virFileIsDir (const char *file) ATTRIBUTE_NONNULL(1);
+bool virFileExists(const char *file) ATTRIBUTE_NONNULL(1);
+bool virFileIsExecutable(const char *file) ATTRIBUTE_NONNULL(1);
+
+char *virFileSanitizePath(const char *path);
+
+enum {
+    VIR_FILE_OPEN_NONE        = 0,
+    VIR_FILE_OPEN_NOFORK      = (1 << 0),
+    VIR_FILE_OPEN_FORK        = (1 << 1),
+    VIR_FILE_OPEN_FORCE_MODE  = (1 << 2),
+    VIR_FILE_OPEN_FORCE_OWNER = (1 << 3),
+};
+int virFileAccessibleAs(const char *path, int mode,
+                        uid_t uid, gid_t gid)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
+int virFileOpenAs(const char *path, int openflags, mode_t mode,
+                  uid_t uid, gid_t gid,
+                  unsigned int flags)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
+
+enum {
+    VIR_DIR_CREATE_NONE        = 0,
+    VIR_DIR_CREATE_AS_UID      = (1 << 0),
+    VIR_DIR_CREATE_FORCE_PERMS = (1 << 1),
+    VIR_DIR_CREATE_ALLOW_EXIST = (1 << 2),
+};
+int virDirCreate(const char *path, mode_t mode, uid_t uid, gid_t gid,
+                 unsigned int flags) ATTRIBUTE_RETURN_CHECK;
+int virFileMakePath(const char *path) ATTRIBUTE_RETURN_CHECK;
+int virFileMakePathWithMode(const char *path,
+                            mode_t mode) ATTRIBUTE_RETURN_CHECK;
+
+char *virFileBuildPath(const char *dir,
+                       const char *name,
+                       const char *ext) ATTRIBUTE_RETURN_CHECK;
+
+
+# ifdef WIN32
+/* On Win32, the canonical directory separator is the backslash, and
+ * the search path separator is the semicolon. Note that also the
+ * (forward) slash works as directory separator.
+ */
+#  define VIR_FILE_DIR_SEPARATOR '\\'
+#  define VIR_FILE_DIR_SEPARATOR_S "\\"
+#  define VIR_FILE_IS_DIR_SEPARATOR(c) ((c) == VIR_FILE_DIR_SEPARATOR || (c) == '/')
+#  define VIR_FILE_PATH_SEPARATOR ';'
+#  define VIR_FILE_PATH_SEPARATOR_S ";"
+
+# else  /* !WIN32 */
+
+#  define VIR_FILE_DIR_SEPARATOR '/'
+#  define VIR_FILE_DIR_SEPARATOR_S "/"
+#  define VIR_FILE_IS_DIR_SEPARATOR(c) ((c) == VIR_FILE_DIR_SEPARATOR)
+#  define VIR_FILE_PATH_SEPARATOR ':'
+#  define VIR_FILE_PATH_SEPARATOR_S ":"
+
+# endif /* !WIN32 */
+
+bool virFileIsAbsPath(const char *path);
+int virFileAbsPath(const char *path,
+                   char **abspath) ATTRIBUTE_RETURN_CHECK;
+const char *virFileSkipRoot(const char *path);
+
+int virFileOpenTty(int *ttymaster,
+                   char **ttyName,
+                   int rawmode);
+
+char *virFileFindMountPoint(const char *type);
+
+void virFileWaitForDevices(void);
+
+/* NB: this should be combined with virFileBuildPath */
+# define virBuildPath(path, ...) \
+    virBuildPathInternal(path, __VA_ARGS__, NULL)
+int virBuildPathInternal(char **path, ...) ATTRIBUTE_SENTINEL;
+
+#endif /* __VIR_FILE_H */
index 097afba93675d424bd574c9583c17bb7ed16ea07..508c26832a66b1ba362dded54535c80a528d502f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * virhook.c: implementation of the synchronous hooks support
  *
- * Copyright (C) 2010-2012 Red Hat, Inc.
+ * Copyright (C) 2010-2013 Red Hat, Inc.
  * Copyright (C) 2010 Daniel Veillard
  *
  * This library is free software; you can redistribute it and/or
index 06a1356cf21f07e364f099369c83725f56d575dd..b0fe2b03a0ca4706592d66d23a8428e189f9412c 100644 (file)
@@ -44,6 +44,7 @@
 #include "vircommand.h"
 #include "viralloc.h"
 #include "virerror.h"
+#include "virfile.h"
 #include "virlog.h"
 #include "virthread.h"
 #include "virstring.h"
index d77e95d79cac83bb643f9df3e2e71bcfe33eae96..1732d0c13ceef34b416167c5afead351bbb18655 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * virkeyfile.c: "ini"-style configuration file handling
  *
- * Copyright (C) 2012 Red Hat, Inc.
+ * Copyright (C) 2012-2013 Red Hat, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -28,6 +28,7 @@
 #include "c-ctype.h"
 #include "virlog.h"
 #include "viralloc.h"
+#include "virfile.h"
 #include "virutil.h"
 #include "virhash.h"
 #include "virkeyfile.h"
index 5daf21ef7b23c4add76ea42d077d4c96ba913acd..e73c31d7099378832fe4398a3fe29bfba56a7599 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010-2011 Red Hat, Inc.
+ * Copyright (C) 2010-2013 Red Hat, Inc.
  * Copyright IBM Corp. 2008
  *
  * This library is free software; you can redistribute it and/or
@@ -30,6 +30,7 @@
 #include "virlog.h"
 #include "vircommand.h"
 #include "virerror.h"
+#include "virfile.h"
 #include "virstring.h"
 #include "virutil.h"
 
index 2efe634957c15febc9427b7e8cfb72082f4ca83c..686cd49ef008573bbce1ba2acaca2cefca31f9b0 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * virsysinfo.c: get SMBIOS/sysinfo information from the host
  *
- * Copyright (C) 2010-2012 Red Hat, Inc.
+ * Copyright (C) 2010-2013 Red Hat, Inc.
  * Copyright (C) 2010 Daniel Veillard
  *
  * This library is free software; you can redistribute it and/or
@@ -35,6 +35,7 @@
 #include "virlog.h"
 #include "viralloc.h"
 #include "vircommand.h"
+#include "virfile.h"
 #include "virstring.h"
 
 #define VIR_FROM_THIS VIR_FROM_SYSINFO
index 3192634f4ef4fc49bdf6474cb6a92657a27ea6d1..27ba9c773b31e2b3efcfb8881b3f76eeeb358910 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * virusb.c: helper APIs for managing host USB devices
  *
- * Copyright (C) 2009-2012 Red Hat, Inc.
+ * Copyright (C) 2009-2013 Red Hat, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -38,6 +38,7 @@
 #include "viralloc.h"
 #include "virutil.h"
 #include "virerror.h"
+#include "virfile.h"
 #include "virstring.h"
 
 #define USB_SYSFS "/sys/bus/usb"
index 6a4bc14902571bd9ca00c804091bd07ab55d1e0c..43814dfd2fe9f9ac2c9c4dad70d957c94875e0cc 100644 (file)
@@ -29,7 +29,6 @@
 #include <dirent.h>
 #include <stdio.h>
 #include <stdarg.h>
-#include <stdlib.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <errno.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/ioctl.h>
-#include <sys/wait.h>
 #if HAVE_MMAP
 # include <sys/mman.h>
 #endif
 #include <string.h>
-#include <signal.h>
 #include <termios.h>
-#include <pty.h>
 #include <locale.h>
 
 #if HAVE_LIBDEVMAPPER_H
@@ -63,9 +59,6 @@
 # include <cap-ng.h>
 # include <sys/prctl.h>
 #endif
-#if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
-# include <mntent.h>
-#endif
 
 #ifdef WIN32
 # ifdef HAVE_WINSOCK2_H
 #endif
 
 #include "c-ctype.h"
-#include "dirname.h"
 #include "virerror.h"
 #include "virlog.h"
 #include "virbuffer.h"
-#include "virstoragefile.h"
 #include "viralloc.h"
 #include "virthread.h"
 #include "verify.h"
 #include "virfile.h"
 #include "vircommand.h"
 #include "nonblocking.h"
-#include "passfd.h"
-#include "virprocess.h"
-#include "virstring.h"
-
-#ifndef NSIG
-# define NSIG 32
-#endif
-
-verify(sizeof(gid_t) <= sizeof(unsigned int) &&
-       sizeof(uid_t) <= sizeof(unsigned int));
-
-#define VIR_FROM_THIS VIR_FROM_NONE
-
-/* Like read(), but restarts after EINTR.  Doesn't play
- * nicely with nonblocking FD and EAGAIN, in which case
- * you want to use bare read(). Or even use virSocket()
- * if the FD is related to a socket rather than a plain
- * file or pipe. */
-ssize_t
-saferead(int fd, void *buf, size_t count)
-{
-    size_t nread = 0;
-    while (count > 0) {
-        ssize_t r = read(fd, buf, count);
-        if (r < 0 && errno == EINTR)
-            continue;
-        if (r < 0)
-            return r;
-        if (r == 0)
-            return nread;
-        buf = (char *)buf + r;
-        count -= r;
-        nread += r;
-    }
-    return nread;
-}
-
-/* Like write(), but restarts after EINTR. Doesn't play
- * nicely with nonblocking FD and EAGAIN, in which case
- * you want to use bare write(). Or even use virSocket()
- * if the FD is related to a socket rather than a plain
- * file or pipe. */
-ssize_t
-safewrite(int fd, const void *buf, size_t count)
-{
-    size_t nwritten = 0;
-    while (count > 0) {
-        ssize_t r = write(fd, buf, count);
-
-        if (r < 0 && errno == EINTR)
-            continue;
-        if (r < 0)
-            return r;
-        if (r == 0)
-            return nwritten;
-        buf = (const char *)buf + r;
-        count -= r;
-        nwritten += r;
-    }
-    return nwritten;
-}
-
-#ifdef HAVE_POSIX_FALLOCATE
-int safezero(int fd, off_t offset, off_t len)
-{
-    int ret = posix_fallocate(fd, offset, len);
-    if (ret == 0)
-        return 0;
-    errno = ret;
-    return -1;
-}
-#else
-
-# ifdef HAVE_MMAP
-int safezero(int fd, off_t offset, off_t len)
-{
-    int r;
-    char *buf;
-
-    /* memset wants the mmap'ed file to be present on disk so create a
-     * sparse file
-     */
-    r = ftruncate(fd, offset + len);
-    if (r < 0)
-        return -1;
-
-    buf = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset);
-    if (buf == MAP_FAILED)
-        return -1;
-
-    memset(buf, 0, len);
-    munmap(buf, len);
-
-    return 0;
-}
-
-# else /* HAVE_MMAP */
-
-int safezero(int fd, off_t offset, off_t len)
-{
-    int r;
-    char *buf;
-    unsigned long long remain, bytes;
-
-    if (lseek(fd, offset, SEEK_SET) < 0)
-        return -1;
-
-    /* Split up the write in small chunks so as not to allocate lots of RAM */
-    remain = len;
-    bytes = 1024 * 1024;
-
-    r = VIR_ALLOC_N(buf, bytes);
-    if (r < 0) {
-        errno = ENOMEM;
-        return -1;
-    }
-
-    while (remain) {
-        if (bytes > remain)
-            bytes = remain;
-
-        r = safewrite(fd, buf, bytes);
-        if (r < 0) {
-            VIR_FREE(buf);
-            return -1;
-        }
-
-        /* safewrite() guarantees all data will be written */
-        remain -= bytes;
-    }
-    VIR_FREE(buf);
-    return 0;
-}
-# endif /* HAVE_MMAP */
-#endif /* HAVE_POSIX_FALLOCATE */
-
-int virFileStripSuffix(char *str,
-                       const char *suffix)
-{
-    int len = strlen(str);
-    int suffixlen = strlen(suffix);
-
-    if (len < suffixlen)
-        return 0;
-
-    if (!STREQ(str + len - suffixlen, suffix))
-        return 0;
-
-    str[len-suffixlen] = '\0';
-
-    return 1;
-}
-
-#ifndef WIN32
-
-int virSetInherit(int fd, bool inherit) {
-    int fflags;
-    if ((fflags = fcntl(fd, F_GETFD)) < 0)
-        return -1;
-    if (inherit)
-        fflags &= ~FD_CLOEXEC;
-    else
-        fflags |= FD_CLOEXEC;
-    if ((fcntl(fd, F_SETFD, fflags)) < 0)
-        return -1;
-    return 0;
-}
-
-#else /* WIN32 */
-
-int virSetInherit(int fd ATTRIBUTE_UNUSED, bool inherit ATTRIBUTE_UNUSED)
-{
-    /* FIXME: Currently creating child processes is not supported on
-     * Win32, so there is no point in failing calls that are only relevant
-     * when creating child processes. So just pretend that we changed the
-     * inheritance property of the given fd as requested. */
-    return 0;
-}
-
-#endif /* WIN32 */
-
-int virSetBlocking(int fd, bool blocking) {
-    return set_nonblocking_flag(fd, !blocking);
-}
-
-int virSetNonBlock(int fd) {
-    return virSetBlocking(fd, false);
-}
-
-int virSetCloseExec(int fd)
-{
-    return virSetInherit(fd, false);
-}
-
-int
-virPipeReadUntilEOF(int outfd, int errfd,
-                    char **outbuf, char **errbuf) {
-
-    struct pollfd fds[2];
-    int i;
-    int finished[2];
-
-    fds[0].fd = outfd;
-    fds[0].events = POLLIN;
-    fds[0].revents = 0;
-    finished[0] = 0;
-    fds[1].fd = errfd;
-    fds[1].events = POLLIN;
-    fds[1].revents = 0;
-    finished[1] = 0;
-
-    while (!(finished[0] && finished[1])) {
-
-        if (poll(fds, ARRAY_CARDINALITY(fds), -1) < 0) {
-            if ((errno == EAGAIN) || (errno == EINTR))
-                continue;
-            goto pollerr;
-        }
-
-        for (i = 0; i < ARRAY_CARDINALITY(fds); ++i) {
-            char data[1024], **buf;
-            int got, size;
-
-            if (!(fds[i].revents))
-                continue;
-            else if (fds[i].revents & POLLHUP)
-                finished[i] = 1;
-
-            if (!(fds[i].revents & POLLIN)) {
-                if (fds[i].revents & POLLHUP)
-                    continue;
-
-                virReportError(VIR_ERR_INTERNAL_ERROR,
-                               "%s", _("Unknown poll response."));
-                goto error;
-            }
-
-            got = read(fds[i].fd, data, sizeof(data));
-
-            if (got == sizeof(data))
-                finished[i] = 0;
-
-            if (got == 0) {
-                finished[i] = 1;
-                continue;
-            }
-            if (got < 0) {
-                if (errno == EINTR)
-                    continue;
-                if (errno == EAGAIN)
-                    break;
-                goto pollerr;
-            }
-
-            buf = ((fds[i].fd == outfd) ? outbuf : errbuf);
-            size = (*buf ? strlen(*buf) : 0);
-            if (VIR_REALLOC_N(*buf, size+got+1) < 0) {
-                virReportOOMError();
-                goto error;
-            }
-            memmove(*buf+size, data, got);
-            (*buf)[size+got] = '\0';
-        }
-        continue;
-
-    pollerr:
-        virReportSystemError(errno,
-                             "%s", _("poll error"));
-        goto error;
-    }
-
-    return 0;
-
-error:
-    VIR_FREE(*outbuf);
-    VIR_FREE(*errbuf);
-    return -1;
-}
-
-/* Like gnulib's fread_file, but read no more than the specified maximum
-   number of bytes.  If the length of the input is <= max_len, and
-   upon error while reading that data, it works just like fread_file.  */
-static char *
-saferead_lim(int fd, size_t max_len, size_t *length)
-{
-    char *buf = NULL;
-    size_t alloc = 0;
-    size_t size = 0;
-    int save_errno;
-
-    for (;;) {
-        int count;
-        int requested;
-
-        if (size + BUFSIZ + 1 > alloc) {
-            alloc += alloc / 2;
-            if (alloc < size + BUFSIZ + 1)
-                alloc = size + BUFSIZ + 1;
-
-            if (VIR_REALLOC_N(buf, alloc) < 0) {
-                save_errno = errno;
-                break;
-            }
-        }
-
-        /* Ensure that (size + requested <= max_len); */
-        requested = MIN(size < max_len ? max_len - size : 0,
-                        alloc - size - 1);
-        count = saferead(fd, buf + size, requested);
-        size += count;
-
-        if (count != requested || requested == 0) {
-            save_errno = errno;
-            if (count < 0)
-                break;
-            buf[size] = '\0';
-            *length = size;
-            return buf;
-        }
-    }
-
-    VIR_FREE(buf);
-    errno = save_errno;
-    return NULL;
-}
-
-/* A wrapper around saferead_lim that maps a failure due to
-   exceeding the maximum size limitation to EOVERFLOW.  */
-int
-virFileReadLimFD(int fd, int maxlen, char **buf)
-{
-    size_t len;
-    char *s;
-
-    if (maxlen <= 0) {
-        errno = EINVAL;
-        return -1;
-    }
-    s = saferead_lim(fd, maxlen+1, &len);
-    if (s == NULL)
-        return -1;
-    if (len > maxlen || (int)len != len) {
-        VIR_FREE(s);
-        /* There was at least one byte more than MAXLEN.
-           Set errno accordingly. */
-        errno = EOVERFLOW;
-        return -1;
-    }
-    *buf = s;
-    return len;
-}
-
-int virFileReadAll(const char *path, int maxlen, char **buf)
-{
-    int fd = open(path, O_RDONLY);
-    if (fd < 0) {
-        virReportSystemError(errno, _("Failed to open file '%s'"), path);
-        return -1;
-    }
-
-    int len = virFileReadLimFD(fd, maxlen, buf);
-    VIR_FORCE_CLOSE(fd);
-    if (len < 0) {
-        virReportSystemError(errno, _("Failed to read file '%s'"), path);
-        return -1;
-    }
-
-    return len;
-}
-
-/* Truncate @path and write @str to it.  If @mode is 0, ensure that
-   @path exists; otherwise, use @mode if @path must be created.
-   Return 0 for success, nonzero for failure.
-   Be careful to preserve any errno value upon failure. */
-int virFileWriteStr(const char *path, const char *str, mode_t mode)
-{
-    int fd;
-
-    if (mode)
-        fd = open(path, O_WRONLY|O_TRUNC|O_CREAT, mode);
-    else
-        fd = open(path, O_WRONLY|O_TRUNC);
-    if (fd == -1)
-        return -1;
-
-    if (safewrite(fd, str, strlen(str)) < 0) {
-        VIR_FORCE_CLOSE(fd);
-        return -1;
-    }
-
-    /* Use errno from failed close only if there was no write error.  */
-    if (VIR_CLOSE(fd) != 0)
-        return -1;
-
-    return 0;
-}
-
-int virFileMatchesNameSuffix(const char *file,
-                             const char *name,
-                             const char *suffix)
-{
-    int filelen = strlen(file);
-    int namelen = strlen(name);
-    int suffixlen = strlen(suffix);
-
-    if (filelen == (namelen + suffixlen) &&
-        STREQLEN(file, name, namelen) &&
-        STREQLEN(file + namelen, suffix, suffixlen))
-        return 1;
-    else
-        return 0;
-}
-
-int virFileHasSuffix(const char *str,
-                     const char *suffix)
-{
-    int len = strlen(str);
-    int suffixlen = strlen(suffix);
-
-    if (len < suffixlen)
-        return 0;
-
-    return STRCASEEQ(str + len - suffixlen, suffix);
-}
-
-#define SAME_INODE(Stat_buf_1, Stat_buf_2) \
-  ((Stat_buf_1).st_ino == (Stat_buf_2).st_ino \
-   && (Stat_buf_1).st_dev == (Stat_buf_2).st_dev)
-
-/* Return nonzero if checkLink and checkDest
-   refer to the same file.  Otherwise, return 0.  */
-int virFileLinkPointsTo(const char *checkLink,
-                        const char *checkDest)
-{
-    struct stat src_sb;
-    struct stat dest_sb;
-
-    return (stat(checkLink, &src_sb) == 0
-            && stat(checkDest, &dest_sb) == 0
-            && SAME_INODE(src_sb, dest_sb));
-}
-
-
-
-static int
-virFileResolveLinkHelper(const char *linkpath,
-                         bool intermediatePaths,
-                         char **resultpath)
-{
-    struct stat st;
-
-    *resultpath = NULL;
-
-    /* We don't need the full canonicalization of intermediate
-     * directories, if linkpath is absolute and the basename is
-     * already a non-symlink.  */
-    if (IS_ABSOLUTE_FILE_NAME(linkpath) && !intermediatePaths) {
-        if (lstat(linkpath, &st) < 0)
-            return -1;
-
-        if (!S_ISLNK(st.st_mode)) {
-            if (!(*resultpath = strdup(linkpath)))
-                return -1;
-            return 0;
-        }
-    }
-
-    *resultpath = canonicalize_file_name(linkpath);
-
-    return *resultpath == NULL ? -1 : 0;
-}
-
-/*
- * Attempt to resolve a symbolic link, returning an
- * absolute path where only the last component is guaranteed
- * not to be a symlink.
- *
- * Return 0 if path was not a symbolic, or the link was
- * resolved. Return -1 with errno set upon error
- */
-int virFileResolveLink(const char *linkpath,
-                       char **resultpath)
-{
-    return virFileResolveLinkHelper(linkpath, false, resultpath);
-}
-
-/*
- * Attempt to resolve a symbolic link, returning an
- * absolute path where every component is guaranteed
- * not to be a symlink.
- *
- * Return 0 if path was not a symbolic, or the link was
- * resolved. Return -1 with errno set upon error
- */
-int virFileResolveAllLinks(const char *linkpath,
-                           char **resultpath)
-{
-    return virFileResolveLinkHelper(linkpath, true, resultpath);
-}
-
-/*
- * Check whether the given file is a link.
- * Returns 1 in case of the file being a link, 0 in case it is not
- * a link and the negative errno in all other cases.
- */
-int virFileIsLink(const char *linkpath)
-{
-    struct stat st;
-
-    if (lstat(linkpath, &st) < 0)
-        return -errno;
-
-    return S_ISLNK(st.st_mode) != 0;
-}
-
-
-/*
- * Finds a requested executable file in the PATH env. e.g.:
- * "kvm-img" will return "/usr/bin/kvm-img"
- *
- * You must free the result
- */
-char *virFindFileInPath(const char *file)
-{
-    char *path = NULL;
-    char *pathiter;
-    char *pathseg;
-    char *fullpath = NULL;
-
-    if (file == NULL)
-        return NULL;
-
-    /* if we are passed an absolute path (starting with /), return a
-     * copy of that path, after validating that it is executable
-     */
-    if (IS_ABSOLUTE_FILE_NAME(file)) {
-        if (virFileIsExecutable(file))
-            return strdup(file);
-        else
-            return NULL;
-    }
-
-    /* If we are passed an anchored path (containing a /), then there
-     * is no path search - it must exist in the current directory
-     */
-    if (strchr(file, '/')) {
-        if (virFileIsExecutable(file))
-            ignore_value(virFileAbsPath(file, &path));
-        return path;
-    }
-
-    /* copy PATH env so we can tweak it */
-    path = getenv("PATH");
-
-    if (path == NULL || (path = strdup(path)) == NULL)
-        return NULL;
-
-    /* for each path segment, append the file to search for and test for
-     * it. return it if found.
-     */
-    pathiter = path;
-    while ((pathseg = strsep(&pathiter, ":")) != NULL) {
-        if (virAsprintf(&fullpath, "%s/%s", pathseg, file) < 0 ||
-            virFileIsExecutable(fullpath))
-            break;
-        VIR_FREE(fullpath);
-    }
-
-    VIR_FREE(path);
-    return fullpath;
-}
-
-bool virFileIsDir(const char *path)
-{
-    struct stat s;
-    return (stat(path, &s) == 0) && S_ISDIR(s.st_mode);
-}
-
-bool virFileExists(const char *path)
-{
-    return access(path, F_OK) == 0;
-}
-
-/* Check that a file is regular and has executable bits.  If false is
- * returned, errno is valid.
- *
- * Note: In the presence of ACLs, this may return true for a file that
- * would actually fail with EACCES for a given user, or false for a
- * file that the user could actually execute, but setups with ACLs
- * that weird are unusual. */
-bool
-virFileIsExecutable(const char *file)
-{
-    struct stat sb;
-
-    /* We would also want to check faccessat if we cared about ACLs,
-     * but we don't.  */
-    if (stat(file, &sb) < 0)
-        return false;
-    if (S_ISREG(sb.st_mode) && (sb.st_mode & 0111) != 0)
-        return true;
-    errno = S_ISDIR(sb.st_mode) ? EISDIR : EACCES;
-    return false;
-}
-
-#ifndef WIN32
-/* Check that a file is accessible under certain
- * user & gid.
- * @mode can be F_OK, or a bitwise combination of R_OK, W_OK, and X_OK.
- * see 'man access' for more details.
- * Returns 0 on success, -1 on fail with errno set.
- */
-int
-virFileAccessibleAs(const char *path, int mode,
-                    uid_t uid, gid_t gid)
-{
-    pid_t pid = 0;
-    int status, ret = 0;
-    int forkRet = 0;
-
-    if (uid == getuid() &&
-        gid == getgid())
-        return access(path, mode);
-
-    forkRet = virFork(&pid);
-
-    if (pid < 0) {
-        return -1;
-    }
-
-    if (pid) { /* parent */
-        if (virProcessWait(pid, &status) < 0) {
-            /* virProcessWait() already
-             * reported error */
-            return -1;
-        }
-
-        if (!WIFEXITED(status)) {
-            errno = EINTR;
-            return -1;
-        }
-
-        if (status) {
-            errno = WEXITSTATUS(status);
-            return -1;
-        }
-
-        return 0;
-    }
-
-    /* child.
-     * Return positive value here. Parent
-     * will change it to negative one. */
-
-    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);
-}
-
-/* virFileOpenForceOwnerMode() - an internal utility function called
- * only by virFileOpenAs().  Sets the owner and mode of the file
- * opened as "fd" if it's not correct AND the flags say it should be
- * forced. */
-static int
-virFileOpenForceOwnerMode(const char *path, int fd, mode_t mode,
-                          uid_t uid, gid_t gid, unsigned int flags)
-{
-    int ret = 0;
-    struct stat st;
-
-    if (!(flags & (VIR_FILE_OPEN_FORCE_OWNER | VIR_FILE_OPEN_FORCE_MODE)))
-        return 0;
-
-    if (fstat(fd, &st) == -1) {
-        ret = -errno;
-        virReportSystemError(errno, _("stat of '%s' failed"), path);
-        return ret;
-    }
-    /* NB: uid:gid are never "-1" (default) at this point - the caller
-     * has always changed -1 to the value of get[gu]id().
-    */
-    if ((flags & VIR_FILE_OPEN_FORCE_OWNER) &&
-        ((st.st_uid != uid) || (st.st_gid != gid)) &&
-        (fchown(fd, uid, gid) < 0)) {
-        ret = -errno;
-        virReportSystemError(errno,
-                             _("cannot chown '%s' to (%u, %u)"),
-                             path, (unsigned int) uid,
-                             (unsigned int) gid);
-        return ret;
-    }
-    if ((flags & VIR_FILE_OPEN_FORCE_MODE) &&
-        ((mode & (S_IRWXU|S_IRWXG|S_IRWXO)) !=
-         (st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO))) &&
-        (fchmod(fd, mode) < 0)) {
-        ret = -errno;
-        virReportSystemError(errno,
-                             _("cannot set mode of '%s' to %04o"),
-                             path, mode);
-        return ret;
-    }
-    return ret;
-}
-
-/* virFileOpenForked() - an internal utility function called only by
- * virFileOpenAs(). It forks, then the child does setuid+setgid to
- * given uid:gid and attempts to open the file, while the parent just
- * calls recvfd to get the open fd back from the child. returns the
- * fd, or -errno if there is an error. */
-static int
-virFileOpenForked(const char *path, int openflags, mode_t mode,
-                  uid_t uid, gid_t gid, unsigned int flags)
-{
-    pid_t pid;
-    int waitret, status, ret = 0;
-    int fd = -1;
-    int pair[2] = { -1, -1 };
-    int forkRet;
-
-    /* parent is running as root, but caller requested that the
-     * file be opened as some other user and/or group). The
-     * following dance avoids problems caused by root-squashing
-     * NFS servers. */
-
-    if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) < 0) {
-        ret = -errno;
-        virReportSystemError(errno,
-                             _("failed to create socket needed for '%s'"),
-                             path);
-        return ret;
-    }
-
-    forkRet = virFork(&pid);
-    if (pid < 0)
-        return -errno;
-
-    if (pid == 0) {
-
-        /* child */
-
-        VIR_FORCE_CLOSE(pair[0]); /* preserves errno */
-        if (forkRet < 0) {
-            /* error encountered and logged in virFork() after the fork. */
-            ret = -errno;
-            goto childerror;
-        }
-
-        /* set desired uid/gid, then attempt to create the file */
-
-        if (virSetUIDGID(uid, gid) < 0) {
-            ret = -errno;
-            goto childerror;
-        }
-
-        if ((fd = open(path, openflags, mode)) < 0) {
-            ret = -errno;
-            virReportSystemError(errno,
-                                 _("child process failed to create file '%s'"),
-                                 path);
-            goto childerror;
-        }
-
-        /* File is successfully open. Set permissions if requested. */
-        ret = virFileOpenForceOwnerMode(path, fd, mode, uid, gid, flags);
-        if (ret < 0)
-            goto childerror;
-
-        do {
-            ret = sendfd(pair[1], fd);
-        } while (ret < 0 && errno == EINTR);
-
-        if (ret < 0) {
-            ret = -errno;
-            virReportSystemError(errno, "%s",
-                                 _("child process failed to send fd to parent"));
-            goto childerror;
-        }
-
-    childerror:
-        /* ret tracks -errno on failure, but exit value must be positive.
-         * If the child exits with EACCES, then the parent tries again.  */
-        /* XXX This makes assumptions about errno being < 255, which is
-         * not true on Hurd.  */
-        VIR_FORCE_CLOSE(pair[1]);
-        if (ret < 0) {
-            VIR_FORCE_CLOSE(fd);
-        }
-        ret = -ret;
-        if ((ret & 0xff) != ret) {
-            VIR_WARN("unable to pass desired return value %d", ret);
-            ret = 0xff;
-        }
-        _exit(ret);
-    }
-
-    /* parent */
-
-    VIR_FORCE_CLOSE(pair[1]);
-
-    do {
-        fd = recvfd(pair[0], 0);
-    } while (fd < 0 && errno == EINTR);
-    VIR_FORCE_CLOSE(pair[0]); /* NB: this preserves errno */
-
-    if (fd < 0 && errno != EACCES) {
-        ret = -errno;
-        while (waitpid(pid, NULL, 0) == -1 && errno == EINTR);
-        return ret;
-    }
-
-    /* wait for child to complete, and retrieve its exit code */
-    while ((waitret = waitpid(pid, &status, 0) == -1)
-           && (errno == EINTR));
-    if (waitret == -1) {
-        ret = -errno;
-        virReportSystemError(errno,
-                             _("failed to wait for child creating '%s'"),
-                             path);
-        VIR_FORCE_CLOSE(fd);
-        return ret;
-    }
-    if (!WIFEXITED(status) || (ret = -WEXITSTATUS(status)) == -EACCES ||
-        fd == -1) {
-        /* fall back to the simpler method, which works better in
-         * some cases */
-        VIR_FORCE_CLOSE(fd);
-        if (flags & VIR_FILE_OPEN_NOFORK) {
-            /* If we had already tried opening w/o fork+setuid and
-             * failed, no sense trying again. Just set return the
-             * original errno that we got at that time (by
-             * definition, always either EACCES or EPERM - EACCES
-             * is close enough).
-             */
-            return -EACCES;
-        }
-        if ((fd = open(path, openflags, mode)) < 0)
-            return -errno;
-        ret = virFileOpenForceOwnerMode(path, fd, mode, uid, gid, flags);
-        if (ret < 0) {
-            VIR_FORCE_CLOSE(fd);
-            return ret;
-        }
-    }
-    return fd;
-}
-
-/**
- * virFileOpenAs:
- * @path: file to open or create
- * @openflags: flags to pass to open
- * @mode: mode to use on creation or when forcing permissions
- * @uid: uid that should own file on creation
- * @gid: gid that should own file
- * @flags: bit-wise or of VIR_FILE_OPEN_* flags
- *
- * Open @path, and return an fd to the open file. @openflags contains
- * the flags normally passed to open(2), while those in @flags are
- * used internally. If @flags includes VIR_FILE_OPEN_NOFORK, then try
- * opening the file while executing with the current uid:gid
- * (i.e. don't fork+setuid+setgid before the call to open()).  If
- * @flags includes VIR_FILE_OPEN_FORK, then try opening the file while
- * the effective user id is @uid (by forking a child process); this
- * allows one to bypass root-squashing NFS issues; NOFORK is always
- * tried before FORK (the absence of both flags is treated identically
- * to (VIR_FILE_OPEN_NOFORK | VIR_FILE_OPEN_FORK)). If @flags includes
- * VIR_FILE_OPEN_FORCE_OWNER, then ensure that @path is owned by
- * uid:gid before returning (even if it already existed with a
- * different owner). If @flags includes VIR_FILE_OPEN_FORCE_MODE,
- * ensure it has those permissions before returning (again, even if
- * the file already existed with different permissions).
- *
- * The return value (if non-negative) is the file descriptor, left
- * open.  Returns -errno on failure.
- */
-int
-virFileOpenAs(const char *path, int openflags, mode_t mode,
-              uid_t uid, gid_t gid, unsigned int flags)
-{
-    int ret = 0, fd = -1;
-
-    /* allow using -1 to mean "current value" */
-    if (uid == (uid_t) -1)
-        uid = getuid();
-    if (gid == (gid_t) -1)
-        gid = getgid();
-
-    /* treat absence of both flags as presence of both for simpler
-     * calling. */
-    if (!(flags & (VIR_FILE_OPEN_NOFORK|VIR_FILE_OPEN_FORK)))
-        flags |= VIR_FILE_OPEN_NOFORK|VIR_FILE_OPEN_FORK;
-
-    if ((flags & VIR_FILE_OPEN_NOFORK)
-        || (getuid() != 0)
-        || ((uid == 0) && (gid == 0))) {
-
-        if ((fd = open(path, openflags, mode)) < 0) {
-            ret = -errno;
-            if (!(flags & VIR_FILE_OPEN_FORK))
-                goto error;
-        } else {
-            ret = virFileOpenForceOwnerMode(path, fd, mode, uid, gid, flags);
-            if (ret < 0)
-                goto error;
-        }
-    }
-
-    /* If we either 1) didn't try opening as current user at all, or
-     * 2) failed, and errno/virStorageFileIsSharedFS indicate we might
-     * be successful if we try as a different uid, then try doing
-     * fork+setuid+setgid before opening.
-     */
-    if ((fd < 0) && (flags & VIR_FILE_OPEN_FORK)) {
-
-        if (ret < 0) {
-            /* An open(2) that failed due to insufficient permissions
-             * could return one or the other of these depending on OS
-             * version and circumstances. Any other errno indicates a
-             * problem that couldn't be remedied by fork+setuid
-             * anyway. */
-            if (ret != -EACCES && ret != -EPERM)
-                goto error;
-
-            /* On Linux we can also verify the FS-type of the
-             * directory.  (this is a NOP on other platforms). */
-            if (virStorageFileIsSharedFS(path) <= 0)
-                goto error;
-        }
-
-        /* passed all prerequisites - retry the open w/fork+setuid */
-        if ((fd = virFileOpenForked(path, openflags, mode, uid, gid, flags)) < 0) {
-            ret = fd;
-            goto error;
-        }
-    }
-
-    /* File is successfully opened */
-    return fd;
-
-error:
-    if (fd >= 0) {
-        /* some other failure after the open succeeded */
-        VIR_FORCE_CLOSE(fd);
-    }
-    /* whoever failed the open last has already set ret = -errno */
-    return ret;
-}
-
-/* return -errno on failure, or 0 on success */
-static int virDirCreateNoFork(const char *path, mode_t mode, uid_t uid, gid_t gid,
-                              unsigned int flags) {
-    int ret = 0;
-    struct stat st;
-
-    if ((mkdir(path, mode) < 0)
-        && !((errno == EEXIST) && (flags & VIR_DIR_CREATE_ALLOW_EXIST))) {
-        ret = -errno;
-        virReportSystemError(errno, _("failed to create directory '%s'"),
-                             path);
-        goto error;
-    }
-
-    if (stat(path, &st) == -1) {
-        ret = -errno;
-        virReportSystemError(errno, _("stat of '%s' failed"), path);
-        goto error;
-    }
-    if (((st.st_uid != uid) || (st.st_gid != gid))
-        && (chown(path, uid, gid) < 0)) {
-        ret = -errno;
-        virReportSystemError(errno, _("cannot chown '%s' to (%u, %u)"),
-                             path, (unsigned int) uid, (unsigned int) gid);
-        goto error;
-    }
-    if ((flags & VIR_DIR_CREATE_FORCE_PERMS)
-        && (chmod(path, mode) < 0)) {
-        ret = -errno;
-        virReportSystemError(errno,
-                             _("cannot set mode of '%s' to %04o"),
-                             path, mode);
-        goto error;
-    }
-error:
-    return ret;
-}
-
-/* return -errno on failure, or 0 on success */
-int virDirCreate(const char *path, mode_t mode,
-                 uid_t uid, gid_t gid, unsigned int flags) {
-    struct stat st;
-    pid_t pid;
-    int waitret;
-    int status, ret = 0;
-
-    /* allow using -1 to mean "current value" */
-    if (uid == (uid_t) -1)
-        uid = getuid();
-    if (gid == (gid_t) -1)
-        gid = getgid();
-
-    if ((!(flags & VIR_DIR_CREATE_AS_UID))
-        || (getuid() != 0)
-        || ((uid == 0) && (gid == 0))
-        || ((flags & VIR_DIR_CREATE_ALLOW_EXIST) && (stat(path, &st) >= 0))) {
-        return virDirCreateNoFork(path, mode, uid, gid, flags);
-    }
-
-    int forkRet = virFork(&pid);
-
-    if (pid < 0) {
-        ret = -errno;
-        return ret;
-    }
-
-    if (pid) { /* parent */
-        /* wait for child to complete, and retrieve its exit code */
-        while ((waitret = waitpid(pid, &status, 0) == -1)  && (errno == EINTR));
-        if (waitret == -1) {
-            ret = -errno;
-            virReportSystemError(errno,
-                                 _("failed to wait for child creating '%s'"),
-                                 path);
-            goto parenterror;
-        }
-        if (!WIFEXITED(status) || (ret = -WEXITSTATUS(status)) == -EACCES) {
-            /* fall back to the simpler method, which works better in
-             * some cases */
-            return virDirCreateNoFork(path, mode, uid, gid, flags);
-        }
-parenterror:
-        return ret;
-    }
-
-    /* child */
-
-    if (forkRet < 0) {
-        /* error encountered and logged in virFork() after the fork. */
-        goto childerror;
-    }
-
-    /* set desired uid/gid, then attempt to create the directory */
-
-    if (virSetUIDGID(uid, gid) < 0) {
-        ret = -errno;
-        goto childerror;
-    }
-    if (mkdir(path, mode) < 0) {
-        ret = -errno;
-        if (ret != -EACCES) {
-            /* in case of EACCES, the parent will retry */
-            virReportSystemError(errno, _("child failed to create directory '%s'"),
-                                 path);
-        }
-        goto childerror;
-    }
-    /* check if group was set properly by creating after
-     * setgid. If not, try doing it with chown */
-    if (stat(path, &st) == -1) {
-        ret = -errno;
-        virReportSystemError(errno,
-                             _("stat of '%s' failed"), path);
-        goto childerror;
-    }
-    if ((st.st_gid != gid) && (chown(path, (uid_t) -1, gid) < 0)) {
-        ret = -errno;
-        virReportSystemError(errno,
-                             _("cannot chown '%s' to group %u"),
-                             path, (unsigned int) gid);
-        goto childerror;
-    }
-    if ((flags & VIR_DIR_CREATE_FORCE_PERMS)
-        && chmod(path, mode) < 0) {
-        virReportSystemError(errno,
-                             _("cannot set mode of '%s' to %04o"),
-                             path, mode);
-        goto childerror;
-    }
-childerror:
-    _exit(ret);
-}
-
-#else /* WIN32 */
-
-int
-virFileAccessibleAs(const char *path,
-                    int mode,
-                    uid_t uid ATTRIBUTE_UNUSED,
-                    gid_t gid ATTRIBUTE_UNUSED)
-{
-
-    VIR_WARN("Ignoring uid/gid due to WIN32");
-
-    return access(path, mode);
-}
-
-/* return -errno on failure, or 0 on success */
-int virFileOpenAs(const char *path ATTRIBUTE_UNUSED,
-                  int openflags ATTRIBUTE_UNUSED,
-                  mode_t mode ATTRIBUTE_UNUSED,
-                  uid_t uid ATTRIBUTE_UNUSED,
-                  gid_t gid ATTRIBUTE_UNUSED,
-                  unsigned int flags_unused ATTRIBUTE_UNUSED)
-{
-    virReportError(VIR_ERR_INTERNAL_ERROR,
-                   "%s", _("virFileOpenAs is not implemented for WIN32"));
-
-    return -ENOSYS;
-}
-
-int virDirCreate(const char *path ATTRIBUTE_UNUSED,
-                 mode_t mode ATTRIBUTE_UNUSED,
-                 uid_t uid ATTRIBUTE_UNUSED,
-                 gid_t gid ATTRIBUTE_UNUSED,
-                 unsigned int flags_unused ATTRIBUTE_UNUSED)
-{
-    virReportError(VIR_ERR_INTERNAL_ERROR,
-                   "%s", _("virDirCreate is not implemented for WIN32"));
-
-    return -ENOSYS;
-}
-#endif /* WIN32 */
-
-static int virFileMakePathHelper(char *path, mode_t mode)
-{
-    struct stat st;
-    char *p;
+#include "virprocess.h"
+#include "virstring.h"
+#include "virutil.h"
 
-    VIR_DEBUG("path=%s mode=0%o", path, mode);
+#ifndef NSIG
+# define NSIG 32
+#endif
 
-    if (stat(path, &st) >= 0) {
-        if (S_ISDIR(st.st_mode))
-            return 0;
+verify(sizeof(gid_t) <= sizeof(unsigned int) &&
+       sizeof(uid_t) <= sizeof(unsigned int));
 
-        errno = ENOTDIR;
-        return -1;
-    }
+#define VIR_FROM_THIS VIR_FROM_NONE
 
-    if (errno != ENOENT)
-        return -1;
+#ifndef WIN32
 
-    if ((p = strrchr(path, '/')) == NULL) {
-        errno = EINVAL;
+int virSetInherit(int fd, bool inherit) {
+    int fflags;
+    if ((fflags = fcntl(fd, F_GETFD)) < 0)
         return -1;
-    }
-
-    if (p != path) {
-        *p = '\0';
-
-        if (virFileMakePathHelper(path, mode) < 0)
-            return -1;
-
-        *p = '/';
-    }
-
-    if (mkdir(path, mode) < 0 && errno != EEXIST)
+    if (inherit)
+        fflags &= ~FD_CLOEXEC;
+    else
+        fflags |= FD_CLOEXEC;
+    if ((fcntl(fd, F_SETFD, fflags)) < 0)
         return -1;
-
     return 0;
 }
 
-/**
- * Creates the given directory with mode 0777 if it's not already existing.
- *
- * Returns 0 on success, or -1 if an error occurred (in which case, errno
- * is set appropriately).
- */
-int virFileMakePath(const char *path)
-{
-    return virFileMakePathWithMode(path, 0777);
-}
+#else /* WIN32 */
 
-int
-virFileMakePathWithMode(const char *path,
-                        mode_t mode)
+int virSetInherit(int fd ATTRIBUTE_UNUSED, bool inherit ATTRIBUTE_UNUSED)
 {
-    int ret = -1;
-    char *tmp;
-
-    if ((tmp = strdup(path)) == NULL)
-        goto cleanup;
-
-    ret = virFileMakePathHelper(tmp, mode);
-
-cleanup:
-    VIR_FREE(tmp);
-    return ret;
+    /* FIXME: Currently creating child processes is not supported on
+     * Win32, so there is no point in failing calls that are only relevant
+     * when creating child processes. So just pretend that we changed the
+     * inheritance property of the given fd as requested. */
+    return 0;
 }
 
-/* Build up a fully qualified path for a config file to be
- * associated with a persistent guest or network */
-char *
-virFileBuildPath(const char *dir, const char *name, const char *ext)
-{
-    char *path;
-
-    if (ext == NULL) {
-        if (virAsprintf(&path, "%s/%s", dir, name) < 0) {
-            virReportOOMError();
-            return NULL;
-        }
-    } else {
-        if (virAsprintf(&path, "%s/%s%s", dir, name, ext) < 0) {
-            virReportOOMError();
-            return NULL;
-        }
-    }
+#endif /* WIN32 */
 
-    return path;
+int virSetBlocking(int fd, bool blocking) {
+    return set_nonblocking_flag(fd, !blocking);
 }
 
-/* Open a non-blocking master side of a pty.  If ttyName is not NULL,
- * then populate it with the name of the slave.  If rawmode is set,
- * also put the master side into raw mode before returning.  */
-#ifndef WIN32
-int virFileOpenTty(int *ttymaster,
-                   char **ttyName,
-                   int rawmode)
-{
-    /* XXX A word of caution - on some platforms (Solaris and HP-UX),
-     * additional ioctl() calls are needs after opening the slave
-     * before it will cause isatty() to return true.  Should we make
-     * virFileOpenTty also return the opened slave fd, so the caller
-     * doesn't have to worry about that mess?  */
-    int ret = -1;
-    int slave = -1;
-    char *name = NULL;
-
-    /* Unfortunately, we can't use the name argument of openpty, since
-     * there is no guarantee on how large the buffer has to be.
-     * Likewise, we can't use the termios argument: we have to use
-     * read-modify-write since there is no portable way to initialize
-     * a struct termios without use of tcgetattr.  */
-    if (openpty(ttymaster, &slave, NULL, NULL, NULL) < 0)
-        return -1;
-
-    /* What a shame that openpty cannot atomically set FD_CLOEXEC, but
-     * that using posix_openpt/grantpt/unlockpt/ptsname is not
-     * thread-safe, and that ptsname_r is not portable.  */
-    if (virSetNonBlock(*ttymaster) < 0 ||
-        virSetCloseExec(*ttymaster) < 0)
-        goto cleanup;
-
-    /* While Linux supports tcgetattr on either the master or the
-     * slave, Solaris requires it to be on the slave.  */
-    if (rawmode) {
-        struct termios ttyAttr;
-        if (tcgetattr(slave, &ttyAttr) < 0)
-            goto cleanup;
-
-        cfmakeraw(&ttyAttr);
-
-        if (tcsetattr(slave, TCSADRAIN, &ttyAttr) < 0)
-            goto cleanup;
-    }
-
-    /* ttyname_r on the slave is required by POSIX, while ptsname_r on
-     * the master is a glibc extension, and the POSIX ptsname is not
-     * thread-safe.  Since openpty gave us both descriptors, guess
-     * which way we will determine the name?  :)  */
-    if (ttyName) {
-        /* Initial guess of 64 is generally sufficient; rely on ERANGE
-         * to tell us if we need to grow.  */
-        size_t len = 64;
-        int rc;
-
-        if (VIR_ALLOC_N(name, len) < 0)
-            goto cleanup;
-
-        while ((rc = ttyname_r(slave, name, len)) == ERANGE) {
-            if (VIR_RESIZE_N(name, len, len, len) < 0)
-                goto cleanup;
-        }
-        if (rc != 0) {
-            errno = rc;
-            goto cleanup;
-        }
-        *ttyName = name;
-        name = NULL;
-    }
-
-    ret = 0;
-
-cleanup:
-    if (ret != 0)
-        VIR_FORCE_CLOSE(*ttymaster);
-    VIR_FORCE_CLOSE(slave);
-    VIR_FREE(name);
-
-    return ret;
-}
-#else /* WIN32 */
-int virFileOpenTty(int *ttymaster ATTRIBUTE_UNUSED,
-                   char **ttyName ATTRIBUTE_UNUSED,
-                   int rawmode ATTRIBUTE_UNUSED)
-{
-    /* mingw completely lacks pseudo-terminals, and the gnulib
-     * replacements are not (yet) license compatible.  */
-    errno = ENOSYS;
-    return -1;
+int virSetNonBlock(int fd) {
+    return virSetBlocking(fd, false);
 }
-#endif /* WIN32 */
 
-bool virFileIsAbsPath(const char *path)
+int virSetCloseExec(int fd)
 {
-    if (!path)
-        return false;
-
-    if (VIR_FILE_IS_DIR_SEPARATOR(path[0]))
-        return true;
-
-#ifdef WIN32
-    if (c_isalpha(path[0]) &&
-        path[1] == ':' &&
-        VIR_FILE_IS_DIR_SEPARATOR(path[2]))
-        return true;
-#endif
-
-    return false;
+    return virSetInherit(fd, false);
 }
 
+int
+virPipeReadUntilEOF(int outfd, int errfd,
+                    char **outbuf, char **errbuf) {
 
-const char *virFileSkipRoot(const char *path)
-{
-#ifdef WIN32
-    /* Skip \\server\share or //server/share */
-    if (VIR_FILE_IS_DIR_SEPARATOR(path[0]) &&
-        VIR_FILE_IS_DIR_SEPARATOR(path[1]) &&
-        path[2] &&
-        !VIR_FILE_IS_DIR_SEPARATOR(path[2]))
-    {
-        const char *p = strchr(path + 2, VIR_FILE_DIR_SEPARATOR);
-        const char *q = strchr(path + 2, '/');
-
-        if (p == NULL || (q != NULL && q < p))
-            p = q;
-
-        if (p && p > path + 2 && p[1]) {
-            path = p + 1;
+    struct pollfd fds[2];
+    int i;
+    int finished[2];
 
-            while (path[0] &&
-                   !VIR_FILE_IS_DIR_SEPARATOR(path[0]))
-                path++;
+    fds[0].fd = outfd;
+    fds[0].events = POLLIN;
+    fds[0].revents = 0;
+    finished[0] = 0;
+    fds[1].fd = errfd;
+    fds[1].events = POLLIN;
+    fds[1].revents = 0;
+    finished[1] = 0;
 
-            /* Possibly skip a backslash after the share name */
-            if (VIR_FILE_IS_DIR_SEPARATOR(path[0]))
-                path++;
+    while (!(finished[0] && finished[1])) {
 
-            return path;
+        if (poll(fds, ARRAY_CARDINALITY(fds), -1) < 0) {
+            if ((errno == EAGAIN) || (errno == EINTR))
+                continue;
+            goto pollerr;
         }
-    }
-#endif
-
-    /* Skip initial slashes */
-    if (VIR_FILE_IS_DIR_SEPARATOR(path[0])) {
-        while (VIR_FILE_IS_DIR_SEPARATOR(path[0]))
-            path++;
 
-        return path;
-    }
+        for (i = 0; i < ARRAY_CARDINALITY(fds); ++i) {
+            char data[1024], **buf;
+            int got, size;
 
-#ifdef WIN32
-    /* Skip X:\ */
-    if (c_isalpha(path[0]) &&
-        path[1] == ':' &&
-        VIR_FILE_IS_DIR_SEPARATOR(path[2]))
-        return path + 3;
-#endif
+            if (!(fds[i].revents))
+                continue;
+            else if (fds[i].revents & POLLHUP)
+                finished[i] = 1;
 
-    return path;
-}
+            if (!(fds[i].revents & POLLIN)) {
+                if (fds[i].revents & POLLHUP)
+                    continue;
 
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               "%s", _("Unknown poll response."));
+                goto error;
+            }
 
+            got = read(fds[i].fd, data, sizeof(data));
 
-/*
- * Creates an absolute path for a potentially relative path.
- * Return 0 if the path was not relative, or on success.
- * Return -1 on error.
- *
- * You must free the result.
- */
-int virFileAbsPath(const char *path, char **abspath)
-{
-    char *buf;
+            if (got == sizeof(data))
+                finished[i] = 0;
 
-    if (path[0] == '/') {
-        if (!(*abspath = strdup(path)))
-            return -1;
-    } else {
-        buf = getcwd(NULL, 0);
-        if (buf == NULL)
-            return -1;
+            if (got == 0) {
+                finished[i] = 1;
+                continue;
+            }
+            if (got < 0) {
+                if (errno == EINTR)
+                    continue;
+                if (errno == EAGAIN)
+                    break;
+                goto pollerr;
+            }
 
-        if (virAsprintf(abspath, "%s/%s", buf, path) < 0) {
-            VIR_FREE(buf);
-            return -1;
+            buf = ((fds[i].fd == outfd) ? outbuf : errbuf);
+            size = (*buf ? strlen(*buf) : 0);
+            if (VIR_REALLOC_N(*buf, size+got+1) < 0) {
+                virReportOOMError();
+                goto error;
+            }
+            memmove(*buf+size, data, got);
+            (*buf)[size+got] = '\0';
         }
-        VIR_FREE(buf);
-    }
-
-    return 0;
-}
-
-/* Remove spurious / characters from a path. The result must be freed */
-char *
-virFileSanitizePath(const char *path)
-{
-    const char *cur = path;
-    char *cleanpath;
-    int idx = 0;
-
-    cleanpath = strdup(path);
-    if (!cleanpath) {
-        virReportOOMError();
-        return NULL;
-    }
-
-    /* Need to sanitize:
-     * //           -> //
-     * ///          -> /
-     * /../foo      -> /../foo
-     * /foo///bar/  -> /foo/bar
-     */
+        continue;
 
-    /* Starting with // is valid posix, but ///foo == /foo */
-    if (cur[0] == '/' && cur[1] == '/' && cur[2] != '/') {
-        idx = 2;
-        cur += 2;
+    pollerr:
+        virReportSystemError(errno,
+                             "%s", _("poll error"));
+        goto error;
     }
 
-    /* Sanitize path in place */
-    while (*cur != '\0') {
-        if (*cur != '/') {
-            cleanpath[idx++] = *cur++;
-            continue;
-        }
-
-        /* Skip all extra / */
-        while (*++cur == '/')
-            continue;
-
-        /* Don't add a trailing / */
-        if (idx != 0 && *cur == '\0')
-            break;
-
-        cleanpath[idx++] = '/';
-    }
-    cleanpath[idx] = '\0';
+    return 0;
 
-    return cleanpath;
+error:
+    VIR_FREE(*outbuf);
+    VIR_FREE(*errbuf);
+    return -1;
 }
 
 /* Convert C from hexadecimal character to integer.  */
@@ -2777,50 +1440,6 @@ virSetUIDGIDWithCaps(uid_t uid, gid_t gid,
 #endif
 
 
-#if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
-/* search /proc/mounts for mount point of *type; return pointer to
- * malloc'ed string of the path if found, otherwise return NULL
- * with errno set to an appropriate value.
- */
-char *virFileFindMountPoint(const char *type)
-{
-    FILE *f;
-    struct mntent mb;
-    char mntbuf[1024];
-    char *ret = NULL;
-
-    f = setmntent("/proc/mounts", "r");
-    if (!f)
-        return NULL;
-
-    while (getmntent_r(f, &mb, mntbuf, sizeof(mntbuf))) {
-        if (STREQ(mb.mnt_type, type)) {
-            ret = strdup(mb.mnt_dir);
-            goto cleanup;
-        }
-    }
-
-    if (!ret)
-        errno = ENOENT;
-
-cleanup:
-    endmntent(f);
-
-    return ret;
-}
-
-#else /* defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R */
-
-char *
-virFileFindMountPoint(const char *type ATTRIBUTE_UNUSED)
-{
-    errno = ENOSYS;
-
-    return NULL;
-}
-
-#endif /* defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R */
-
 #if defined(UDEVADM) || defined(UDEVSETTLE)
 void virFileWaitForDevices(void)
 {
@@ -2847,34 +1466,6 @@ void virFileWaitForDevices(void)
 void virFileWaitForDevices(void) {}
 #endif
 
-int virBuildPathInternal(char **path, ...)
-{
-    char *path_component = NULL;
-    virBuffer buf = VIR_BUFFER_INITIALIZER;
-    va_list ap;
-    int ret = 0;
-
-    va_start(ap, path);
-
-    path_component = va_arg(ap, char *);
-    virBufferAdd(&buf, path_component, -1);
-
-    while ((path_component = va_arg(ap, char *)) != NULL)
-    {
-        virBufferAddChar(&buf, '/');
-        virBufferAdd(&buf, path_component, -1);
-    }
-
-    va_end(ap);
-
-    *path = virBufferContentAndReset(&buf);
-    if (*path == NULL) {
-        ret = -1;
-    }
-
-    return ret;
-}
-
 #if HAVE_LIBDEVMAPPER_H
 bool
 virIsDevMapperDevice(const char *dev_name)
index 4c0a9a5c4a12bde9e4a72a3b394ba2b6a6b2c73d..00ee0c3d0bb11e30b02b21f49777a3c336f15f0d 100644 (file)
 #  define MAX(a, b) ((a) > (b) ? (a) : (b))
 # endif
 
-ssize_t saferead(int fd, void *buf, size_t count) ATTRIBUTE_RETURN_CHECK;
-ssize_t safewrite(int fd, const void *buf, size_t count)
-    ATTRIBUTE_RETURN_CHECK;
-int safezero(int fd, off_t offset, off_t len)
-    ATTRIBUTE_RETURN_CHECK;
-
 int virSetBlocking(int fd, bool blocking) ATTRIBUTE_RETURN_CHECK;
 int virSetNonBlock(int fd) ATTRIBUTE_RETURN_CHECK;
 int virSetInherit(int fd, bool inherit) ATTRIBUTE_RETURN_CHECK;
@@ -56,104 +50,6 @@ int virSetUIDGID(uid_t uid, gid_t gid);
 int virSetUIDGIDWithCaps(uid_t uid, gid_t gid, unsigned long long capBits,
                          bool clearExistingCaps);
 
-int virFileReadLimFD(int fd, int maxlen, char **buf) ATTRIBUTE_RETURN_CHECK;
-
-int virFileReadAll(const char *path, int maxlen, char **buf) ATTRIBUTE_RETURN_CHECK;
-
-int virFileWriteStr(const char *path, const char *str, mode_t mode)
-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
-
-int virFileMatchesNameSuffix(const char *file,
-                             const char *name,
-                             const char *suffix);
-
-int virFileHasSuffix(const char *str,
-                     const char *suffix);
-
-int virFileStripSuffix(char *str,
-                       const char *suffix) ATTRIBUTE_RETURN_CHECK;
-
-int virFileLinkPointsTo(const char *checkLink,
-                        const char *checkDest);
-
-int virFileResolveLink(const char *linkpath,
-                       char **resultpath) ATTRIBUTE_RETURN_CHECK;
-int virFileResolveAllLinks(const char *linkpath,
-                           char **resultpath) ATTRIBUTE_RETURN_CHECK;
-
-int virFileIsLink(const char *linkpath)
-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
-
-char *virFindFileInPath(const char *file);
-
-bool virFileIsDir (const char *file) ATTRIBUTE_NONNULL(1);
-bool virFileExists(const char *file) ATTRIBUTE_NONNULL(1);
-bool virFileIsExecutable(const char *file) ATTRIBUTE_NONNULL(1);
-
-char *virFileSanitizePath(const char *path);
-
-enum {
-    VIR_FILE_OPEN_NONE        = 0,
-    VIR_FILE_OPEN_NOFORK      = (1 << 0),
-    VIR_FILE_OPEN_FORK        = (1 << 1),
-    VIR_FILE_OPEN_FORCE_MODE  = (1 << 2),
-    VIR_FILE_OPEN_FORCE_OWNER = (1 << 3),
-};
-int virFileAccessibleAs(const char *path, int mode,
-                        uid_t uid, gid_t gid)
-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
-int virFileOpenAs(const char *path, int openflags, mode_t mode,
-                  uid_t uid, gid_t gid,
-                  unsigned int flags)
-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
-
-enum {
-    VIR_DIR_CREATE_NONE        = 0,
-    VIR_DIR_CREATE_AS_UID      = (1 << 0),
-    VIR_DIR_CREATE_FORCE_PERMS = (1 << 1),
-    VIR_DIR_CREATE_ALLOW_EXIST = (1 << 2),
-};
-int virDirCreate(const char *path, mode_t mode, uid_t uid, gid_t gid,
-                 unsigned int flags) ATTRIBUTE_RETURN_CHECK;
-int virFileMakePath(const char *path) ATTRIBUTE_RETURN_CHECK;
-int virFileMakePathWithMode(const char *path,
-                            mode_t mode) ATTRIBUTE_RETURN_CHECK;
-
-char *virFileBuildPath(const char *dir,
-                       const char *name,
-                       const char *ext) ATTRIBUTE_RETURN_CHECK;
-
-
-# ifdef WIN32
-/* On Win32, the canonical directory separator is the backslash, and
- * the search path separator is the semicolon. Note that also the
- * (forward) slash works as directory separator.
- */
-#  define VIR_FILE_DIR_SEPARATOR '\\'
-#  define VIR_FILE_DIR_SEPARATOR_S "\\"
-#  define VIR_FILE_IS_DIR_SEPARATOR(c) ((c) == VIR_FILE_DIR_SEPARATOR || (c) == '/')
-#  define VIR_FILE_PATH_SEPARATOR ';'
-#  define VIR_FILE_PATH_SEPARATOR_S ";"
-
-# else  /* !WIN32 */
-
-#  define VIR_FILE_DIR_SEPARATOR '/'
-#  define VIR_FILE_DIR_SEPARATOR_S "/"
-#  define VIR_FILE_IS_DIR_SEPARATOR(c) ((c) == VIR_FILE_DIR_SEPARATOR)
-#  define VIR_FILE_PATH_SEPARATOR ':'
-#  define VIR_FILE_PATH_SEPARATOR_S ":"
-
-# endif /* !WIN32 */
-
-bool virFileIsAbsPath(const char *path);
-int virFileAbsPath(const char *path,
-                   char **abspath) ATTRIBUTE_RETURN_CHECK;
-const char *virFileSkipRoot(const char *path);
-
-int virFileOpenTty(int *ttymaster,
-                   char **ttyName,
-                   int rawmode);
-
 int virScaleInteger(unsigned long long *value, const char *suffix,
                     unsigned long long scale, unsigned long long limit)
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
@@ -224,13 +120,6 @@ int virGetUserID(const char *name,
 int virGetGroupID(const char *name,
                   gid_t *gid) ATTRIBUTE_RETURN_CHECK;
 
-char *virFileFindMountPoint(const char *type);
-
-void virFileWaitForDevices(void);
-
-# define virBuildPath(path, ...) virBuildPathInternal(path, __VA_ARGS__, NULL)
-int virBuildPathInternal(char **path, ...) ATTRIBUTE_SENTINEL;
-
 bool virIsDevMapperDevice(const char *dev_name) ATTRIBUTE_NONNULL(1);
 
 bool virValidateWWN(const char *wwn);
index e0b606fe4ac777c5f5ae3258b46cde4f1fc38f28..121382c1c28e6f1290f778c52613110228450be9 100644 (file)
@@ -41,6 +41,7 @@
 #include "virutil.h"
 #include "virlog.h"
 #include "virerror.h"
+#include "virfile.h"
 #include "virstring.h"
 
 #define VIR_FROM_THIS VIR_FROM_VBOX
index 6eac1fa01e66b542934b5410e4eb3b9e6b7176a2..5464d1330efcc8c9ff81c02f173d06e3efe36488 100644 (file)
@@ -26,6 +26,7 @@
 
 #include "internal.h"
 #include "virerror.h"
+#include "virfile.h"
 #include "virconf.h"
 #include "viralloc.h"
 #include "virlog.h"
index 66bd28942fda43850a69bd20152fc4dca2f42538..66a6c4cde53df6054aef7b146652cc61fbd202c8 100644 (file)
@@ -36,6 +36,7 @@
 #include <xen/dom0_ops.h>
 
 #include "virerror.h"
+#include "virfile.h"
 #include "datatypes.h"
 #include "xm_internal.h"
 #include "xen_driver.h"
index 16a693c2f656aa0317501e16a2e1c72878fe5510..700ea08f5fd5da8b1b1144cf7840927351d86970 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * eventtest.c: Test the libvirtd event loop impl
  *
- * Copyright (C) 2009, 2011 Red Hat, Inc.
+ * Copyright (C) 2009, 2011-2013 Red Hat, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -28,6 +28,7 @@
 
 #include "testutils.h"
 #include "internal.h"
+#include "virfile.h"
 #include "virthread.h"
 #include "virlog.h"
 #include "virutil.h"
index df8d3d8dbcac6d7a469f2a8449cb9a43f7d5b8b6..e1dd82d15c1334c13243f064a05f728c319e596c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 Red Hat, Inc.
+ * Copyright (C) 2012-2013 Red Hat, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -27,6 +27,7 @@
 #include "virutil.h"
 #include "c-ctype.h"
 #include "virerror.h"
+#include "virfile.h"
 #include "virlog.h"
 #include "virconf.h"
 #include "virstring.h"
index 0d56769cc80f783ee88f0a319031d2ef09a939ee..f276e6d746ba9fa3a0784d96b25e307f736d8eec 100644 (file)
@@ -33,6 +33,7 @@
 #include "viralloc.h"
 #include "virlog.h"
 #include "virerror.h"
+#include "virfile.h"
 #include "security/security_manager.h"
 #include "virstring.h"
 
index 76783960adcc53ff27ee686979d1755b2fba37e9..b659f61d5032210f337d8dd17751397126ef9fa8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 Red Hat, Inc.
+ * Copyright (C) 2011, 2013 Red Hat, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -28,6 +28,7 @@
 #include "virutil.h"
 #include "virerror.h"
 #include "viralloc.h"
+#include "virfile.h"
 #include "virlog.h"
 
 #include "virlockspace.h"
index a52850687d77cbbd10b2a942272cd711e4b13826..1a0cdfafd7dd1ceb342750d3e71728a5e808c86d 100644 (file)
@@ -53,6 +53,7 @@ int bind(int sockfd ATTRIBUTE_UNUSED,
 # include "virutil.h"
 # include "virerror.h"
 # include "viralloc.h"
+# include "virfile.h"
 # include "virlog.h"
 # include "virportallocator.h"
 # include "virstring.h"
index 0016052e3385fbadb029e4c735ad362deaa380e2..fef4b372fc5b1ced5f6f90b018292ba8d5fe265b 100644 (file)
@@ -25,6 +25,7 @@
 #include "testutils.h"
 #include "vircommand.h"
 #include "virerror.h"
+#include "virfile.h"
 #include "virlog.h"
 #include "virstoragefile.h"
 #include "virstring.h"
index 706074faad0ccb3357488143cb7f9a1dd34ac716..f75c572fd9837a642dca85cbebf147ca46eede57 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * virsh-interface.c: Commands to manage host interface
  *
- * Copyright (C) 2005, 2007-2012 Red Hat, Inc.
+ * Copyright (C) 2005, 2007-2013 Red Hat, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -34,6 +34,7 @@
 #include "internal.h"
 #include "virbuffer.h"
 #include "viralloc.h"
+#include "virfile.h"
 #include "virutil.h"
 #include "virxml.h"
 #include "virstring.h"
index 81267bcaa8f3d25484eb78095e1b28e4dbdaa068..a80cbb5a7a419e7ae17524e2bdee9742988fa975 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * virsh-network.c: Commands to manage network
  *
- * Copyright (C) 2005, 2007-2012 Red Hat, Inc.
+ * Copyright (C) 2005, 2007-2013 Red Hat, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -34,6 +34,7 @@
 #include "internal.h"
 #include "virbuffer.h"
 #include "viralloc.h"
+#include "virfile.h"
 #include "virxml.h"
 #include "conf/network_conf.h"
 
index 8fa67fcc865cddbd4c9f432ca918864105a49c17..592fa4439a36f76de72aa4cb437f1932db7e7241 100644 (file)
@@ -34,6 +34,7 @@
 #include "internal.h"
 #include "virbuffer.h"
 #include "viralloc.h"
+#include "virfile.h"
 #include "virxml.h"
 #include "conf/node_device_conf.h"
 
index 3b1e1e4641da2f76f65737605707dec26f64ae54..5a360c2c70348e13d629dcaf72ccdd90ed3178ec 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * virsh-nwfilter.c: Commands to manage network filters
  *
- * Copyright (C) 2005, 2007-2012 Red Hat, Inc.
+ * Copyright (C) 2005, 2007-2013 Red Hat, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -34,6 +34,7 @@
 #include "internal.h"
 #include "virbuffer.h"
 #include "viralloc.h"
+#include "virfile.h"
 #include "virutil.h"
 #include "virxml.h"
 
index f154366b396999e17927f50cd5fd05913693e0af..c5944aea327573d721a4183d4622f319bd0cbd4e 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * virsh-pool.c: Commands to manage storage pool
  *
- * Copyright (C) 2005, 2007-2012 Red Hat, Inc.
+ * Copyright (C) 2005, 2007-2013 Red Hat, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -34,6 +34,7 @@
 #include "internal.h"
 #include "virbuffer.h"
 #include "viralloc.h"
+#include "virfile.h"
 #include "virxml.h"
 #include "conf/storage_conf.h"
 #include "virstring.h"
index 72015229dfeb1eaf5666790526ee65e1d3165fce..044629dcf331669d3b2f4c429777d85b3d1c71a9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * virsh-secret.c: Commands to manage secret
  *
- * Copyright (C) 2005, 2007-2012 Red Hat, Inc.
+ * Copyright (C) 2005, 2007-2013 Red Hat, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -35,6 +35,7 @@
 #include "base64.h"
 #include "virbuffer.h"
 #include "viralloc.h"
+#include "virfile.h"
 #include "virutil.h"
 #include "virxml.h"
 
index 4f5fa156da51a29cc2606e3388474b4e9cbc1e7f..7e7577276cf18255d60031a4ea0b604932dc174a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * virsh-snapshot.c: Commands to manage domain snapshot
  *
- * Copyright (C) 2005, 2007-2012 Red Hat, Inc.
+ * Copyright (C) 2005, 2007-2013 Red Hat, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -36,6 +36,7 @@
 #include "internal.h"
 #include "virbuffer.h"
 #include "viralloc.h"
+#include "virfile.h"
 #include "virsh-domain.h"
 #include "virxml.h"
 #include "conf/snapshot_conf.h"