[libvirt] [PATCH] Use XDG Base Directories instead of storing in home directory

William Jon McCann william.jon.mccann at gmail.com
Tue May 1 13:52:11 UTC 2012


Sorry for the noise. Please disregard. Apparently I don't know how to
use git-email.

On Tue, May 1, 2012 at 9:39 AM, William Jon McCann
<william.jon.mccann at gmail.com> wrote:
> ---
>  daemon/libvirtd-config.c       |   10 +--
>  daemon/libvirtd.c              |  110 +++++++++++++++++++++++-------
>  daemon/libvirtd.pod.in         |    2 +-
>  docs/auth.html.in              |    2 +-
>  docs/uri.html.in               |    2 +-
>  src/libvirt.c                  |    4 +-
>  src/libvirt_private.syms       |    5 ++
>  src/network/bridge_driver.c    |    8 ++-
>  src/nwfilter/nwfilter_driver.c |   11 +--
>  src/qemu/qemu_driver.c         |   32 ++++++---
>  src/remote/remote_driver.c     |    4 +-
>  src/remote/remote_driver.h     |    2 +-
>  src/secret/secret_driver.c     |   11 +--
>  src/storage/storage_driver.c   |   13 +---
>  src/uml/uml_driver.c           |   10 +--
>  src/util/util.c                |  145 ++++++++++++++++++++++++++++++++++++++++
>  src/util/util.h                |    6 ++
>  src/util/virauth.c             |    4 +-
>  tools/virsh.c                  |    6 +-
>  19 files changed, 298 insertions(+), 89 deletions(-)
>
> diff --git a/daemon/libvirtd-config.c b/daemon/libvirtd-config.c
> index 471236c..8b95969 100644
> --- a/daemon/libvirtd-config.c
> +++ b/daemon/libvirtd-config.c
> @@ -205,16 +205,16 @@ daemonConfigFilePath(bool privileged, char **configfile)
>         if (!(*configfile = strdup(SYSCONFDIR "/libvirt/libvirtd.conf")))
>             goto no_memory;
>     } else {
> -        char *userdir = NULL;
> +        char *configdir = NULL;
>
> -        if (!(userdir = virGetUserDirectory(geteuid())))
> +        if (!(configdir = virGetUserConfigDirectory(geteuid())))
>             goto error;
>
> -        if (virAsprintf(configfile, "%s/.libvirt/libvirtd.conf", userdir) < 0) {
> -            VIR_FREE(userdir);
> +        if (virAsprintf(configfile, "%s/libvirtd.conf", configdir) < 0) {
> +            VIR_FREE(configdir);
>             goto no_memory;
>         }
> -        VIR_FREE(userdir);
> +        VIR_FREE(configdir);
>     }
>
>     return 0;
> diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c
> index b098f6a..f98ba6f 100644
> --- a/daemon/libvirtd.c
> +++ b/daemon/libvirtd.c
> @@ -239,17 +239,20 @@ daemonPidFilePath(bool privileged,
>         if (!(*pidfile = strdup(LOCALSTATEDIR "/run/libvirtd.pid")))
>             goto no_memory;
>     } else {
> -        char *userdir = NULL;
> +        char *rundir = NULL;
>
> -        if (!(userdir = virGetUserDirectory(geteuid())))
> +        if (!(rundir = virGetUserRuntimeDirectory(geteuid())))
>             goto error;
>
> -        if (virAsprintf(pidfile, "%s/.libvirt/libvirtd.pid", userdir) < 0) {
> -            VIR_FREE(userdir);
> +        if (virFileMakePathWithParents (rundir, 0700) != 0)
> +            goto error;
> +
> +        if (virAsprintf(pidfile, "%s/libvirtd.pid", rundir) < 0) {
> +            VIR_FREE(rundir);
>             goto no_memory;
>         }
>
> -        VIR_FREE(userdir);
> +        VIR_FREE(rundir);
>     }
>
>     return 0;
> @@ -279,17 +282,20 @@ daemonUnixSocketPaths(struct daemonConfig *config,
>             if (!(*rosockfile = strdup(LOCALSTATEDIR "/run/libvirt/libvirt-sock-ro")))
>                 goto no_memory;
>         } else {
> -            char *userdir = NULL;
> +            char *rundir = NULL;
> +
> +            if (!(rundir = virGetUserRuntimeDirectory(geteuid())))
> +                goto error;
>
> -            if (!(userdir = virGetUserDirectory(geteuid())))
> +            if (virFileMakePathWithParents (rundir, 0700) != 0)
>                 goto error;
>
> -            if (virAsprintf(sockfile, "@%s/.libvirt/libvirt-sock", userdir) < 0) {
> -                VIR_FREE(userdir);
> +            if (virAsprintf(sockfile, "@%s/libvirt-sock", rundir) < 0) {
> +                VIR_FREE(rundir);
>                 goto no_memory;
>             }
>
> -            VIR_FREE(userdir);
> +            VIR_FREE(rundir);
>         }
>     }
>     return 0;
> @@ -593,16 +599,19 @@ daemonSetupLogging(struct daemonConfig *config,
>                                 LOCALSTATEDIR) == -1)
>                     goto no_memory;
>             } else {
> -                char *userdir = virGetUserDirectory(geteuid());
> -                if (!userdir)
> +                char *logdir = virGetUserCacheDirectory(geteuid());
> +                if (!logdir)
>                     goto error;
>
> -                if (virAsprintf(&tmp, "%d:file:%s/.libvirt/libvirtd.log",
> -                                virLogGetDefaultPriority(), userdir) == -1) {
> -                    VIR_FREE(userdir);
> +                if (virFileMakePathWithParents (logdir, 0700) != 0)
> +                    goto error;
> +
> +                if (virAsprintf(&tmp, "%d:file:%s/libvirtd.log",
> +                                virLogGetDefaultPriority(), logdir) == -1) {
> +                    VIR_FREE(logdir);
>                     goto no_memory;
>                 }
> -                VIR_FREE(userdir);
> +                VIR_FREE(logdir);
>             }
>         } else {
>             if (virAsprintf(&tmp, "%d:stderr", virLogGetDefaultPriority()) < 0)
> @@ -722,6 +731,59 @@ static int daemonStateInit(virNetServerPtr srv)
>     return 0;
>  }
>
> +static void migrateProfile(void)
> +{
> +    char *old_base = NULL;
> +    char *updated = NULL;
> +    char *home = NULL;
> +    char *xdg_dir = NULL;
> +    char *config_dir = NULL;
> +
> +    home = virGetUserDirectory(geteuid());
> +    if (virAsprintf(&old_base, "%s/.libvirt", home) < 0) {
> +        goto error;
> +    }
> +
> +    /* if the new directory is there or the old one is not: do nothing */
> +    config_dir = virGetUserConfigDirectory(geteuid());
> +    if (!virFileIsDir(old_base) || virFileExists(config_dir)) {
> +        goto error;
> +    }
> +
> +    /* test if we already attempted to migrate first */
> +    if (virAsprintf(&updated, "%s/DEPRECATED-DIRECTORY", old_base) < 0) {
> +        goto error;
> +    }
> +    if (virFileExists(updated)) {
> +        goto error;
> +    }
> +
> +    xdg_dir = strdup(getenv("XDG_CONFIG_HOME"));
> +    if (!xdg_dir || xdg_dir[0] == '\0') {
> +        if (virAsprintf(&xdg_dir, "%s/.config", home) < 0) {
> +            goto error;
> +        }
> +    }
> +
> +    if (virFileMakePathWithParents(xdg_dir, 0700) != 0) {
> +        goto error;
> +    }
> +
> +    if (rename (old_base, config_dir) != 0) {
> +        int fd = creat(updated, 0600);
> +        close(fd);
> +        goto error;
> +    }
> +
> + error:
> +    VIR_FREE(home);
> +    VIR_FREE(old_base);
> +    VIR_FREE(xdg_dir);
> +    VIR_FREE(config_dir);
> +    VIR_FREE(updated);
> +
> +}
> +
>  /* Print command-line usage. */
>  static void
>  daemonUsage(const char *argv0, bool privileged)
> @@ -775,10 +837,10 @@ libvirt management daemon:\n"), argv0);
>   Default paths:\n\
>  \n\
>     Configuration file (unless overridden by -f):\n\
> -      $HOME/.libvirt/libvirtd.conf\n\
> +      $XDG_CONFIG_HOME/libvirt/libvirtd.conf\n\
>  \n\
>     Sockets:\n\
> -      $HOME/.libvirt/libvirt-sock (in UNIX abstract namespace)\n\
> +      $XDG_RUNTIME_HOME/libvirt/libvirt-sock (in UNIX abstract namespace)\n\
>  \n\
>     TLS:\n\
>       CA certificate:     $HOME/.pki/libvirt/cacert.pem\n\
> @@ -786,7 +848,7 @@ libvirt management daemon:\n"), argv0);
>       Server private key: $HOME/.pki/libvirt/serverkey.pem\n\
>  \n\
>     PID file:\n\
> -      $HOME/.libvirt/libvirtd.pid\n\
> +      $XDG_RUNTIME_HOME/libvirt/libvirtd.pid\n\
>  \n"));
>     }
>  }
> @@ -931,6 +993,8 @@ int main(int argc, char **argv) {
>         exit(EXIT_FAILURE);
>     }
>
> +    migrateProfile ();
> +
>     if (config->host_uuid &&
>         virSetHostUUIDStr(config->host_uuid) < 0) {
>         VIR_ERROR(_("invalid host UUID: %s"), config->host_uuid);
> @@ -977,14 +1041,12 @@ int main(int argc, char **argv) {
>     if (privileged) {
>         run_dir = strdup(LOCALSTATEDIR "/run/libvirt");
>     } else {
> -        char *user_dir = virGetUserDirectory(geteuid());
> +        run_dir = virGetUserRuntimeDirectory(geteuid());
>
> -        if (!user_dir) {
> +        if (!run_dir) {
>             VIR_ERROR(_("Can't determine user directory"));
>             goto cleanup;
>         }
> -        ignore_value(virAsprintf(&run_dir, "%s/.libvirt/", user_dir));
> -        VIR_FREE(user_dir);
>     }
>     if (!run_dir) {
>         virReportOOMError();
> @@ -992,7 +1054,7 @@ int main(int argc, char **argv) {
>     }
>
>     old_umask = umask(022);
> -    if (virFileMakePath(run_dir) < 0) {
> +    if (virFileMakePathWithParents(run_dir, 0700) < 0) {
>         char ebuf[1024];
>         VIR_ERROR(_("unable to create rundir %s: %s"), run_dir,
>                   virStrerror(errno, ebuf, sizeof(ebuf)));
> diff --git a/daemon/libvirtd.pod.in b/daemon/libvirtd.pod.in
> index 6e699b8..ea6c37d 100644
> --- a/daemon/libvirtd.pod.in
> +++ b/daemon/libvirtd.pod.in
> @@ -85,7 +85,7 @@ command line using the B<-f>|B<--config> option.
>
>  The sockets libvirtd will use when B<run as root>.
>
> -=item F<$HOME/.libvirt/libvirt-sock>
> +=item F<$XDG_RUNTIME_DIR/libvirt/libvirt-sock>
>
>  The socket libvirtd will use when run as a B<non-root> user.
>
> diff --git a/docs/auth.html.in b/docs/auth.html.in
> index ecff0fc..60e4f11 100644
> --- a/docs/auth.html.in
> +++ b/docs/auth.html.in
> @@ -25,7 +25,7 @@ for the authentication file using the following sequence:
>         variable.</li>
>       <li>The file path specified by the "authfile=/some/file" URI
>         query parameter</li>
> -      <li>The file $HOME/.libvirt/auth.conf</li>
> +      <li>The file $XDG_CONFIG_DIR/libvirt/auth.conf</li>
>       <li>The file /etc/libvirt/auth.conf</li>
>     </ol>
>
> diff --git a/docs/uri.html.in b/docs/uri.html.in
> index 2f76e8f..5812ca9 100644
> --- a/docs/uri.html.in
> +++ b/docs/uri.html.in
> @@ -30,7 +30,7 @@ virConnectPtr conn = virConnectOpenReadOnly (<b>"test:///default"</b>);
>     <p>
>  To simplify life for administrators, it is possible to setup URI aliases in a
>  libvirt client configuration file. The configuration file is <code>/etc/libvirt/libvirt.conf</code>
> -for the root user, or <code>$HOME/.libvirt/libvirt.conf</code> for any unprivileged user.
> +for the root user, or <code>$XDG_CONFIG_DIR/libvirt/libvirt.conf</code> for any unprivileged user.
>  In this file, the following syntax can be used to setup aliases
>     </p>
>
> diff --git a/src/libvirt.c b/src/libvirt.c
> index b01ebba..f467290 100644
> --- a/src/libvirt.c
> +++ b/src/libvirt.c
> @@ -969,11 +969,11 @@ virConnectGetConfigFilePath(void)
>                         SYSCONFDIR) < 0)
>             goto no_memory;
>     } else {
> -        char *userdir = virGetUserDirectory(geteuid());
> +        char *userdir = virGetUserConfigDirectory(geteuid());
>         if (!userdir)
>             goto error;
>
> -        if (virAsprintf(&path, "%s/.libvirt/libvirt.conf",
> +        if (virAsprintf(&path, "%s/libvirt.conf",
>                         userdir) < 0) {
>             VIR_FREE(userdir);
>             goto no_memory;
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index 025816a..c198e36 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -1109,8 +1109,10 @@ virFileFindMountPoint;
>  virFileHasSuffix;
>  virFileIsExecutable;
>  virFileIsLink;
> +virFileIsDir;
>  virFileLinkPointsTo;
>  virFileLock;
> +virFileMakePathWithParents;
>  virFileMakePath;
>  virFileMatchesNameSuffix;
>  virFileOpenAs;
> @@ -1129,6 +1131,9 @@ virGetGroupID;
>  virGetGroupName;
>  virGetHostname;
>  virGetUserDirectory;
> +virGetUserConfigDirectory;
> +virGetUserCacheDirectory;
> +virGetUserRuntimeDirectory;
>  virGetUserID;
>  virGetUserName;
>  virHexToBin;
> diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
> index d82212f..cea87c2 100644
> --- a/src/network/bridge_driver.c
> +++ b/src/network/bridge_driver.c
> @@ -280,18 +280,20 @@ networkStartup(int privileged) {
>         if ((base = strdup (SYSCONFDIR "/libvirt")) == NULL)
>             goto out_of_memory;
>     } else {
> -        char *userdir = virGetUserDirectory(uid);
> +        char *userdir = virGetUserCacheDirectory(uid);
>
>         if (!userdir)
>             goto error;
>
>         if (virAsprintf(&driverState->logDir,
> -                        "%s/.libvirt/qemu/log", userdir) == -1) {
> +                        "%s/qemu/log", userdir) == -1) {
>             VIR_FREE(userdir);
>             goto out_of_memory;
>         }
> +        VIR_FREE(userdir);
>
> -        if (virAsprintf(&base, "%s/.libvirt", userdir) == -1) {
> +        userdir = virGetUserConfigDirectory(uid);
> +        if (virAsprintf(&base, "%s", userdir) == -1) {
>             VIR_FREE(userdir);
>             goto out_of_memory;
>         }
> diff --git a/src/nwfilter/nwfilter_driver.c b/src/nwfilter/nwfilter_driver.c
> index ffb4b5d..3d732ab 100644
> --- a/src/nwfilter/nwfilter_driver.c
> +++ b/src/nwfilter/nwfilter_driver.c
> @@ -87,16 +87,9 @@ nwfilterDriverStartup(int privileged) {
>             goto out_of_memory;
>     } else {
>         uid_t uid = geteuid();
> -        char *userdir = virGetUserDirectory(uid);
> -
> -        if (!userdir)
> +        base = virGetUserConfigDirectory(uid);
> +        if (!base)
>             goto error;
> -
> -        if (virAsprintf(&base, "%s/.libvirt", userdir) == -1) {
> -            VIR_FREE(userdir);
> -            goto out_of_memory;
> -        }
> -        VIR_FREE(userdir);
>     }
>
>     if (virAsprintf(&driverState->configDir,
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index ce31e09..8293a19 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -518,28 +518,38 @@ qemudStartup(int privileged) {
>             goto out_of_memory;
>     } else {
>         uid_t uid = geteuid();
> -        char *userdir = virGetUserDirectory(uid);
> -        if (!userdir)
> +        char *rundir;
> +        char *cachedir;
> +
> +        cachedir = virGetUserCacheDirectory(uid);
> +        if (!cachedir)
>             goto error;
>
>         if (virAsprintf(&qemu_driver->logDir,
> -                        "%s/.libvirt/qemu/log", userdir) == -1) {
> -            VIR_FREE(userdir);
> +                        "%s/qemu/log", cachedir) == -1) {
> +            VIR_FREE(cachedir);
>             goto out_of_memory;
>         }
> -
> -        if (virAsprintf(&base, "%s/.libvirt", userdir) == -1) {
> -            VIR_FREE(userdir);
> +        if (virAsprintf(&qemu_driver->cacheDir, "%s/qemu/cache", cachedir) == -1) {
> +            VIR_FREE(cachedir);
>             goto out_of_memory;
>         }
> -        VIR_FREE(userdir);
> +        VIR_FREE(cachedir);
>
> -        if (virAsprintf(&qemu_driver->stateDir, "%s/qemu/run", base) == -1)
> +        rundir = virGetUserRuntimeDirectory(uid);
> +        if (!rundir)
> +            goto error;
> +        if (virAsprintf(&qemu_driver->stateDir, "%s/qemu/run", rundir) == -1) {
> +            VIR_FREE(rundir);
>             goto out_of_memory;
> +        }
> +        VIR_FREE(rundir);
> +
> +        base = virGetUserConfigDirectory(uid);
> +        if (!base)
> +            goto error;
>         if (virAsprintf(&qemu_driver->libDir, "%s/qemu/lib", base) == -1)
>             goto out_of_memory;
> -        if (virAsprintf(&qemu_driver->cacheDir, "%s/qemu/cache", base) == -1)
> -            goto out_of_memory;
>         if (virAsprintf(&qemu_driver->saveDir, "%s/qemu/save", base) == -1)
>             goto out_of_memory;
>         if (virAsprintf(&qemu_driver->snapshotDir, "%s/qemu/snapshot", base) == -1)
> diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
> index 7863b73..4a9299a 100644
> --- a/src/remote/remote_driver.c
> +++ b/src/remote/remote_driver.c
> @@ -578,12 +578,12 @@ doRemoteOpen (virConnectPtr conn,
>     case trans_unix:
>         if (!sockname) {
>             if (flags & VIR_DRV_OPEN_REMOTE_USER) {
> -                char *userdir = virGetUserDirectory(getuid());
> +                char *userdir = virGetUserRuntimeDirectory(getuid());
>
>                 if (!userdir)
>                     goto failed;
>
> -                if (virAsprintf(&sockname, "@%s" LIBVIRTD_USER_UNIX_SOCKET, userdir) < 0) {
> +                if (virAsprintf(&sockname, "@%s/" LIBVIRTD_USER_UNIX_SOCKET, userdir) < 0) {
>                     VIR_FREE(userdir);
>                     goto out_of_memory;
>                 }
> diff --git a/src/remote/remote_driver.h b/src/remote/remote_driver.h
> index 1504eec..aca9412 100644
> --- a/src/remote/remote_driver.h
> +++ b/src/remote/remote_driver.h
> @@ -37,7 +37,7 @@ unsigned long remoteVersion(void);
>  # define LIBVIRTD_TCP_PORT "16509"
>  # define LIBVIRTD_PRIV_UNIX_SOCKET LOCALSTATEDIR "/run/libvirt/libvirt-sock"
>  # define LIBVIRTD_PRIV_UNIX_SOCKET_RO LOCALSTATEDIR "/run/libvirt/libvirt-sock-ro"
> -# define LIBVIRTD_USER_UNIX_SOCKET "/.libvirt/libvirt-sock"
> +# define LIBVIRTD_USER_UNIX_SOCKET "libvirt-sock"
>  # define LIBVIRTD_CONFIGURATION_FILE SYSCONFDIR "/libvirtd.conf"
>
>  /* Defaults for PKI directory. */
> diff --git a/src/secret/secret_driver.c b/src/secret/secret_driver.c
> index 088a243..f3fcce2 100644
> --- a/src/secret/secret_driver.c
> +++ b/src/secret/secret_driver.c
> @@ -1013,16 +1013,9 @@ secretDriverStartup(int privileged)
>             goto out_of_memory;
>     } else {
>         uid_t uid = geteuid();
> -        char *userdir = virGetUserDirectory(uid);
> -
> -        if (!userdir)
> +        base = virGetUserConfigDirectory(uid);
> +        if (!base)
>             goto error;
> -
> -        if (virAsprintf(&base, "%s/.libvirt", userdir) == -1) {
> -            VIR_FREE(userdir);
> -            goto out_of_memory;
> -        }
> -        VIR_FREE(userdir);
>     }
>     if (virAsprintf(&driverState->directory, "%s/secrets", base) == -1)
>         goto out_of_memory;
> diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c
> index f23ec7e..fd762c0 100644
> --- a/src/storage/storage_driver.c
> +++ b/src/storage/storage_driver.c
> @@ -146,19 +146,12 @@ storageDriverStartup(int privileged)
>             goto out_of_memory;
>     } else {
>         uid_t uid = geteuid();
> -        char *userdir = virGetUserDirectory(uid);
> -
> -        if (!userdir)
> +        base = virGetUserConfigDirectory(uid);
> +        if (!base)
>             goto error;
> -
> -        if (virAsprintf(&base, "%s/.libvirt", userdir) == -1) {
> -            VIR_FREE(userdir);
> -            goto out_of_memory;
> -        }
> -        VIR_FREE(userdir);
>     }
>
> -    /* Configuration paths are either ~/.libvirt/storage/... (session) or
> +    /* Configuration paths are either $USER_CONFIG_HOME/libvirt/storage/... (session) or
>      * /etc/libvirt/storage/... (system).
>      */
>     if (virAsprintf(&driverState->configDir,
> diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c
> index 4e640ff..8a39d73 100644
> --- a/src/uml/uml_driver.c
> +++ b/src/uml/uml_driver.c
> @@ -434,12 +434,12 @@ umlStartup(int privileged)
>                         "%s/run/libvirt/uml-guest", LOCALSTATEDIR) == -1)
>             goto out_of_memory;
>     } else {
> +        base = virGetUserConfigDirectory(uid);
> +        if (!base)
> +            goto error;
>
>         if (virAsprintf(&uml_driver->logDir,
> -                        "%s/.libvirt/uml/log", userdir) == -1)
> -            goto out_of_memory;
> -
> -        if (virAsprintf(&base, "%s/.libvirt", userdir) == -1)
> +                        "%s/uml/log", base) == -1)
>             goto out_of_memory;
>
>         if (virAsprintf(&uml_driver->monitorDir,
> @@ -447,7 +447,7 @@ umlStartup(int privileged)
>             goto out_of_memory;
>     }
>
> -    /* Configuration paths are either ~/.libvirt/uml/... (session) or
> +    /* Configuration paths are either $XDG_CONFIG_HOME/libvirt/uml/... (session) or
>      * /etc/libvirt/uml/... (system).
>      */
>     if (virAsprintf(&uml_driver->configDir, "%s/uml", base) == -1)
> diff --git a/src/util/util.c b/src/util/util.c
> index 48358b2..bb3703c 100644
> --- a/src/util/util.c
> +++ b/src/util/util.c
> @@ -665,6 +665,12 @@ char *virFindFileInPath(const char *file)
>     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;
> @@ -1271,6 +1277,67 @@ static int virFileMakePathHelper(char *path)
>  }
>
>  /**
> + * Creates the given directory with mode if it's not already existing.
> + *
> + * Returns 0 on success, or -1 if an error occurred (in which case, errno
> + * is set appropriately).
> + */
> +int virFileMakePathWithParents (const char *pathname,
> +                                int         mode)
> +{
> +    char *fn, *p;
> +
> +    if (pathname == NULL || *pathname == '\0') {
> +        errno = EINVAL;
> +        return -1;
> +    }
> +
> +    fn = strdup(pathname);
> +
> +    if (fn[0] == '/') {
> +        /* Skip initial slashes */
> +        p = fn;
> +        while (p[0] == '/')
> +            p++;
> +    } else {
> +        p = fn;
> +    }
> +
> +    do {
> +        while (*p && *p != '/')
> +            p++;
> +
> +        if (!*p)
> +            p = NULL;
> +        else
> +            *p = '\0';
> +
> +        if (access(fn, F_OK) != 0) {
> +            if (mkdir(fn, mode) == -1 && errno != EEXIST) {
> +                int errno_save = errno;
> +                free(fn);
> +                errno = errno_save;
> +                return -1;
> +            }
> +        } else if (!virFileIsDir(fn)) {
> +            free(fn);
> +            errno = ENOTDIR;
> +            return -1;
> +        }
> +
> +        if (p) {
> +            *p++ = '/';
> +            while (*p && *p == '/')
> +                p++;
> +        }
> +    } while (p);
> +
> +    free(fn);
> +
> +    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
> @@ -2304,6 +2371,84 @@ char *virGetUserDirectory(uid_t uid)
>     return virGetUserEnt(uid, VIR_USER_ENT_DIRECTORY);
>  }
>
> +char *virGetUserConfigDirectory(uid_t uid)
> +{
> +    char *path = NULL;
> +    virBuffer buf = VIR_BUFFER_INITIALIZER;
> +
> +    if (uid == getuid ())
> +        path = getenv("XDG_CONFIG_HOME");
> +
> +    if (path && path[0]) {
> +        virBufferAsprintf(&buf, "%s/libvirt/", path);
> +    } else {
> +        char *home;
> +        home = virGetUserEnt(uid, VIR_USER_ENT_DIRECTORY);
> +        virBufferAsprintf(&buf, "%s/.config/libvirt/", home);
> +        VIR_FREE(home);
> +    }
> +    VIR_FREE(path);
> +
> +    if (virBufferError(&buf)) {
> +        virBufferFreeAndReset(&buf);
> +        virReportOOMError();
> +        return NULL;
> +    }
> +
> +    return virBufferContentAndReset(&buf);
> +}
> +
> +char *virGetUserCacheDirectory(uid_t uid)
> +{
> +    char *path = NULL;
> +    virBuffer buf = VIR_BUFFER_INITIALIZER;
> +
> +    if (uid == getuid ())
> +        path = getenv("XDG_CACHE_HOME");
> +
> +    if (path && path[0]) {
> +        virBufferAsprintf(&buf, "%s/libvirt/", path);
> +    } else {
> +        char *home;
> +        home = virGetUserEnt(uid, VIR_USER_ENT_DIRECTORY);
> +        virBufferAsprintf(&buf, "%s/.cache/libvirt/", home);
> +        VIR_FREE(home);
> +    }
> +    VIR_FREE(path);
> +
> +    if (virBufferError(&buf)) {
> +        virBufferFreeAndReset(&buf);
> +        virReportOOMError();
> +        return NULL;
> +    }
> +
> +    return virBufferContentAndReset(&buf);
> +}
> +
> +char *virGetUserRuntimeDirectory(uid_t uid)
> +{
> +    char *path = NULL;
> +    virBuffer buf = VIR_BUFFER_INITIALIZER;
> +
> +    if (uid == getuid ())
> +        path = getenv("XDG_RUNTIME_DIR");
> +
> +    if (!path || !path[0]) {
> +        return virGetUserCacheDirectory(uid);
> +    } else {
> +        virBufferAsprintf(&buf, "%s/libvirt/", path);
> +        VIR_FREE(path);
> +
> +        if (virBufferError(&buf)) {
> +            virBufferFreeAndReset(&buf);
> +            virReportOOMError();
> +            return NULL;
> +        }
> +
> +        return virBufferContentAndReset(&buf);
> +    }
> +}
> +
>  char *virGetUserName(uid_t uid)
>  {
>     return virGetUserEnt(uid, VIR_USER_ENT_NAME);
> diff --git a/src/util/util.h b/src/util/util.h
> index 85e8bd6..5c87a49 100644
> --- a/src/util/util.h
> +++ b/src/util/util.h
> @@ -85,6 +85,7 @@ int virFileIsLink(const char *linkpath)
>
>  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);
>
> @@ -114,6 +115,8 @@ enum {
>  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 virFileMakePathWithParents (const char *pathname,
> +                            int         mode) ATTRIBUTE_RETURN_CHECK;
>
>  char *virFileBuildPath(const char *dir,
>                        const char *name,
> @@ -228,6 +231,9 @@ char *virGetHostname(virConnectPtr conn);
>  int virKillProcess(pid_t pid, int sig);
>
>  char *virGetUserDirectory(uid_t uid);
> +char *virGetUserConfigDirectory(uid_t uid);
> +char *virGetUserCacheDirectory(uid_t uid);
> +char *virGetUserRuntimeDirectory(uid_t uid);
>  char *virGetUserName(uid_t uid);
>  char *virGetGroupName(gid_t gid);
>  int virGetUserID(const char *name,
> diff --git a/src/util/virauth.c b/src/util/virauth.c
> index c59c55a..92ecb7c 100644
> --- a/src/util/virauth.c
> +++ b/src/util/virauth.c
> @@ -65,10 +65,10 @@ int virAuthGetConfigFilePath(virConnectPtr conn,
>         }
>     }
>
> -    if (!(userdir = virGetUserDirectory(geteuid())))
> +    if (!(userdir = virGetUserConfigDirectory(geteuid())))
>         goto cleanup;
>
> -    if (virAsprintf(path, "%s/.libvirt/auth.conf", userdir) < 0)
> +    if (virAsprintf(path, "%s/auth.conf", userdir) < 0)
>         goto no_memory;
>
>     VIR_DEBUG("Checking for readability of '%s'", *path);
> diff --git a/tools/virsh.c b/tools/virsh.c
> index e177684..ee14c02 100644
> --- a/tools/virsh.c
> +++ b/tools/virsh.c
> @@ -19863,15 +19863,15 @@ vshReadlineInit(vshControl *ctl)
>     /* Limit the total size of the history buffer */
>     stifle_history(500);
>
> -    /* Prepare to read/write history from/to the ~/.virsh/history file */
> -    userdir = virGetUserDirectory(getuid());
> +    /* Prepare to read/write history from/to the $XDG_CACHE_HOME/virsh/history file */
> +    userdir = virGetUserCacheDirectory(getuid());
>
>     if (userdir == NULL) {
>         vshError(ctl, "%s", _("Could not determine home directory"));
>         return -1;
>     }
>
> -    if (virAsprintf(&ctl->historydir, "%s/.virsh", userdir) < 0) {
> +    if (virAsprintf(&ctl->historydir, "%s/virsh", userdir) < 0) {
>         vshError(ctl, "%s", _("Out of memory"));
>         VIR_FREE(userdir);
>         return -1;
> --
> 1.7.10
>




More information about the libvir-list mailing list