aboutsummaryrefslogtreecommitdiff
path: root/src/libjin/3rdparty/smount/smount.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libjin/3rdparty/smount/smount.c')
-rw-r--r--src/libjin/3rdparty/smount/smount.c200
1 files changed, 200 insertions, 0 deletions
diff --git a/src/libjin/3rdparty/smount/smount.c b/src/libjin/3rdparty/smount/smount.c
new file mode 100644
index 0000000..c4e2ef0
--- /dev/null
+++ b/src/libjin/3rdparty/smount/smount.c
@@ -0,0 +1,200 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <vadefs.h>
+#include "smount.h"
+#include "dirent.h"
+
+#define isseparator(c) (c == '/' || c == '\\')
+
+static smtPath* smtnewpath(int type, const char* path, smtPath* next)
+{
+ smtPath* temp = (smtPath*)malloc(sizeof(smtPath));
+ int len = strlen(path);
+ temp->path = (char*)malloc(len + 1);
+ memcpy(temp->path, path, len);
+ temp->path[len] = '\0';
+ // trim trailing separator
+ while (isseparator(temp->path[--len]))
+ temp->path[len] = '\0';
+ temp->next = next;
+ temp->type = type;
+ return temp;
+}
+
+static const char* mkstr(const char* str)
+{
+ int len = strlen(str);
+ char* temp = (char*)malloc(strlen(str));
+ memcpy(temp, str, len);
+ return temp;
+}
+
+/**
+* Create a new shared contex.
+*/
+smtShared* smtnewshared()
+{
+ smtShared* shared = (smtShared*)malloc(sizeof(smtShared));
+ shared->mount = 0;
+ return shared;
+}
+
+/**
+* Concatenate strings together.
+*/
+char *concat(const char *str, ...) {
+ va_list args;
+ const char *s;
+ // Get len
+ int len = strlen(str);
+ va_start(args, str);
+ while ((s = va_arg(args, char*))) {
+ len += strlen(s);
+ }
+ va_end(args);
+ // Build string
+ char *res = (char*)malloc(len + 1);
+ if (!res) return NULL;
+ strcpy(res, str);
+ va_start(args, str);
+ while ((s = va_arg(args, char*))) {
+ strcat(res, s);
+ }
+ va_end(args);
+ return res;
+}
+
+static int isdir(const char *path) {
+ struct stat s;
+ int res = stat(path, &s);
+ return S_ISDIR(s.st_mode);
+}
+
+int smtmount(smtShared* S, const char *path)
+{
+ if (!isdir(path))
+ {
+ return SMT_INVALIDMOUNT;
+ }
+
+ S->mount = smtnewpath(PATH_DIR, path, 0);
+
+ return SMT_SUCCESS;
+}
+
+void smtunmount(smtShared* S)
+{
+ smtPath* mount = S->mount;
+ while (mount)
+ {
+ free(mount->path);
+ mount = mount->next;
+ }
+}
+
+int smtexists(smtShared* S, const char *path)
+{
+ char* r = concat(S->mount->path, "/", path, 0);
+ if (!r) return SMT_NOSUCHDIR;
+ struct stat s;
+ int res = stat(r, &s);
+ free(r);
+ if (res == 0)
+ return SMT_SUCCESS;
+ return SMT_NOSUCHDIR;
+}
+
+static struct stat smtgetstat(smtShared* S, const char*path)
+{
+ char* r = concat(S->mount->path, "/", path, 0);
+ struct stat s = {};
+ if (!r) return s;
+ int res = stat(r, &s);
+ free(r);
+ return s;
+}
+
+int smtisdir(smtShared* S, const char *path)
+{
+ struct stat s = smtgetstat(S, path);
+ return S_ISDIR(s.st_mode);
+}
+
+int smtisreg(smtShared* S, const char *path)
+{
+ struct stat s = smtgetstat(S, path);
+ return S_ISREG(s.st_mode);
+}
+
+const char* smterrstr(int e)
+{
+ switch (e)
+ {
+ case SMT_INVALIDMOUNT: return "invalid mount directory";
+ default: return "unknown error";
+ }
+}
+
+void *smtread(smtShared* S, const char *path, unsigned int *size)
+{
+ if (!smtisreg(S, path)) return 0;
+ int fr = 0;
+ if (size == 0)
+ {
+ fr = 1;
+ size = (unsigned int*)malloc(sizeof(unsigned int));
+ }
+ char *r = concat(S->mount->path, "/", path, NULL);
+ if (!r) return NULL;
+ FILE *fp = fopen(r, "rb");
+ free(r);
+ if (!fp) return 0;
+ /* Get file size */
+ fseek(fp, 0, SEEK_END);
+ *size = ftell(fp);
+ /* Load file */
+ fseek(fp, 0, SEEK_SET);
+ char *res = (char*)malloc(*size + 1);
+ if (!res) return NULL;
+ res[*size] = '\0';
+ if (fread(res, 1, *size, fp) != *size) {
+ free(res);
+ fclose(fp);
+ return NULL;
+ }
+ fclose(fp);
+ if (fr) free(size);
+ return res;
+}
+
+char* smtfullpath(smtShared* S, const char* path)
+{
+ return concat(S->mount->path, "/", path, 0);
+}
+
+int smtsize(smtShared* S, const char *path)
+{
+ struct stat s = smtgetstat(S, path);
+ return s.st_size;
+}
+
+void smtdelete(smtShared* S, const char *path)
+{
+ char* name = smtfullpath(S, path);
+ remove(name);
+ free(name);
+}
+
+int smtwrite(smtShared* S, const char *path, const void *data, int size)
+{
+ char* name = smtfullpath(S, path);
+ if (!name) return SMT_NOSUCHDIR;
+ FILE *fp = fopen(name, "wb");
+ free(name);
+ if (!fp) return SMT_UNABLEOPEN;
+ int res = fwrite(data, size, 1, fp);
+ fclose(fp);
+ return (res == 1) ? SMT_SUCCESS : SMT_CANTWRITE;
+} \ No newline at end of file