]> xenbits.xensource.com Git - people/liuw/libxenctrl-split/libvirt.git/commitdiff
Introduce a virFileDeleteTree method
authorDaniel P. Berrange <berrange@redhat.com>
Thu, 28 Mar 2013 14:46:45 +0000 (14:46 +0000)
committerDaniel P. Berrange <berrange@redhat.com>
Mon, 15 Apr 2013 16:35:31 +0000 (17:35 +0100)
Introduce a method virFileDeleteTree for recursively deleting
an entire directory tree

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
src/libvirt_private.syms
src/util/virfile.c
src/util/virfile.h

index 8d8d56d2e9e0276de71bcccf574dba28eceb4532..ee4273585185fe14c68494f994f230df1ecc76ed 100644 (file)
@@ -1264,6 +1264,7 @@ virEventPollUpdateTimeout;
 
 # util/virfile.h
 virFileClose;
+virFileDeleteTree;
 virFileDirectFdFlag;
 virFileFclose;
 virFileFdopen;
index 4a9fa811b2bc8c478d8ff5b8ad0b432ad8ac2edf..fbaeeddbe8972cd0314f825b0b3dc549fa0c332a 100644 (file)
@@ -644,3 +644,86 @@ int virFileLoopDeviceAssociate(const char *file,
 }
 
 #endif /* __linux__ */
+
+
+/**
+ * virFileDeleteTree:
+ *
+ * Recursively deletes all files / directories
+ * starting from the directory @dir. Does not
+ * follow symlinks
+ *
+ * NB the algorithm is not efficient, and is subject to
+ * race conditions which can be exploited by malicious
+ * code. It should not be used in any scenarios where
+ * performance is important, or security is critical.
+ */
+int virFileDeleteTree(const char *dir)
+{
+    DIR *dh = opendir(dir);
+    struct dirent *de;
+    char *filepath = NULL;
+    int ret = -1;
+
+    if (!dh) {
+        virReportSystemError(errno, _("Cannot open dir '%s'"),
+                             dir);
+        return -1;
+    }
+
+    errno = 0;
+    while ((de = readdir(dh)) != NULL) {
+        struct stat sb;
+
+        if (STREQ(de->d_name, ".") ||
+            STREQ(de->d_name, ".."))
+            continue;
+
+        if (virAsprintf(&filepath, "%s/%s",
+                        dir, de->d_name) < 0) {
+            virReportOOMError();
+            goto cleanup;
+        }
+
+        if (lstat(filepath, &sb) < 0) {
+            virReportSystemError(errno, _("Cannot access '%s'"),
+                                 filepath);
+            goto cleanup;
+        }
+
+        if (S_ISDIR(sb.st_mode)) {
+            if (virFileDeleteTree(filepath) < 0)
+                goto cleanup;
+        } else {
+            if (unlink(filepath) < 0 && errno != ENOENT) {
+                virReportSystemError(errno,
+                                     _("Cannot delete file '%s'"),
+                                     filepath);
+                goto cleanup;
+            }
+        }
+
+        VIR_FREE(filepath);
+        errno = 0;
+    }
+
+    if (errno) {
+        virReportSystemError(errno, _("Cannot read dir '%s'"),
+                             dir);
+        goto cleanup;
+    }
+
+    if (rmdir(dir) < 0 && errno != ENOENT) {
+        virReportSystemError(errno,
+                             _("Cannot delete directory '%s'"),
+                             dir);
+        goto cleanup;
+    }
+
+    ret = 0;
+
+cleanup:
+    VIR_FREE(filepath);
+    closedir(dh);
+    return ret;
+}
index c885b73c365fab39aa39aa7c6882e4306cd0764e..5f0dd2ba2a3553c0fc045bd8c307cb6b590b557e 100644 (file)
@@ -108,4 +108,6 @@ int virFileUpdatePerm(const char *path,
 int virFileLoopDeviceAssociate(const char *file,
                                char **dev);
 
+int virFileDeleteTree(const char *dir);
+
 #endif /* __VIR_FILES_H */