diff options
author | Kevin Newton <[email protected]> | 2024-09-11 16:49:08 -0400 |
---|---|---|
committer | Kevin Newton <[email protected]> | 2024-09-12 13:43:04 -0400 |
commit | 38ba15beed5eb9f3a4923f9a215473965f31a7bc (patch) | |
tree | d08a137031db3343d37d733c57347d3ce8569f59 /prism/util/pm_string.c | |
parent | ca61729fa7713f650c7e4144daa08932f8b66454 (diff) |
[ruby/prism] Check errno for parsing directory
https://github.com/ruby/prism/commit/d68ea29d04
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/11497
Diffstat (limited to 'prism/util/pm_string.c')
-rw-r--r-- | prism/util/pm_string.c | 78 |
1 files changed, 44 insertions, 34 deletions
diff --git a/prism/util/pm_string.c b/prism/util/pm_string.c index 3e1e22e34f..99a27ede4d 100644 --- a/prism/util/pm_string.c +++ b/prism/util/pm_string.c @@ -64,24 +64,33 @@ typedef struct { * Open the file indicated by the filepath parameter for reading on Windows. * Perform any kind of normalization that needs to happen on the filepath. */ -static bool +static pm_string_init_result_t pm_string_file_handle_open(pm_string_file_handle_t *handle, const char *filepath) { int length = MultiByteToWideChar(CP_UTF8, 0, filepath, -1, NULL, 0); - if (length == 0) return false; + if (length == 0) return PM_STRING_INIT_ERROR_GENERIC; handle->path = xmalloc(sizeof(WCHAR) * ((size_t) length)); if ((handle->path == NULL) || (MultiByteToWideChar(CP_UTF8, 0, filepath, -1, handle->path, length) == 0)) { xfree(handle->path); - return false; + return PM_STRING_INIT_ERROR_GENERIC; } handle->file = CreateFileW(handle->path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL); if (handle->file == INVALID_HANDLE_VALUE) { + pm_string_init_result_t result = PM_STRING_INIT_ERROR_GENERIC; + + if (GetLastError() == ERROR_ACCESS_DENIED) { + DWORD attributes = GetFileAttributesW(handle->path); + if ((attributes != INVALID_FILE_ATTRIBUTES) && (attributes & FILE_ATTRIBUTE_DIRECTORY)) { + result = PM_STRING_INIT_ERROR_DIRECTORY; + } + } + xfree(handle->path); - return false; + return result; } - return true; + return PM_STRING_INIT_SUCCESS; } /** @@ -105,18 +114,19 @@ pm_string_file_handle_close(pm_string_file_handle_t *handle) { * `MapViewOfFile`, on POSIX systems that have access to `mmap` we'll use * `mmap`, and on other POSIX systems we'll use `read`. */ -PRISM_EXPORTED_FUNCTION bool +PRISM_EXPORTED_FUNCTION pm_string_init_result_t pm_string_mapped_init(pm_string_t *string, const char *filepath) { #ifdef _WIN32 // Open the file for reading. pm_string_file_handle_t handle; - if (!pm_string_file_handle_open(&handle, filepath)) return false; + pm_string_init_result_t result = pm_string_file_handle_open(&handle, filepath); + if (result != PM_STRING_INIT_SUCCESS) return result; // Get the file size. DWORD file_size = GetFileSize(handle.file, NULL); if (file_size == INVALID_FILE_SIZE) { pm_string_file_handle_close(&handle); - return false; + return PM_STRING_INIT_ERROR_GENERIC; } // If the file is empty, then we don't need to do anything else, we'll set @@ -125,14 +135,14 @@ pm_string_mapped_init(pm_string_t *string, const char *filepath) { pm_string_file_handle_close(&handle); const uint8_t source[] = ""; *string = (pm_string_t) { .type = PM_STRING_CONSTANT, .source = source, .length = 0 }; - return true; + return PM_STRING_INIT_SUCCESS; } // Create a mapping of the file. HANDLE mapping = CreateFileMapping(handle.file, NULL, PAGE_READONLY, 0, 0, NULL); if (mapping == NULL) { pm_string_file_handle_close(&handle); - return false; + return PM_STRING_INIT_ERROR_GENERIC; } // Map the file into memory. @@ -141,30 +151,29 @@ pm_string_mapped_init(pm_string_t *string, const char *filepath) { pm_string_file_handle_close(&handle); if (source == NULL) { - return false; + return PM_STRING_INIT_ERROR_GENERIC; } *string = (pm_string_t) { .type = PM_STRING_MAPPED, .source = source, .length = (size_t) file_size }; - return true; + return PM_STRING_INIT_SUCCESS; #elif defined(_POSIX_MAPPED_FILES) // Open the file for reading int fd = open(filepath, O_RDONLY); if (fd == -1) { - return false; + return PM_STRING_INIT_ERROR_GENERIC; } // Stat the file to get the file size struct stat sb; if (fstat(fd, &sb) == -1) { close(fd); - return false; + return PM_STRING_INIT_ERROR_GENERIC; } // Ensure it is a file and not a directory if (S_ISDIR(sb.st_mode)) { - errno = EISDIR; close(fd); - return false; + return PM_STRING_INIT_ERROR_DIRECTORY; } // mmap the file descriptor to virtually get the contents @@ -175,17 +184,17 @@ pm_string_mapped_init(pm_string_t *string, const char *filepath) { close(fd); const uint8_t source[] = ""; *string = (pm_string_t) { .type = PM_STRING_CONSTANT, .source = source, .length = 0 }; - return true; + return PM_STRING_INIT_SUCCESS; } source = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); if (source == MAP_FAILED) { - return false; + return PM_STRING_INIT_ERROR_GENERIC; } close(fd); *string = (pm_string_t) { .type = PM_STRING_MAPPED, .source = source, .length = size }; - return true; + return PM_STRING_INIT_SUCCESS; #else return pm_string_file_init(string, filepath); #endif @@ -196,18 +205,19 @@ pm_string_mapped_init(pm_string_t *string, const char *filepath) { * contents and size into the given `pm_string_t`. The given `pm_string_t` * should be freed using `pm_string_free` when it is no longer used. */ -PRISM_EXPORTED_FUNCTION bool +PRISM_EXPORTED_FUNCTION pm_string_init_result_t pm_string_file_init(pm_string_t *string, const char *filepath) { #ifdef _WIN32 // Open the file for reading. pm_string_file_handle_t handle; - if (!pm_string_file_handle_open(&handle, filepath)) return false; + pm_string_init_result_t result = pm_string_file_handle_open(&handle, filepath); + if (result != PM_STRING_INIT_SUCCESS) return result; // Get the file size. DWORD file_size = GetFileSize(handle.file, NULL); if (file_size == INVALID_FILE_SIZE) { pm_string_file_handle_close(&handle); - return false; + return PM_STRING_INIT_ERROR_GENERIC; } // If the file is empty, then we don't need to do anything else, we'll set @@ -216,37 +226,37 @@ pm_string_file_init(pm_string_t *string, const char *filepath) { pm_string_file_handle_close(&handle); const uint8_t source[] = ""; *string = (pm_string_t) { .type = PM_STRING_CONSTANT, .source = source, .length = 0 }; - return true; + return PM_STRING_INIT_SUCCESS; } // Create a buffer to read the file into. uint8_t *source = xmalloc(file_size); if (source == NULL) { pm_string_file_handle_close(&handle); - return false; + return PM_STRING_INIT_ERROR_GENERIC; } // Read the contents of the file DWORD bytes_read; if (!ReadFile(handle.file, source, file_size, &bytes_read, NULL)) { pm_string_file_handle_close(&handle); - return false; + return PM_STRING_INIT_ERROR_GENERIC; } // Check the number of bytes read if (bytes_read != file_size) { xfree(source); pm_string_file_handle_close(&handle); - return false; + return PM_STRING_INIT_ERROR_GENERIC; } pm_string_file_handle_close(&handle); *string = (pm_string_t) { .type = PM_STRING_OWNED, .source = source, .length = (size_t) file_size }; - return true; + return PM_STRING_INIT_SUCCESS; #elif defined(PRISM_HAS_FILESYSTEM) FILE *file = fopen(filepath, "rb"); if (file == NULL) { - return false; + return PM_STRING_INIT_ERROR_GENERIC; } fseek(file, 0, SEEK_END); @@ -254,21 +264,21 @@ pm_string_file_init(pm_string_t *string, const char *filepath) { if (file_size == -1) { fclose(file); - return false; + return PM_STRING_INIT_ERROR_GENERIC; } if (file_size == 0) { fclose(file); const uint8_t source[] = ""; *string = (pm_string_t) { .type = PM_STRING_CONSTANT, .source = source, .length = 0 }; - return true; + return PM_STRING_INIT_SUCCESS; } size_t length = (size_t) file_size; uint8_t *source = xmalloc(length); if (source == NULL) { fclose(file); - return false; + return PM_STRING_INIT_ERROR_GENERIC; } fseek(file, 0, SEEK_SET); @@ -277,16 +287,16 @@ pm_string_file_init(pm_string_t *string, const char *filepath) { if (bytes_read != 1) { xfree(source); - return false; + return PM_STRING_INIT_ERROR_GENERIC; } *string = (pm_string_t) { .type = PM_STRING_OWNED, .source = source, .length = length }; - return true; + return PM_STRING_INIT_SUCCESS; #else (void) string; (void) filepath; perror("pm_string_file_init is not implemented for this platform"); - return false; + return PM_STRING_INIT_ERROR_GENERIC; #endif } |