Skip to content

Commit

Permalink
Merge pull request #3063 from ruby/stat-first
Browse files Browse the repository at this point in the history
Stat file first to check directory
  • Loading branch information
kddnewton authored Sep 13, 2024
2 parents 7d14ed3 + 4ed7de5 commit f544151
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 16 deletions.
3 changes: 3 additions & 0 deletions include/prism/util/pm_string.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#elif defined(PRISM_HAS_FILESYSTEM)
#include <fcntl.h>
#include <sys/stat.h>
#endif

/**
Expand Down
37 changes: 22 additions & 15 deletions src/util/pm_string.c
Original file line number Diff line number Diff line change
Expand Up @@ -254,38 +254,45 @@ pm_string_file_init(pm_string_t *string, const char *filepath) {
*string = (pm_string_t) { .type = PM_STRING_OWNED, .source = source, .length = (size_t) file_size };
return PM_STRING_INIT_SUCCESS;
#elif defined(PRISM_HAS_FILESYSTEM)
FILE *file = fopen(filepath, "rb");
if (file == NULL) {
// Open the file for reading
int fd = open(filepath, O_RDONLY);
if (fd == -1) {
return PM_STRING_INIT_ERROR_GENERIC;
}

fseek(file, 0, SEEK_END);
long file_size = ftell(file);

if (file_size == -1) {
fclose(file);
// Stat the file to get the file size
struct stat sb;
if (fstat(fd, &sb) == -1) {
close(fd);
return PM_STRING_INIT_ERROR_GENERIC;
}

if (file_size == 0) {
fclose(file);
// Ensure it is a file and not a directory
if (S_ISDIR(sb.st_mode)) {
close(fd);
return PM_STRING_INIT_ERROR_DIRECTORY;
}

// Check the size to see if it's empty
size_t size = (size_t) sb.st_size;
if (size == 0) {
close(fd);
const uint8_t source[] = "";
*string = (pm_string_t) { .type = PM_STRING_CONSTANT, .source = source, .length = 0 };
return PM_STRING_INIT_SUCCESS;
}

size_t length = (size_t) file_size;
size_t length = (size_t) size;
uint8_t *source = xmalloc(length);
if (source == NULL) {
fclose(file);
close(fd);
return PM_STRING_INIT_ERROR_GENERIC;
}

fseek(file, 0, SEEK_SET);
size_t bytes_read = fread(source, length, 1, file);
fclose(file);
long bytes_read = (long) read(fd, source, length);
close(fd);

if (bytes_read != 1) {
if (bytes_read == -1) {
xfree(source);
return PM_STRING_INIT_ERROR_GENERIC;
}
Expand Down
1 change: 0 additions & 1 deletion test/prism/api/parse_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ def test_parse_directory
rescue SystemCallError => error
end

return if error.nil? || error.is_a?(Errno::ENOMEM)
assert_kind_of Errno::EISDIR, error
end

Expand Down

0 comments on commit f544151

Please sign in to comment.