[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] libxl: provide libxl__remove_file et al.
# HG changeset patch # User Ian Jackson <ian.jackson@xxxxxxxxxxxxx> # Date 1336759138 -3600 # Node ID 0856b8d4d80acccf4cf453815a1cb2737d2b9903 # Parent 85bf1c658d98ade6caa0eefa30172c732fc47b40 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> Committed-by: Ian Jackson <Ian.Jackson@xxxxxxxxxxxxx> --- diff -r 85bf1c658d98 -r 0856b8d4d80a tools/libxl/libxl_internal.h --- a/tools/libxl/libxl_internal.h Fri May 11 18:58:57 2012 +0100 +++ b/tools/libxl/libxl_internal.h Fri May 11 18:58:58 2012 +0100 @@ -433,6 +433,13 @@ _hidden char *libxl__strndup(libxl__gc * * 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 -r 85bf1c658d98 -r 0856b8d4d80a tools/libxl/libxl_utils.c --- a/tools/libxl/libxl_utils.c Fri May 11 18:58:57 2012 +0100 +++ b/tools/libxl/libxl_utils.c Fri May 11 18:58:58 2012 +0100 @@ -364,6 +364,85 @@ int libxl_read_file_contents(libxl_ctx * 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) { _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |