summaryrefslogtreecommitdiff
path: root/prism/util/pm_string.c
diff options
context:
space:
mode:
authorKevin Newton <[email protected]>2024-09-11 16:49:08 -0400
committerKevin Newton <[email protected]>2024-09-12 13:43:04 -0400
commit38ba15beed5eb9f3a4923f9a215473965f31a7bc (patch)
treed08a137031db3343d37d733c57347d3ce8569f59 /prism/util/pm_string.c
parentca61729fa7713f650c7e4144daa08932f8b66454 (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.c78
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
}