summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'extract/src/sys.c')
-rw-r--r--extract/src/sys.c137
1 files changed, 137 insertions, 0 deletions
diff --git a/extract/src/sys.c b/extract/src/sys.c
new file mode 100644
index 00000000..131f6312
--- /dev/null
+++ b/extract/src/sys.c
@@ -0,0 +1,137 @@
+#include "mem.h"
+#include "outf.h"
+#include "sys.h"
+
+#include <errno.h>
+#include <stdarg.h>
+
+#include <sys/stat.h>
+
+
+/* Define extract_APPLE_IOS if we are on iOS. */
+#undef extract_APPLE_IOS
+#ifdef __APPLE__
+ #include "TargetConditionals.h"
+ #ifdef TARGET_OS_IPHONE
+ #define extract_APPLE_IOS
+ #elif TARGET_IPHONE_SIMULATOR
+ #define extract_APPLE_IOS
+ #endif
+#endif
+
+int extract_systemf(extract_alloc_t* alloc, const char* format, ...)
+{
+ #ifdef extract_APPLE_IOS
+ /* system() not available on iOS. */
+ (void) alloc;
+ (void) format;
+ errno = ENOTSUP;
+ return -1;
+ #else
+
+ int e;
+ char* command;
+ va_list va;
+ va_start(va, format);
+ e = extract_vasprintf(alloc, &command, format, va);
+ va_end(va);
+ if (e < 0) return e;
+ outf("running: %s", command);
+ e = system(command);
+ extract_free(alloc, &command);
+ if (e > 0) {
+ errno = EIO;
+ }
+ return e;
+
+ #endif
+}
+
+int extract_read_all(extract_alloc_t* alloc, FILE* in, char** o_out)
+{
+ size_t len = 0;
+ size_t delta = 128;
+ for(;;) {
+ size_t n;
+ if (extract_realloc2(alloc, o_out, len, len + delta + 1)) {
+ extract_free(alloc, o_out);
+ return -1;
+ }
+ n = fread(*o_out + len, 1 /*size*/, delta /*nmemb*/, in);
+ len += n;
+ if (feof(in)) {
+ (*o_out)[len] = 0;
+ return 0;
+ }
+ if (ferror(in)) {
+ /* It's weird that fread() and ferror() don't set errno. */
+ errno = EIO;
+ extract_free(alloc, o_out);
+ return -1;
+ }
+ }
+}
+
+int extract_read_all_path(extract_alloc_t* alloc, const char* path, char** o_text)
+{
+ int e = -1;
+ FILE* f = NULL;
+ f = fopen(path, "rb");
+ if (!f) goto end;
+ if (extract_read_all(alloc, f, o_text)) goto end;
+ e = 0;
+ end:
+ if (f) fclose(f);
+ if (e) extract_free(alloc, &o_text);
+ return e;
+}
+
+int extract_write_all(const void* data, size_t data_size, const char* path)
+{
+ int e = -1;
+ FILE* f = fopen(path, "w");
+ if (!f) goto end;
+ if (fwrite(data, data_size, 1 /*nmemb*/, f) != 1) goto end;
+ e = 0;
+ end:
+ if (f) fclose(f);
+ return e;
+}
+
+int extract_check_path_shell_safe(const char* path)
+/* Returns -1 with errno=EINVAL if <path> contains sequences that could make it
+unsafe in shell commands. */
+{
+ if (0
+ || strstr(path, "..")
+ || strchr(path, '\'')
+ || strchr(path, '"')
+ || strchr(path, ' ')
+ ) {
+ errno = EINVAL;
+ return -1;
+ }
+ return 0;
+}
+int extract_remove_directory(extract_alloc_t* alloc, const char* path)
+{
+ if (extract_check_path_shell_safe(path)) {
+ outf("path_out is unsafe: %s", path);
+ return -1;
+ }
+ return extract_systemf(alloc, "rm -r '%s'", path);
+}
+
+#ifdef _WIN32
+#include <direct.h>
+int extract_mkdir(const char* path, int mode)
+{
+ (void) mode;
+ return _mkdir(path);
+}
+#else
+int extract_mkdir(const char* path, int mode)
+{
+ return mkdir(path, mode);
+}
+#endif