From mboxrd@z Thu Jan 1 00:00:00 1970 From: Ian Jackson Subject: [PATCH 05/20] libxl: provide libxl__remove_file et al. Date: Fri, 13 Apr 2012 19:39:59 +0100 Message-ID: <1334342414-10289-6-git-send-email-ian.jackson@eu.citrix.com> References: <1334342414-10289-1-git-send-email-ian.jackson@eu.citrix.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <1334342414-10289-1-git-send-email-ian.jackson@eu.citrix.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: xen-devel@lists.xen.org Cc: Ian Jackson List-Id: xen-devel@lists.xenproject.org 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 --- 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 abc38fb..3996824 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..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