Updater: Fix overwriting directories with files

This commit is contained in:
Vicki Pfau 2023-07-16 20:41:48 -07:00
parent 436d6c5a08
commit 52ef584424
3 changed files with 62 additions and 7 deletions

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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;
}