aboutsummaryrefslogtreecommitdiff
path: root/src/std/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/std/file.c')
-rw-r--r--src/std/file.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/src/std/file.c b/src/std/file.c
index 46099b4..098b18f 100644
--- a/src/std/file.c
+++ b/src/std/file.c
@@ -14,6 +14,7 @@
#include <unistd.h>
#define SCANDIR_PATH_LENGTH 4096
+#define MAX_FILE_SIZE 1024*1024*48 /* 48 mb */
static int scan_dir_recursive_internal(char *dir_path, int path_length, scan_dir_callback_func callback_func, void *userdata) {
DIR *dir;
@@ -165,11 +166,40 @@ int mapped_file_deinit(MappedFile *self) {
return 0;
}
+typedef enum {
+ REGULAR,
+ DIRECTORY,
+ OTHER
+} FileType;
+
+static CHECK_RESULT int file_get_type(const char *filepath, FileType *type) {
+ struct stat file_stats;
+ if(stat(filepath, &file_stats) == -1) {
+ amal_log_perror(filepath);
+ return -1;
+ }
+
+ if(file_stats.st_mode & S_IFDIR)
+ *type = DIRECTORY;
+ else if(file_stats.st_mode & S_IFREG)
+ *type = REGULAR;
+ else
+ *type = OTHER;
+ return 0;
+}
+
int read_whole_file(const char *filepath, char **data, usize *size) {
+ FileType file_type;
FILE *file;
int result;
usize bytes_read;
+ return_if_error(file_get_type(filepath, &file_type));
+ if(file_type != REGULAR) {
+ amal_log_error("Expected file %s to be a regular file", filepath);
+ return -2;
+ }
+
result = 0;
file = fopen(filepath, "rb");
if(!file) {
@@ -192,6 +222,12 @@ int read_whole_file(const char *filepath, char **data, usize *size) {
goto cleanup;
}
+ if(*size > MAX_FILE_SIZE) {
+ amal_log_error("File %s is too large (larger than 48 megabytes)", filepath);
+ result = -1;
+ goto cleanup;
+ }
+
cleanup_if_error(am_malloc(*size, (void**)data));
bytes_read = fread(*data, 1, *size, file);
if(bytes_read != *size) {
@@ -202,3 +238,21 @@ int read_whole_file(const char *filepath, char **data, usize *size) {
fclose(file);
return result;
}
+
+BufferView file_get_parent_directory(BufferView filepath) {
+ int i;
+ for(i = filepath.size - 1; i >= 0; --i) {
+ if(filepath.data[i] == '/')
+ return create_buffer_view(filepath.data, i);
+ }
+ return create_buffer_view(filepath.data, 0);
+}
+
+BufferView file_get_name(BufferView filepath) {
+ int i;
+ for(i = filepath.size - 1; i >= 0; --i) {
+ if(filepath.data[i] == '/')
+ return create_buffer_view(filepath.data + i, filepath.size - i);
+ }
+ return filepath;
+}