#include "port/win.h" #define WIN32_LEAN_AND_MEAN /* Exclude rarely-used stuff from Windows headers */ #include "windows.h" #include #include #ifdef _LIB #include "postgres.h" #include "miscadmin.h" #endif int win32_rmdir(const char *dirname) { BOOL ans = RemoveDirectory(dirname); if (!ans && GetLastError() == ERROR_DIR_NOT_EMPTY) { /* Blow away the contents recursively and try again */ WIN32_FIND_DATA dir_find_data; char buffer[MAX_PATH*2 + 1]; HANDLE find_handle; strcpy(buffer, dirname); strcat(buffer, "\\*"); ans = TRUE; find_handle = FindFirstFile(buffer, &dir_find_data); while (find_handle && find_handle != INVALID_HANDLE_VALUE) { if (strcmp(dir_find_data.cFileName, ".") != 0 && strcmp(dir_find_data.cFileName, "..") != 0) { strcpy(buffer + strlen(dirname) + 1, dir_find_data.cFileName); if (dir_find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ans = (win32_rmdir(buffer) == 0); else ans = DeleteFile(buffer); } if (!ans || !FindNextFile(find_handle, &dir_find_data)) break; } FindClose(find_handle); ans = ans && RemoveDirectory(dirname); } return (ans ? 0 : -1); } /* Recursively copy srcdir to destdir. Destdir is created * if needed. If destdir exists already but is not a * directory, it is an error. Returns 0 for success, * -1 otherwise. */ int copydir(const char* srcdir, const char* destdir) { WIN32_FIND_DATA dir_find_data; char src_buffer[MAX_PATH*2 + 1]; char dest_buffer[MAX_PATH*2 + 1]; HANDLE find_handle = FindFirstFile(destdir, &dir_find_data); BOOL ans; if (find_handle && (find_handle != INVALID_HANDLE_VALUE)) { /* destdir exists, now make sure it is a directory */ if (dir_find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ans = 1; else ans = 0; FindClose(find_handle); } else { /* Create the destdir */ ans = CreateDirectory(destdir, NULL); } FindClose(find_handle); if (!ans) return -1; /* Get ready to do some copying */ strcpy(src_buffer, srcdir); strcat(src_buffer, "\\*"); strcpy(dest_buffer, destdir); strcat(dest_buffer, "\\"); find_handle = FindFirstFile(src_buffer, &dir_find_data); if (find_handle && find_handle != INVALID_HANDLE_VALUE) { do { if (strcmp(dir_find_data.cFileName, ".") == 0) continue; if (strcmp(dir_find_data.cFileName, "..") == 0) continue; strcpy(src_buffer + strlen(srcdir) + 1, dir_find_data.cFileName); strcpy(dest_buffer + strlen(destdir) + 1, dir_find_data.cFileName); if (dir_find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ans = (copydir(src_buffer, dest_buffer) == 0); else ans = CopyFile(src_buffer, dest_buffer, FALSE); if (!ans) break; } while (FindNextFile(find_handle, &dir_find_data)); FindClose(find_handle); } return (ans ? 0 : -1); } #define VALID_FLAG 0xcade typedef struct { DWORD valid_flag; char dir_name[MAX_PATH + 1]; dirent *dir_info; HANDLE search_handle; } pg_win32_dir_struct; DIR* opendir(const char* name) { WIN32_FIND_DATA dir_find_data; HANDLE file_handle = FindFirstFile(name, &dir_find_data); pg_win32_dir_struct* the_dir = NULL; if (file_handle && (file_handle != INVALID_HANDLE_VALUE)) { FindClose(file_handle); if (dir_find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { /* Found a decent directory -- return it */ the_dir = (pg_win32_dir_struct*)malloc(sizeof(pg_win32_dir_struct)); the_dir->valid_flag = VALID_FLAG; strcpy(the_dir->dir_name, name); strcat(the_dir->dir_name, "/"); the_dir->dir_info = (dirent*)malloc(sizeof(dirent)); the_dir->search_handle = NULL; } } return the_dir; } dirent* readdir(DIR* dir) { WIN32_FIND_DATA find_data; static dirent s_dirent; pg_win32_dir_struct* the_dir = (pg_win32_dir_struct*)dir; if (!the_dir || the_dir->valid_flag != VALID_FLAG) /* Bad user -- gave invalid DIR */ return NULL; if (the_dir->search_handle == NULL) { /* This is the first call */ char buffer[MAX_PATH+1]; HANDLE file_handle; strcpy(buffer, the_dir->dir_name); strcat(buffer, "*"); file_handle = FindFirstFile(buffer, &find_data); if (file_handle && (file_handle != INVALID_HANDLE_VALUE)) { the_dir->search_handle = file_handle; } } else if (!FindNextFile(the_dir->search_handle, &find_data)) { FindClose(the_dir->search_handle); the_dir->search_handle = NULL; } if (the_dir->search_handle) { strcpy(the_dir->dir_info->d_name, find_data.cFileName); the_dir->dir_info->d_type = find_data.dwFileAttributes; return the_dir->dir_info; } else return NULL; } int closedir(DIR* dir) { pg_win32_dir_struct* the_dir = (pg_win32_dir_struct*)dir; if (the_dir && the_dir->valid_flag == VALID_FLAG) { the_dir->valid_flag = -1; if (the_dir->search_handle) FindClose(the_dir->search_handle); free(the_dir->dir_info); the_dir->dir_info = ((dirent*)1); free(the_dir); } return 0; } #ifdef _LIB #define UNLINK_LATER_FILE "pg_win32_unlink_later.data" BOOL win32_save_unlink_for_later(char* filename) { FILE* later_file; char buffer[1024]; int count = 0; sprintf(buffer, "%s/global/%s", DataDir, UNLINK_LATER_FILE); later_file = fopen(buffer, "a+"); while (!later_file && count++ < 5) { Sleep(100); later_file = fopen(buffer, "a+"); } if (later_file) { SYSTEMTIME sys_time; GetLocalTime(&sys_time); fprintf(later_file, "%02hu/%02hu/%04hu %02hu:%02hu:%02hu\t" "%s\n", sys_time.wMonth, sys_time.wDay, sys_time.wYear, sys_time.wHour, sys_time.wMinute, sys_time.wSecond, filename); fclose(later_file); elog(NOTICE, "Could not delete %s -- will try again later", filename); return true; } else return false; } void win32_unlink_leftover_files() { FILE* later_file; char later_file_path[1024]; sprintf(later_file_path, "%s/global/%s", DataDir, UNLINK_LATER_FILE); later_file = fopen(later_file_path, "r"); if (later_file) { char temp_file_path[1024], filename[1024]; FILE* temp_file = NULL; SYSTEMTIME orig_time; memset(&orig_time, 0, sizeof(SYSTEMTIME)); while (fscanf(later_file, "%02hu/%02hu/%04hu %02hu:%02hu:%02hu\t%s\n", &orig_time.wMonth, &orig_time.wDay, &orig_time.wYear, &orig_time.wHour, &orig_time.wMinute, &orig_time.wSecond, filename) != EOF) { if (DeleteFile(filename)) elog(DEBUG, "Successfully deleted file %s, which had been postponed from an earlier attempt", filename); else if (GetLastError() != ERROR_FILE_NOT_FOUND) { if (!temp_file) { sprintf(temp_file_path, "%s/global/%s.%d", DataDir, UNLINK_LATER_FILE, getpid()); temp_file = fopen(temp_file_path, "w"); } if (temp_file) { fprintf(temp_file, "%02hu/%02hu/%04hu %02hu:%02hu:%02hu\t" "%s\n", orig_time.wMonth, orig_time.wDay, orig_time.wYear, orig_time.wHour, orig_time.wMinute, orig_time.wSecond, filename); } else { elog(DEBUG, "Could not delete file %s. Please delete by hand.", filename); } } } fclose(later_file); DeleteFile(later_file_path); if (temp_file) { fclose(temp_file); rename(temp_file_path, later_file_path); } } } #endif /* _LIB */