[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 06/27] libxl: provide libxl__remove_file et al.
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> Acked-by: Ian Campbell <ian.campbell@xxxxxxxxxx> --- 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 d04e856..909e01f 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -433,6 +433,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..1a4874c 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; + 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) goto 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) { -- 1.7.2.5 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |