summaryrefslogtreecommitdiff
blob: 2359acab8860e3e9795348a78ebe413261ce7f36 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
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