[libvirt] [PATCH] Fix return value semantic of virFileMakePath

Eric Blake eblake at redhat.com
Tue Jul 5 22:16:31 UTC 2011


On 07/05/2011 03:04 PM, Matthias Bolte wrote:
> Some callers expected virFileMakePath to set errno, some expected
> it to return an errno value. Unify this to return 0 on success and
> -1 on error. Set errno to report detailed error information.
> 
> Also Make virFileMakePath report an error when stat fails with an
> errno different from ENOENT.

When I first read this, I thought that you meant that virFileMakePath
would use virReportSystemError, but only on that particular failure
path.  But on reading the patch, I see that you merely meant that this
patch now guarantees that virFileMakePath returns -1 for errno different
than ENOENT right away, rather than wasting time calling strdup and
eventually mkdir and possibly having the errno from mkdir be less
specific than the errno from the initial failed stat.  So maybe reword
this as:

Also optimize virFileMakePath if stat fails with an errno different from
ENOENT.

> @@ -429,8 +429,8 @@ static int lxcContainerMountBasicFS(virDomainFSDefPtr root)
>          }
>      }
>  
> -    if ((rc = virFileMakePath("/dev/pts") != 0)) {
> -        virReportSystemError(rc, "%s",
> +    if (virFileMakePath("/dev/pts") < 0) {
> +        virReportSystemError(errno, "%s",

Nice bug fix, by the way.  Matthias had to point out to me on IRC that
the parenthesis were wrong, and that virFileMakePAth("/dev/pts") != 0
ended up making rc only 0 or 1, rather than 0 or an errno value, making
for a misleading virReportSystemError output pre-patch.

> +++ b/src/util/util.c
> @@ -1010,66 +1010,80 @@ int virDirCreate(const char *path ATTRIBUTE_UNUSED,
>  }
>  #endif /* WIN32 */
>  
> -static int virFileMakePathHelper(char *path) {
> +static int virFileMakePathHelper(char *path)
> +{
>      struct stat st;
>      char *p = NULL;
> -    int err;
>  
>      if (stat(path, &st) >= 0)
>          return 0;
> +    else if (errno != ENOENT)
> +        return -1;

The 'else' isn't strictly necessary.  And as long as we are taking
shortcuts, should we use this instead?

if (stat(path, &st) >= 0) {
    if (S_ISDIR(st.st_mode))
        return 0;
    errno = ENOTDIR;
    return -1;
}
if (errno != ENOENT)
    return -1;

> +/**
> + * Creates the given path with mode 0777 if it's not already existing

I probably would do s/path/directory/, although it's not critical to
this patch.

> + * completely.
> + *
> + * Returns 0 on success, or -1 if an error occurred (in which case, errno
> + * is set appropriately).
> + */
>  int virFileMakePath(const char *path)
>  {
> +    int ret = -1;
>      struct stat st;
>      char *parent = NULL;
>      char *p;
> -    int err = 0;
>  
>      if (stat(path, &st) >= 0)
> +        return 0;
> +    else if (errno != ENOENT)
>          goto cleanup;

Same shortcut question as for virFileMakePathHelper.

>  
>      if ((parent = strdup(path)) == NULL) {
> -        err = ENOMEM;
> +        errno = ENOMEM;
>          goto cleanup;
>      }

At this point, why don't we just call virFileMakePathHelper, rather than...

>  
>      if ((p = strrchr(parent, '/')) == NULL) {
> -        err = EINVAL;
> +        errno = EINVAL;
>          goto cleanup;
>      }
>  
>      if (p != parent) {
>          *p = '\0';
> -        if ((err = virFileMakePathHelper(parent)) != 0) {
> +
> +        if (virFileMakePathHelper(parent) < 0)
>              goto cleanup;
> -        }
>      }
>  
> -    if (mkdir(path, 0777) < 0 && errno != EEXIST) {
> -        err = errno;
> +    if (mkdir(path, 0777) < 0 && errno != EEXIST)
>          goto cleanup;
> -    }

...copying the same code for the strrchr, recursion, and mkdir
ourselves?  For that matter, even the initial stat() could be skipped,
and have this function be _just_ the strdup and call into the recursive
helper.

On the other hand, that could be a cleanup for a separate patch; what
you have here is minimally invasive for fixing the problem at hand, so:

ACK.

-- 
Eric Blake   eblake at redhat.com    +1-801-349-2682
Libvirt virtualization library http://libvirt.org

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 619 bytes
Desc: OpenPGP digital signature
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20110705/da19472c/attachment-0001.sig>


More information about the libvir-list mailing list