summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/util/error.c2
-rw-r--r--src/util/file/file.h15
-rw-r--r--src/util/file/file_linux.c53
-rw-r--r--src/util/file/file_stdio.c37
-rw-r--r--src/util/file/util.c22
5 files changed, 98 insertions, 31 deletions
diff --git a/src/util/error.c b/src/util/error.c
index 97c7502..46fd8e6 100644
--- a/src/util/error.c
+++ b/src/util/error.c
@@ -19,6 +19,8 @@ char *nn_strerror(s32 errnum)
#ifdef NAUNET_ON_WINDOWS
#include "../winwrap.h"
+// @TODO: GetLastError() should be used in common places like file_stdio.
+
// https://stackoverflow.com/a/46104456
char *nn_win32_error_message(s32 err)
{
diff --git a/src/util/file/file.h b/src/util/file/file.h
index 4df4c96..77344f8 100644
--- a/src/util/file/file.h
+++ b/src/util/file/file.h
@@ -3,6 +3,15 @@
#include <al/str.h>
#include <al/lib.h>
+/*
+#if defined NAUNET_ON_WINDOWS && defined AL_WE_32BIT
+AL_ASSERT_TYPE_SIZE(off_t, 4);
+#else
+AL_ASSERT_TYPE_SIZE(off_t, 8);
+#endif
+*/
+AL_ASSERT_TYPE_SIZE(off_t, 8);
+
#ifdef NAUNET_NEEDS_STDIO_ASSIST
// It seems meson adds _FILE_OFFSET_BITS=64 on all "linuxlike" compilers even MinGW.
// https://github.com/mesonbuild/meson/commit/853634a48da025c59eef70161dba0d150833f60d
@@ -52,7 +61,7 @@ struct nn_file {
#endif
#endif
str path;
- size_t size;
+ off_t size;
};
struct nn_dir {
@@ -77,7 +86,11 @@ struct nn_dir_entry {
#endif
};
+void nn_path_append(str *path, str *part);
+void nn_path_prepend(str *path, str *part);
+
bool nn_file_open(struct nn_file *file, str *path, s32 flags);
+bool nn_file_wrap_fd(struct nn_file *file, s32 fd);
bool nn_file_exists(str *path);
bool nn_file_create(str *path);
bool nn_file_truncate(struct nn_file *file, off_t size);
diff --git a/src/util/file/file_linux.c b/src/util/file/file_linux.c
index 6537d26..761b675 100644
--- a/src/util/file/file_linux.c
+++ b/src/util/file/file_linux.c
@@ -6,7 +6,7 @@
#include "file.h"
-static bool lock_file_internal(s32 fd, size_t size)
+static bool lock_file_internal(s32 fd, off_t size)
{
struct flock l = { .l_type = F_WRLCK, .l_whence = SEEK_SET, .l_start = 0, .l_len = size };
if (fcntl(fd, F_SETLKW, &l) == -1) {
@@ -17,7 +17,7 @@ static bool lock_file_internal(s32 fd, size_t size)
return true;
}
-static bool unlock_file_internal(s32 fd, size_t size)
+static bool unlock_file_internal(s32 fd, off_t size)
{
struct flock l = { .l_type = F_ULOCK, .l_whence = SEEK_SET, .l_start = 0, .l_len = size };
if (fcntl(fd, F_SETLKW, &l) == -1) {
@@ -35,6 +35,16 @@ static bool open_file_linux(s32 *fd, str *path, s32 flags)
return success;
}
+static inline off_t fstat_for_size(s32 fd)
+{
+ struct stat sb;
+ if (fstat(fd, &sb) == -1) {
+ log_error("fstat() failed (%s).", nn_strerror(errno));
+ return -1;
+ }
+ return sb.st_size;
+}
+
bool nn_file_open(struct nn_file *file, str *path, s32 flags)
{
file->flags = flags;
@@ -48,14 +58,11 @@ bool nn_file_open(struct nn_file *file, str *path, s32 flags)
return false;
}
- struct stat sb;
- s32 res = fstat(file->fd, &sb);
- if (res == -1) {
- log_error("fstat() failed (%s).", nn_strerror(errno));
+ file->size = fstat_for_size(file->fd);
+ if (file->size == -1) {
close(file->fd);
return false;
}
- file->size = sb.st_size;
if (flags & NNWT_FILE_LOCK && !lock_file_internal(file->fd, file->size)) {
close(file->fd);
@@ -67,6 +74,20 @@ bool nn_file_open(struct nn_file *file, str *path, s32 flags)
return true;
}
+bool nn_file_wrap_fd(struct nn_file *file, s32 fd)
+{
+ file->fd = fd;
+ file->size = fstat_for_size(file->fd);
+ if (file->size == -1) {
+ close(file->fd);
+ return false;
+ }
+ al_str_from(&file->path, "<fd:");
+ al_str_cat(&file->path, al_print_s32(fd));
+ al_str_cat(&file->path, &al_str_c(">"));
+ return true;
+}
+
bool nn_file_exists(str *path)
{
char *c_str = al_str_to_c_str(path);
@@ -85,11 +106,11 @@ bool nn_file_create(str *path)
off_t nn_file_seek(struct nn_file *file, off_t offset, s32 whence)
{
- off_t res = lseek(file->fd, offset, whence);
- if (res == (off_t)-1) {
+ off_t ret = lseek(file->fd, offset, whence);
+ if (ret == (off_t)-1) {
log_error("lseek(%zd, %d) failed (%s).", offset, whence, nn_strerror(errno));
}
- return res;
+ return ret;
}
bool nn_file_truncate(struct nn_file *file, off_t size)
@@ -115,25 +136,25 @@ bool nn_file_flush(struct nn_file *file)
#define file_io_loop(call, fail_case) \
size_t bc = 0; \
- ssize_t res; \
+ ssize_t ret; \
for (;;) { \
- res = call(file->fd, buf, size - bc); \
+ ret = call(file->fd, buf, size - bc); \
if (fail_case) { \
log_error(""#call"() failed (%s).", nn_strerror(errno)); \
return false; \
} \
- if ((bc += res) >= size) break; \
+ if ((bc += ret) >= size) break; \
} \
return true
bool nn_file_write(struct nn_file *file, void *buf, size_t size)
{
- file_io_loop(write, (res == -1));
+ file_io_loop(write, (ret == -1));
}
bool nn_file_read(struct nn_file *file, void *buf, size_t size)
{
- file_io_loop(read, (res == -1));
+ file_io_loop(read, (ret == -1));
}
void *nn_file_mmap(struct nn_file *file)
@@ -233,10 +254,10 @@ bool nn_dir_read(struct nn_dir *dir, struct nn_dir_entry *entry)
}
switch (entry->entry->d_type) {
+ case DT_REG:
case DT_UNKNOWN:
entry->type = NNWT_ENTRY_FILE;
break;
- case DT_REG:
case DT_DIR:
entry->type = NNWT_ENTRY_DIR;
break;
diff --git a/src/util/file/file_stdio.c b/src/util/file/file_stdio.c
index fa74be7..5bdc7d9 100644
--- a/src/util/file/file_stdio.c
+++ b/src/util/file/file_stdio.c
@@ -2,18 +2,14 @@
#include <al/log.h>
#include <al/lib.h>
+#ifdef NAUNET_ON_WINDOWS
+#include "../../winwrap.h"
+#endif
+
#include "../error.h"
#include "file.h"
-/*
-#if defined NAUNET_ON_WINDOWS && defined AL_WE_32BIT
-AL_ASSERT_TYPE_SIZE(off_t, 4);
-#else
-AL_ASSERT_TYPE_SIZE(off_t, 8);
-#endif
-*/
-
static inline bool open_stdio_file(FILE **file, str *path, const char *mode)
{
char *c_str = al_str_to_c_str(path);
@@ -27,13 +23,11 @@ static inline bool open_stdio_file(FILE **file, str *path, const char *mode)
return ret == 0;
}
-static bool query_filesize_stdio(struct nn_file *file)
+static inline off_t seek_for_size(struct nn_file *file)
{
off_t pos = nn_file_seek(file, 0, SEEK_END);
- if (pos == -1) return false;
- file->size = pos;
rewind(file->file);
- return true;
+ return pos;
}
bool nn_file_open(struct nn_file *file, str *path, s32 flags)
@@ -44,7 +38,8 @@ bool nn_file_open(struct nn_file *file, str *path, s32 flags)
return false;
}
- if (!query_filesize_stdio(file)) {
+ file->size = seek_for_size(file);
+ if (file->size == -1) {
nn_file_close(file);
return false;
}
@@ -54,6 +49,13 @@ bool nn_file_open(struct nn_file *file, str *path, s32 flags)
return true;
}
+bool nn_file_wrap_fd(struct nn_file *file, s32 fd)
+{
+ (void)file;
+ (void)fd;
+ al_assert_and_return(false);
+}
+
bool nn_file_exists(str *path)
{
FILE *file;
@@ -81,6 +83,15 @@ off_t nn_file_seek(struct nn_file *file, off_t offset, s32 whence)
bool nn_file_truncate(struct nn_file *file, off_t size)
{
+#ifdef NAUNET_ON_WINDOWS
+ errno_t ret = _chsize_s(fileno(file->file), size);
+#else
+ s32 ret = ftruncate(fileno(file->file), size);
+#endif
+ if (ret != 0) {
+ log_error("ftruncate(%zd) failed (%s).", size, nn_strerror(errno));
+ return false;
+ }
file->size = size;
return true;
}
diff --git a/src/util/file/util.c b/src/util/file/util.c
index 2f1fa36..0a42aad 100644
--- a/src/util/file/util.c
+++ b/src/util/file/util.c
@@ -1,5 +1,25 @@
#include "file.h"
+void nn_path_append(str *path, str *part)
+{
+#ifdef NAUNET_ON_WINDOWS
+ al_str_cat(path, &al_str_c("\\"));
+#else
+ al_str_cat(path, &al_str_c("/"));
+#endif
+ al_str_cat(path, part);
+}
+
+void nn_path_prepend(str *path, str *part)
+{
+#ifdef NAUNET_ON_WINDOWS
+ al_str_prepend(path, &al_str_c("\\"));
+#else
+ al_str_prepend(path, &al_str_c("/"));
+#endif
+ al_str_prepend(path, part);
+}
+
s32 nn_file_read_as_str(struct nn_file *file, str *out)
{
size_t size = file->size;
@@ -20,7 +40,7 @@ s32 nn_file_read_as_c_str(struct nn_file *file, char **out)
al_free(*out);
return -1;
}
- c_str[size] = '\n';
+ c_str[size] = '\0';
*out = c_str;
return size;
}