diff options
Diffstat (limited to 'src/util/file')
| -rw-r--r-- | src/util/file/file.h | 11 | ||||
| -rw-r--r-- | src/util/file/file_linux.c | 43 | ||||
| -rw-r--r-- | src/util/file/file_stdio.c | 4 | ||||
| -rw-r--r-- | src/util/file/util.c | 10 |
4 files changed, 56 insertions, 12 deletions
diff --git a/src/util/file/file.h b/src/util/file/file.h index 465d76a..a6611bd 100644 --- a/src/util/file/file.h +++ b/src/util/file/file.h @@ -14,6 +14,13 @@ #endif #include <al/str.h> +#include <al/lib.h> + +enum { + AKI_FILE_READONLY = 1, + AKI_FILE_CREATE = 1 << 1, + AKI_FILE_LOCK = 1 << 2 +}; enum { AKI_ENTRY_FILE = 0, @@ -60,8 +67,9 @@ struct aki_dir_entry { str path; }; -bool aki_file_open(struct aki_file *file, str *path, bool create); +bool aki_file_open(struct aki_file *file, str *path, s32 flags); bool aki_file_exists(str *path); +bool aki_file_create(str *path); bool aki_file_truncate(struct aki_file *file, off_t size); off_t aki_file_seek(struct aki_file *file, off_t offset, s32 whence); size_t aki_file_get_filesize(struct aki_file *file); @@ -69,6 +77,7 @@ bool aki_file_write(struct aki_file *file, void *buf, size_t size); bool aki_file_read(struct aki_file *file, void *buf, size_t size); s32 aki_file_read_as_str(struct aki_file *file, str *out); s32 aki_file_read_as_c_str(struct aki_file *file, char **out); +s32 aki_file_replace(struct aki_file *file, str *buf); void *aki_file_mmap(struct aki_file *file); void *aki_file_mremap(struct aki_file *file, size_t size, void *old_map); void aki_file_munmap(struct aki_file *file, void *map); diff --git a/src/util/file/file_linux.c b/src/util/file/file_linux.c index 708bd2d..f916e0b 100644 --- a/src/util/file/file_linux.c +++ b/src/util/file/file_linux.c @@ -1,16 +1,33 @@ -#include <sys/mman.h> #include <al/log.h> +#include <sys/mman.h> #include "../error.h" #include "file.h" -bool aki_file_open(struct aki_file *file, str *path, bool create) +static bool lock_file_internal(s32 fd) +{ + struct flock l = { + .l_type = F_WRLCK, + .l_whence = SEEK_SET, + .l_start = 0, + .l_len = 0 + }; + if (fcntl(fd, F_SETLKW, &l) == -1) { + al_log_error("file", "fcntl(F_SETLKW) failed (%s).", aki_strerror(errno)); + close(fd); + return false; + } + return true; +} + +bool aki_file_open(struct aki_file *file, str *path, s32 flags) { + al_assert(!((flags & AKI_FILE_READONLY) && (flags & AKI_FILE_LOCK))); char *c_str = al_str_to_c_str(path); - s32 flags = O_RDWR; - if (create) flags |= O_CREAT; - file->fd = open(c_str, flags, 0666); + s32 oflags = (flags & AKI_FILE_READONLY) ? O_RDONLY : O_RDWR; + if (flags & AKI_FILE_CREATE) oflags |= O_CREAT; + file->fd = open(c_str, oflags, 0666); al_free(c_str); if (file->fd == -1) { al_log_error("file", "open(%.*s) failed (%s).", AL_STR_PRINTF(path), aki_strerror(errno)); @@ -24,6 +41,7 @@ bool aki_file_open(struct aki_file *file, str *path, bool create) return false; } file->filesize = sb.st_size; + if (flags & AKI_FILE_LOCK) lock_file_internal(file->fd); return true; } @@ -32,12 +50,19 @@ bool aki_file_exists(str *path) char *c_str = al_str_to_c_str(path); s32 ret = access(c_str, F_OK); al_free(c_str); - if (ret != 0) { - al_log_error("file", "access(%.*s, F_OK) failed (%s).", AL_STR_PRINTF(path), aki_strerror(errno)); - } return ret == 0; } +bool aki_file_create(str *path) +{ + struct aki_file file; + if (aki_file_open(&file, path, AKI_FILE_CREATE)) { + aki_file_close(&file); + return true; + } + return false; +} + off_t aki_file_seek(struct aki_file *file, off_t offset, s32 whence) { off_t res = lseek(file->fd, offset, whence); @@ -98,7 +123,6 @@ void *aki_file_mmap(struct aki_file *file) void *aki_file_mremap(struct aki_file *file, size_t size, void *old_map) { - printf("old_size: %zu, new_size: %zu\n", file->filesize, size); void *map = mremap(old_map, file->filesize, size, MREMAP_MAYMOVE); if (map == MAP_FAILED) { al_log_error("file", "mremap(%p, %zu, %zu) failed (%s).", old_map, @@ -152,6 +176,7 @@ bool aki_dir_exists(str *path) } return false; } + closedir(dir.dir); return true; } diff --git a/src/util/file/file_stdio.c b/src/util/file/file_stdio.c index 52d8761..fa1e4ff 100644 --- a/src/util/file/file_stdio.c +++ b/src/util/file/file_stdio.c @@ -4,10 +4,10 @@ #include "file.h" -bool aki_file_open(struct aki_file *file, str *path, bool create) +bool aki_file_open(struct aki_file *file, str *path, s32 flags) { char *c_str = al_str_to_c_str(path); - const char *mode = create ? "wb+" : "rb+"; + const char *mode = (flags & AKI_FILE_CREATE) ? "wb+" : "rb+"; #ifndef _WIN32 file->file = fopen(c_str, mode); #else diff --git a/src/util/file/util.c b/src/util/file/util.c index e893de7..fe7785f 100644 --- a/src/util/file/util.c +++ b/src/util/file/util.c @@ -23,3 +23,13 @@ s32 aki_file_read_as_c_str(struct aki_file *file, char **out) (*out)[size] = '\n'; return size; } + +s32 aki_file_replace(struct aki_file *file, str *buf) +{ + if (aki_file_seek(file, 0, SEEK_SET) == (off_t)-1 || + !aki_file_write(file, buf->data, buf->len) || + !aki_file_truncate(file, buf->len)) { + return -1; + } + return buf->len; +} |