From 1d37620c8cf77cbe5f4259b59fe1380add639efe Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 16 Jul 2023 20:41:48 -0700 Subject: [PATCH] Updater: Fix overwriting directories with files --- src/feature/updater-main.c | 58 +++++++++++++++++++++++++++++++--- src/platform/windows/vfs-w32.c | 9 ++++-- src/util/vfs/vfs-dirent.c | 2 +- 3 files changed, 62 insertions(+), 7 deletions(-) diff --git a/src/feature/updater-main.c b/src/feature/updater-main.c index cd72fc4f3..becd9c2a3 100644 --- a/src/feature/updater-main.c +++ b/src/feature/updater-main.c @@ -31,6 +31,39 @@ FILE* logfile; +bool rmdirRecursive(struct VDir* dir) { + if (!dir) { + return false; + } + bool ok = true; + struct VDirEntry* vde; + while ((vde = dir->listNext(dir))) { + const char* name = vde->name(vde); + if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) { + continue; + } + switch (vde->type(vde)) { + case VFS_DIRECTORY: + fprintf(logfile, "cd %s\n", name); + if (!rmdirRecursive(dir->openDir(dir, name))) { + ok = false; + } + fprintf(logfile, "cd ..\n"); + // Fall through + case VFS_FILE: + case VFS_UNKNOWN: + fprintf(logfile, "rm %s\n", name); + if (!dir->deleteFile(dir, name)) { + fprintf(logfile, "error\n"); + ok = false; + } + break; + } + } + dir->close(dir); + return ok; +} + bool extractArchive(struct VDir* archive, const char* root, bool prefix) { char path[PATH_MAX] = {0}; struct VDirEntry* vde; @@ -57,11 +90,13 @@ bool extractArchive(struct VDir* archive, const char* root, bool prefix) { case VFS_DIRECTORY: fprintf(logfile, "mkdir %s\n", fname); if (mkdir(path, 0755) < 0 && errno != EEXIST) { + fprintf(logfile, "error %i\n", errno); return false; } if (!prefix) { struct VDir* subdir = archive->openDir(archive, fname); if (!subdir) { + fprintf(logfile, "error\n"); return false; } if (!extractArchive(subdir, path, false)) { @@ -76,13 +111,28 @@ bool extractArchive(struct VDir* archive, const char* root, bool prefix) { vfIn = archive->openFile(archive, vde->name(vde), O_RDONLY); errno = 0; vfOut = VFileOpen(path, O_WRONLY | O_CREAT | O_TRUNC); - if (!vfOut && errno == EACCES) { + if (!vfOut) { + if (errno == EACCES) { #ifdef _WIN32 - Sleep(1000); + Sleep(1000); #else - sleep(1); + sleep(1); #endif - vfOut = VFileOpen(path, O_WRONLY | O_CREAT | O_TRUNC); + vfOut = VFileOpen(path, O_WRONLY | O_CREAT | O_TRUNC); + } else if (errno == EISDIR) { + fprintf(logfile, "rm -r %s\n", path); + if (!rmdirRecursive(VDirOpen(path))) { + return false; + } +#ifdef _WIN32 + wchar_t wpath[MAX_PATH + 1]; + MultiByteToWideChar(CP_UTF8, 0, path, -1, wpath, MAX_PATH); + RemoveDirectoryW(wpath); +#else + rmdir(path); +#endif + vfOut = VFileOpen(path, O_WRONLY | O_CREAT | O_TRUNC); + } } if (!vfOut) { vfIn->close(vfIn); diff --git a/src/platform/windows/vfs-w32.c b/src/platform/windows/vfs-w32.c index bfa2e30a3..b160bc588 100644 --- a/src/platform/windows/vfs-w32.c +++ b/src/platform/windows/vfs-w32.c @@ -151,7 +151,12 @@ bool _vdwDeleteFile(struct VDir* vd, const char* path) { MultiByteToWideChar(CP_UTF8, 0, path, -1, pathw, MAX_PATH); StringCchPrintfW(combined, MAX_PATH, L"%ws\\%ws", dir, pathw); - return DeleteFileW(combined); + DWORD attrs = GetFileAttributesW(combined); + if (attrs & FILE_ATTRIBUTE_DIRECTORY) { + return RemoveDirectoryW(combined); + } else { + return DeleteFileW(combined); + } } const char* _vdweName(struct VDirEntry* vde) { @@ -183,4 +188,4 @@ bool VDirCreate(const char* path) { return true; } return false; -} \ No newline at end of file +} diff --git a/src/util/vfs/vfs-dirent.c b/src/util/vfs/vfs-dirent.c index 610482313..806148b89 100644 --- a/src/util/vfs/vfs-dirent.c +++ b/src/util/vfs/vfs-dirent.c @@ -133,7 +133,7 @@ bool _vdDeleteFile(struct VDir* vd, const char* path) { char* combined = malloc(sizeof(char) * (strlen(path) + strlen(dir) + 2)); sprintf(combined, "%s%s%s", dir, PATH_SEP, path); - bool ret = !unlink(combined); + bool ret = !remove(combined); free(combined); return ret; }