[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH 24/31] libxl: provide libxl__remove_file et al.



On Tue, 2012-04-10 at 20:07 +0100, Ian Jackson wrote:
> These utility functions cope with EINTR AND ENOENT, do error logging,
> and we provide a recursive version to delete whole directory trees.
> 
> Signed-off-by: Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
> ---
>  tools/libxl/libxl_internal.h |    7 ++++
>  tools/libxl/libxl_utils.c    |   79 
> ++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 86 insertions(+), 0 deletions(-)
> 
> diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
> index a60171c..8e47213 100644
> --- a/tools/libxl/libxl_internal.h
> +++ b/tools/libxl/libxl_internal.h
> @@ -442,6 +442,13 @@ _hidden char *libxl__strndup(libxl__gc *gc_opt, const 
> char *c, size_t n);
>   * string. (similar to a gc'd dirname(3)). */
>  _hidden char *libxl__dirname(libxl__gc *gc_opt, const char *s);
>  
> +/* Each of these logs errors and returns a libxl error code.
> + * They do not mind if path is already removed.
> + * For _file, path must not be a directory; for _directory it must be. */
> +_hidden int libxl__remove_file(libxl__gc *gc, const char *path);
> +_hidden int libxl__remove_directory(libxl__gc *gc, const char *path);
> +_hidden int libxl__remove_file_or_directory(libxl__gc *gc, const char *path);
> +
>  _hidden char **libxl__xs_kvs_of_flexarray(libxl__gc *gc, flexarray_t *array, 
> int length);
>  
>  _hidden int libxl__xs_writev(libxl__gc *gc, xs_transaction_t t,
> diff --git a/tools/libxl/libxl_utils.c b/tools/libxl/libxl_utils.c
> index 0cbd85e..c9157a6 100644
> --- a/tools/libxl/libxl_utils.c
> +++ b/tools/libxl/libxl_utils.c
> @@ -364,6 +364,85 @@ int libxl_read_file_contents(libxl_ctx *ctx, const char 
> *filename,
>  READ_WRITE_EXACTLY(read, 1, /* */)
>  READ_WRITE_EXACTLY(write, 0, const)
>  
> +int libxl__remove_file(libxl__gc *gc, const char *path)
> +{
> +    for (;;) {
> +        int r = unlink(path);
> +        if (!r) return 0;
> +        if (errno == ENOENT) return 0;
> +        if (errno == EINTR) continue;
> +        LOGE(ERROR, "failed to remove file %s", path);
> +        return ERROR_FAIL;
> +     }
> +}
> +
> +int libxl__remove_file_or_directory(libxl__gc *gc, const char *path)
> +{
> +    for (;;) {
> +        int r = rmdir(path);
> +        if (!r) return 0;
> +        if (errno == ENOENT) return 0;
> +        if (errno == ENOTEMPTY) return libxl__remove_directory(gc, path);
> +        if (errno == ENOTDIR) return libxl__remove_file(gc, path);
> +        if (errno == EINTR) continue;

starting to look a bit like a switch statement...

> +        LOGE(ERROR, "failed to remove %s", path);
> +        return ERROR_FAIL;
> +     }
> +}
> +
> +int libxl__remove_directory(libxl__gc *gc, const char *dirpath)
> +{
> +    int rc = 0;
> +    DIR *d = 0;
> +
> +    d = opendir(dirpath);
> +    if (!d) {
> +        if (errno == ENOENT)
> +            goto out;
> +
> +        LOGE(ERROR, "failed to opendir %s for removal", dirpath);
> +        rc = ERROR_FAIL;
> +        goto out;
> +    }
> +
> +    size_t need = offsetof(struct dirent, d_name) +
> +        pathconf(dirpath, _PC_NAME_MAX) + 1;
> +    struct dirent *de_buf = libxl__zalloc(gc, need);
> +    struct dirent *de;
> +
> +    for (;;) {
> +        int r = readdir_r(d, de_buf, &de);
> +        if (r) {
> +            LOGE(ERROR, "failed to readdir %s for removal", dirpath);
> +            rc = ERROR_FAIL;
> +            break;
> +        }
> +        if (!de)
> +            break;
> +
> +        if (!strcmp(de->d_name, ".") ||
> +            !strcmp(de->d_name, ".."))
> +            continue;
> +
> +        const char *subpath = GCSPRINTF("%s/%s", dirpath, de->d_name);
> +        if (libxl__remove_file_or_directory(gc, subpath))
> +            rc = ERROR_FAIL;
> +    }
> +
> +    for (;;) {
> +        int r = rmdir(dirpath);
> +        if (!r) break;
> +        if (errno == ENOENT) return 0;

This misses the closedir() at out?

> +        if (errno == EINTR) continue;
> +        LOGE(ERROR, "failed to remove emptied directory %s", dirpath);
> +        rc = ERROR_FAIL;
> +    }
> +
> + out:
> +    if (d) closedir(d);
> +
> +    return rc;
> +}
>  
>  pid_t libxl_fork(libxl_ctx *ctx)
>  {



_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.