fileio.c (4816B)
1 #include <string.h> 2 #include <stdio.h> 3 4 /* Ensures portable headers are included such as inline. */ 5 #include "config.h" 6 #include "fileio.h" 7 #include "pstrutil.h" 8 9 char *fb_copy_path_n(const char *path, size_t len) 10 { 11 size_t n; 12 char *s; 13 14 n = strnlen(path, len); 15 if ((s = malloc(n + 1))) { 16 memcpy(s, path, n); 17 s[n] = '\0'; 18 } 19 return s; 20 } 21 22 char *fb_copy_path(const char *path) 23 { 24 size_t n; 25 char *s; 26 27 n = strlen(path); 28 if ((s = malloc(n + 1))) { 29 memcpy(s, path, n); 30 s[n] = '\0'; 31 } 32 return s; 33 } 34 35 size_t fb_chomp(const char *path, size_t len, const char *ext) 36 { 37 size_t ext_len = ext ? strlen(ext) : 0; 38 if (len > ext_len && 0 == strncmp(path + len - ext_len, ext, ext_len)) { 39 len -= ext_len; 40 } 41 return len; 42 } 43 44 char *fb_create_join_path_n(const char *prefix, size_t prefix_len, 45 const char *suffix, size_t suffix_len, const char *ext, int path_sep) 46 { 47 char *path; 48 size_t ext_len = ext ? strlen(ext) : 0; 49 size_t n; 50 51 if (!prefix || 52 (suffix_len > 0 && (suffix[0] == '/' || suffix[0] == '\\')) || 53 (suffix_len > 1 && suffix[1] == ':')) { 54 prefix_len = 0; 55 } 56 if (path_sep && (prefix_len == 0 || 57 (prefix[prefix_len - 1] == '/' || prefix[prefix_len - 1] == '\\'))) { 58 path_sep = 0; 59 } 60 path = malloc(prefix_len + !!path_sep + suffix_len + ext_len + 1); 61 if (!path) { 62 return 0; 63 } 64 n = 0; 65 if (prefix_len > 0) { 66 memcpy(path, prefix, prefix_len); 67 n += prefix_len; 68 } 69 if (path_sep) { 70 path[n++] = '/'; 71 } 72 memcpy(path + n, suffix, suffix_len); 73 n += suffix_len; 74 memcpy(path + n, ext, ext_len); 75 n += ext_len; 76 path[n] = '\0'; 77 return path; 78 } 79 80 char *fb_create_join_path(const char *prefix, const char *suffix, const char *ext, int path_sep) 81 { 82 return fb_create_join_path_n(prefix, prefix ? strlen(prefix) : 0, 83 suffix, suffix ? strlen(suffix) : 0, ext, path_sep); 84 } 85 86 char *fb_create_path_ext_n(const char *path, size_t path_len, const char *ext) 87 { 88 return fb_create_join_path_n(0, 0, path, path_len, ext, 0); 89 } 90 91 char *fb_create_path_ext(const char *path, const char *ext) 92 { 93 return fb_create_join_path(0, path, ext, 0); 94 } 95 96 char *fb_create_make_path_n(const char *path, size_t len) 97 { 98 size_t i, j, n; 99 char *s; 100 101 if (len == 1 && (path[0] == ' ' || path[0] == '\\')) { 102 if (!(s = malloc(3))) { 103 return 0; 104 } 105 s[0] = '\\'; 106 s[1] = path[0]; 107 s[2] = '\0'; 108 return s; 109 } 110 if (len <= 1) { 111 return fb_copy_path_n(path, len); 112 } 113 for (i = 0, n = len; i < len - 1; ++i) { 114 if (path[i] == '\\' && path[i + 1] == ' ') { 115 ++n; 116 } 117 n += path[i] == ' '; 118 } 119 n += path[i] == ' '; 120 if (!(s = malloc(n + 1))) { 121 return 0; 122 } 123 for (i = 0, j = 0; i < len - 1; ++i, ++j) { 124 if (path[i] == '\\' && path[i + 1] == ' ') { 125 s[j++] = '\\'; 126 } 127 if (path[i] == ' ') { 128 s[j++] = '\\'; 129 } 130 s[j] = path[i]; 131 } 132 if (path[i] == ' ') { 133 s[j++] = '\\'; 134 } 135 s[j++] = path[i]; 136 s[j] = 0; 137 return s; 138 } 139 140 char *fb_create_make_path(const char *path) 141 { 142 return fb_create_make_path_n(path, strlen(path)); 143 } 144 145 size_t fb_find_basename(const char *path, size_t len) 146 { 147 char *p = (char *)path; 148 149 p += len; 150 while(p != path) { 151 --p; 152 if (*p == '/' || *p == '\\') { 153 ++p; 154 break; 155 } 156 } 157 return (size_t)(p - path); 158 } 159 160 char *fb_create_basename(const char *path, size_t len, const char *ext) 161 { 162 size_t pos; 163 char *s; 164 165 pos = fb_find_basename(path, len); 166 path += pos; 167 len -= pos; 168 len = fb_chomp(path, len, ext); 169 if ((s = malloc(len + 1))) { 170 memcpy(s, path, len); 171 s[len] = '\0'; 172 } 173 return s; 174 } 175 176 char *fb_read_file(const char *filename, size_t max_size, size_t *size_out) 177 { 178 FILE *fp; 179 long k; 180 size_t size, pos, n, _out; 181 char *buf; 182 183 size_out = size_out ? size_out : &_out; 184 185 fp = fopen(filename, "rb"); 186 size = 0; 187 buf = 0; 188 189 if (!fp) { 190 goto fail; 191 } 192 fseek(fp, 0L, SEEK_END); 193 k = ftell(fp); 194 if (k < 0) goto fail; 195 size = (size_t)k; 196 *size_out = size; 197 if (max_size > 0 && size > max_size) { 198 goto fail; 199 } 200 rewind(fp); 201 buf = malloc(size ? size : 1); 202 if (!buf) { 203 goto fail; 204 } 205 pos = 0; 206 while ((n = fread(buf + pos, 1, size - pos, fp))) { 207 pos += n; 208 } 209 if (pos != size) { 210 goto fail; 211 } 212 fclose(fp); 213 *size_out = size; 214 return buf; 215 216 fail: 217 if (fp) { 218 fclose(fp); 219 } 220 if (buf) { 221 free(buf); 222 } 223 *size_out = size; 224 return 0; 225 }