summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/core/slang-io.cpp57
-rw-r--r--source/core/slang-io.h5
2 files changed, 62 insertions, 0 deletions
diff --git a/source/core/slang-io.cpp b/source/core/slang-io.cpp
index ffbb5fa98..dd390fc28 100644
--- a/source/core/slang-io.cpp
+++ b/source/core/slang-io.cpp
@@ -17,6 +17,7 @@
#ifdef _WIN32
# include <direct.h>
# include <windows.h>
+# include <shellapi.h>
#endif
#if defined(__linux__) || defined(__CYGWIN__) || SLANG_APPLE_FAMILY
@@ -27,6 +28,7 @@
# include <dirent.h>
# include <sys/stat.h>
# include <sys/file.h>
+# include <ftw.h> // for nftw
#endif
#if SLANG_APPLE_FAMILY
@@ -777,6 +779,61 @@ namespace Slang
#endif
}
+ /* static */SlangResult Path::removeNonEmpty(const String& path)
+ {
+ if (File::exists(path) == false)
+ {
+ return SLANG_OK;
+ }
+
+ StringBuilder msgBuilder;
+ // Path::remove() doesn't support remove a non-empty directory, so we need to implement
+ // a simple function to remove the directory recursively.
+#ifdef _WIN32
+ // https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shfileoperationa
+ // Note: the fromPath requires a double-null-terminated string.
+ String newPath = path;
+ newPath.append('\0');
+ SHFILEOPSTRUCTA file_op = {
+ NULL,
+ FO_DELETE,
+ newPath.begin(),
+ nullptr,
+ FOF_NOCONFIRMATION |
+ FOF_NOERRORUI |
+ FOF_SILENT,
+ false,
+ 0,
+ nullptr };
+ int ret = SHFileOperationA(&file_op);
+ if (ret)
+ {
+ return SLANG_FAIL;
+ }
+#else
+ auto unlink_cb = [](const char* fpath, const struct stat* sb, int typeflag, struct FTW* ftwbuf) -> int
+ {
+ SLANG_UNUSED(sb)
+ SLANG_UNUSED(typeflag)
+ SLANG_UNUSED(ftwbuf)
+ int rv = ::remove(fpath);
+ if (rv)
+ {
+ perror(fpath);
+ }
+ return rv;
+ };
+ // https://linux.die.net/man/3/nftw
+ int ret = ::nftw(path.begin(), unlink_cb, 64, FTW_DEPTH | FTW_PHYS);
+ if (ret)
+ {
+ return SLANG_FAIL;
+ }
+#endif
+
+ return SLANG_OK;
+ }
+
#if defined(_WIN32)
/* static */SlangResult Path::find(const String& directoryPath, const char* pattern, Visitor* visitor)
{
diff --git a/source/core/slang-io.h b/source/core/slang-io.h
index 763907c98..676635a36 100644
--- a/source/core/slang-io.h
+++ b/source/core/slang-io.h
@@ -217,6 +217,11 @@ namespace Slang
/// @return SLANG_OK if file or directory is removed
static SlangResult remove(const String& path);
+ /// Remove a file or directory at specified path. The directory can be non-empty.
+ /// @param path
+ /// @return SLANG_OK if file or directory is removed
+ static SlangResult removeNonEmpty(const String& path);
+
static bool equals(String path1, String path2);
/// Turn `path` into a relative path from base.