diff options
Diffstat (limited to 'src/libjin/3rdparty/smount/smount.c')
-rw-r--r-- | src/libjin/3rdparty/smount/smount.c | 200 |
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 |