summaryrefslogtreecommitdiff
path: root/filesystem-posix.c
diff options
context:
space:
mode:
Diffstat (limited to 'filesystem-posix.c')
-rw-r--r--filesystem-posix.c90
1 files changed, 90 insertions, 0 deletions
diff --git a/filesystem-posix.c b/filesystem-posix.c
new file mode 100644
index 0000000..8af0bf2
--- /dev/null
+++ b/filesystem-posix.c
@@ -0,0 +1,90 @@
+#include "filesystem.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <errno.h>
+
+FsType fs_path_type(char const *path) {
+ struct stat statbuf = {0};
+ if (stat(path, &statbuf) != 0)
+ return FS_NON_EXISTENT;
+ if (S_ISREG(statbuf.st_mode))
+ return FS_FILE;
+ if (S_ISDIR(statbuf.st_mode))
+ return FS_DIRECTORY;
+ return FS_OTHER;
+}
+
+FsPermission fs_path_permission(char const *path) {
+ int bits = access(path, R_OK | W_OK);
+ FsPermission perm = 0;
+ if (!(bits & R_OK)) perm |= FS_PERMISSION_READ;
+ if (!(bits & W_OK)) perm |= FS_PERMISSION_WRITE;
+ return perm;
+}
+
+bool fs_file_exists(char const *path) {
+ return fs_path_type(path) == FS_FILE;
+}
+
+char **fs_list_directory(char const *dirname) {
+ char **ret = NULL;
+ DIR *dir = opendir(dirname);
+ if (dir) {
+ struct dirent *ent;
+ char **filenames = NULL;
+ size_t nentries = 0;
+ size_t filename_idx = 0;
+
+ while (readdir(dir)) ++nentries;
+ rewinddir(dir);
+ filenames = (char **)calloc(nentries+1, sizeof *filenames);
+
+ while ((ent = readdir(dir))) {
+ char const *filename = ent->d_name;
+ size_t len = strlen(filename);
+ char *filename_copy = (char *)malloc(len+1);
+ if (!filename_copy) break;
+ strcpy(filename_copy, filename);
+ if (filename_idx < nentries) // this could actually fail if someone creates files between calculating nentries and here.
+ filenames[filename_idx++] = filename_copy;
+ }
+ ret = filenames;
+ closedir(dir);
+ }
+ return ret;
+}
+
+int fs_mkdir(char const *path) {
+ if (mkdir(path, 0755) == 0) {
+ // directory created successfully
+ return 1;
+ } else if (errno == EEXIST) {
+ struct stat statbuf = {0};
+ if (stat(path, &statbuf) == 0) {
+ if (S_ISDIR(statbuf.st_mode)) {
+ // already exists, and it's a directory
+ return 0;
+ } else {
+ // already exists, but not a directory
+ return -1;
+ }
+ } else {
+ return -1;
+ }
+ } else {
+ return -1;
+ }
+}
+
+int fs_get_cwd(char *buf, size_t buflen) {
+ assert(buf && buflen);
+ if (getcwd(buf, buflen)) {
+ return 1;
+ } else if (errno == ERANGE) {
+ return 0;
+ } else {
+ return -1;
+ }
+}