1.1 --- a/librazor/uri-io.c Mon Jul 04 10:48:18 2016 +0100
1.2 +++ b/librazor/uri-io.c Tue Jul 05 09:40:01 2016 +0100
1.3 @@ -38,6 +38,10 @@
1.4 #if HAVE_SYS_MMAN_H
1.5 #include <sys/mman.h>
1.6 #endif
1.7 +#if HAVE_LIBARCHIVE
1.8 +#include <archive.h>
1.9 +#include <archive_entry.h>
1.10 +#endif
1.11 #include <assert.h>
1.12
1.13 #include "razor.h"
1.14 @@ -51,6 +55,130 @@
1.15 #define strcmp0(s1, s2) ((s1) && (s2) ? strcmp(s1, s2) : \
1.16 (s1) ? 1 : (s2) ? -1 : 0)
1.17
1.18 +#if HAVE_LIBARCHIVE
1.19 +static void *
1.20 +razor_archive_get_file_contents(const char *filename, int fd, const char *path,
1.21 + size_t *length, struct razor_error **error)
1.22 +{
1.23 + int r;
1.24 + void *addr;
1.25 + const void *buf;
1.26 + size_t size;
1.27 + off_t offset;
1.28 + struct archive *a;
1.29 + struct archive_entry *entry;
1.30 +
1.31 + a = archive_read_new();
1.32 + archive_read_support_compression_all(a);
1.33 + archive_read_support_format_all(a);
1.34 +
1.35 + r = archive_read_open_fd(a, fd, 10240);
1.36 +
1.37 + if (r) {
1.38 + razor_set_error(error, RAZOR_POSIX_ERROR, archive_errno(a),
1.39 + filename, archive_error_string(a));
1.40 + archive_read_finish(a);
1.41 + return NULL;
1.42 + }
1.43 +
1.44 + for (;;) {
1.45 + r = archive_read_next_header(a, &entry);
1.46 + if (r == ARCHIVE_EOF)
1.47 + break;
1.48 + else if (r < ARCHIVE_WARN) {
1.49 + razor_set_error(error, RAZOR_POSIX_ERROR,
1.50 + archive_errno(a), filename,
1.51 + archive_error_string(a));
1.52 + archive_read_close(a);
1.53 + archive_read_finish(a);
1.54 + return NULL;
1.55 + }
1.56 +
1.57 + /*
1.58 + * TODO: Unicode support. Might need to wait for libarchive v4.
1.59 + */
1.60 + if (!strcmp(archive_entry_pathname(entry), path)) {
1.61 + addr = malloc(archive_entry_size(entry));
1.62 + if (!addr) {
1.63 + archive_read_close(a);
1.64 + archive_read_finish(a);
1.65 + razor_set_error(error, RAZOR_POSIX_ERROR,
1.66 + ENOMEM, NULL,
1.67 + "Not enough memory");
1.68 + return NULL;
1.69 + }
1.70 +
1.71 + for(;;) {
1.72 + r = archive_read_data_block(a, &buf, &size,
1.73 + &offset);
1.74 + if (r == ARCHIVE_EOF)
1.75 + break;
1.76 + if (r < ARCHIVE_OK) {
1.77 + razor_set_error(error, RAZOR_POSIX_ERROR,
1.78 + archive_errno(a), path,
1.79 + archive_error_string(a));
1.80 + free(addr);
1.81 + addr = NULL;
1.82 + break;
1.83 + }
1.84 + memcpy((char *)addr + offset, buf, size);
1.85 + }
1.86 +
1.87 + archive_read_close(a);
1.88 + archive_read_finish(a);
1.89 +
1.90 + return addr;
1.91 + }
1.92 + }
1.93 +
1.94 + archive_read_close(a);
1.95 + archive_read_finish(a);
1.96 +
1.97 + razor_set_error(error, RAZOR_POSIX_ERROR, ENOENT, path,
1.98 + "No such file or directory in archive");
1.99 +
1.100 + return NULL;
1.101 +}
1.102 +
1.103 +static void *
1.104 +razor_file_get_contents_archive(const char *filename, size_t *length,
1.105 + struct razor_error **error)
1.106 +{
1.107 + int fd;
1.108 + char *path, *slash, *s;
1.109 + void *addr;
1.110 +
1.111 + path = strdup(filename);
1.112 + slash = strrchr(path, '/');
1.113 +
1.114 + while (slash) {
1.115 + *slash = '\0';
1.116 + fd = open(path, O_RDONLY | O_BINARY);
1.117 + if (fd >= 0) {
1.118 + addr = razor_archive_get_file_contents(path, fd,
1.119 + slash + 1,
1.120 + length, error);
1.121 + free(path);
1.122 + close(fd);
1.123 + return addr;
1.124 + } else if (errno != ENOTDIR) {
1.125 + free(path);
1.126 + razor_set_error_posix(error, filename);
1.127 + return NULL;
1.128 + }
1.129 + s = strrchr(path, '/');
1.130 + *slash = '/';
1.131 + slash = s;
1.132 + }
1.133 +
1.134 + /* Impossible */
1.135 + free(path);
1.136 + razor_set_error(error, RAZOR_POSIX_ERROR, ENOTDIR, filename,
1.137 + strerror(ENOTDIR));
1.138 + return NULL;
1.139 +}
1.140 +#endif
1.141 +
1.142 #define OPEN_FILE_USED (1U<<0)
1.143 #define OPEN_FILE_MMAPPED (1U<<1)
1.144
1.145 @@ -68,24 +196,33 @@
1.146 int fd;
1.147 struct stat st;
1.148 void *addr = NULL;
1.149 - size_t nb;
1.150 + size_t nb, size;
1.151 ssize_t res;
1.152 struct open_file *of, *ofend;
1.153
1.154 fd = open(filename, O_RDONLY | O_BINARY);
1.155 if (fd < 0) {
1.156 +#if HAVE_LIBARCHIVE
1.157 + if (errno != ENOTDIR) {
1.158 + razor_set_error_posix(error, filename);
1.159 + return NULL;
1.160 + }
1.161 + addr = razor_file_get_contents_archive(filename, &size, error);
1.162 + if (!addr)
1.163 + return NULL;
1.164 +#else
1.165 razor_set_error_posix(error, filename);
1.166 return NULL;
1.167 +#endif
1.168 + } else {
1.169 + if (fstat(fd, &st) < 0) {
1.170 + razor_set_error_posix(error, filename);
1.171 + close(fd);
1.172 + return NULL;
1.173 + }
1.174 + size = st.st_size;
1.175 }
1.176
1.177 - if (fstat(fd, &st) < 0) {
1.178 - razor_set_error_posix(error, filename);
1.179 - close(fd);
1.180 - return NULL;
1.181 - }
1.182 -
1.183 - *length = st.st_size;
1.184 -
1.185 ofend = open_files.data + open_files.size;
1.186 for (of = open_files.data; of < ofend; of++)
1.187 if (!(of->flags & OPEN_FILE_USED))
1.188 @@ -96,21 +233,21 @@
1.189 }
1.190
1.191 #if HAVE_SYS_MMAN_H
1.192 - if (!private) {
1.193 - addr = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
1.194 + if (!addr && !private) {
1.195 + addr = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
1.196 if (addr == MAP_FAILED)
1.197 addr = NULL;
1.198 else
1.199 of->flags = OPEN_FILE_USED | OPEN_FILE_MMAPPED;
1.200 }
1.201 #endif /* HAVE_SYS_MMAN_H */
1.202 +
1.203 if (!addr) {
1.204 - addr = malloc(st.st_size);
1.205 + addr = malloc(size);
1.206 if (addr) {
1.207 - of->flags = OPEN_FILE_USED;
1.208 nb = 0;
1.209 - while(nb < st.st_size) {
1.210 - res = read(fd, addr + nb, st.st_size - nb);
1.211 + while(nb < size) {
1.212 + res = read(fd, addr + nb, size - nb);
1.213 if (res <= 0) {
1.214 razor_set_error_posix(error, filename);
1.215 free(addr);
1.216 @@ -119,14 +256,21 @@
1.217 }
1.218 nb += res;
1.219 }
1.220 + if (addr)
1.221 + of->flags = OPEN_FILE_USED;
1.222 } else
1.223 razor_set_error(error, RAZOR_POSIX_ERROR, ENOMEM, NULL,
1.224 "Not enough memory");
1.225 }
1.226 - close(fd);
1.227 +
1.228 + if (fd >= 0)
1.229 + close(fd);
1.230
1.231 of->addr = addr;
1.232 - of->length = st.st_size;
1.233 + of->length = size;
1.234 +
1.235 + if (addr)
1.236 + *length = size;
1.237
1.238 return addr;
1.239 }
1.240 @@ -659,7 +803,8 @@
1.241 return fallback;
1.242 }
1.243
1.244 -int razor_uri_mkdir(const char *uri, mode_t mode, struct razor_error **error)
1.245 +RAZOR_EXPORT int
1.246 +razor_uri_mkdir(const char *uri, mode_t mode, struct razor_error **error)
1.247 {
1.248 int retval;
1.249 char *path;
1.250 @@ -700,7 +845,8 @@
1.251 return retval;
1.252 }
1.253
1.254 -int razor_uri_unlink(const char *uri, struct razor_error **error)
1.255 +RAZOR_EXPORT int
1.256 +razor_uri_unlink(const char *uri, struct razor_error **error)
1.257 {
1.258 int retval;
1.259 char *path;
1.260 @@ -741,8 +887,9 @@
1.261 return retval;
1.262 }
1.263
1.264 -int razor_uri_open(const char *uri, int flags, mode_t mode,
1.265 - struct razor_error **error)
1.266 +RAZOR_EXPORT int
1.267 +razor_uri_open(const char *uri, int flags, mode_t mode,
1.268 + struct razor_error **error)
1.269 {
1.270 int retval;
1.271 char *path;
1.272 @@ -783,8 +930,9 @@
1.273 return retval;
1.274 }
1.275
1.276 -int razor_uri_move(const char *src_uri, const char *dst_uri,
1.277 - struct razor_error **error)
1.278 +RAZOR_EXPORT int
1.279 +razor_uri_move(const char *src_uri, const char *dst_uri,
1.280 + struct razor_error **error)
1.281 {
1.282 int retval;
1.283 char *src_path, *dst_path;
1.284 @@ -851,8 +999,9 @@
1.285 return retval;
1.286 }
1.287
1.288 -void *razor_uri_get_contents(const char *uri, size_t *length, int private,
1.289 - struct razor_error **error)
1.290 +RAZOR_EXPORT void *
1.291 +razor_uri_get_contents(const char *uri, size_t *length, int private,
1.292 + struct razor_error **error)
1.293 {
1.294 void *retval;
1.295 char *path;
1.296 @@ -897,7 +1046,7 @@
1.297 return retval;
1.298 }
1.299
1.300 -int razor_uri_free_contents(void *addr, size_t length)
1.301 +RAZOR_EXPORT int razor_uri_free_contents(void *addr, size_t length)
1.302 {
1.303 int retval, of;
1.304 struct razor_uri_vtable_entry *entry, *eend;
1.305 @@ -925,7 +1074,8 @@
1.306 return retval;
1.307 }
1.308
1.309 -int razor_uri_is_directory(const char *uri, struct razor_error **error)
1.310 +RAZOR_EXPORT int
1.311 +razor_uri_is_directory(const char *uri, struct razor_error **error)
1.312 {
1.313 int retval;
1.314 char *path;
1.315 @@ -966,8 +1116,9 @@
1.316 return retval;
1.317 }
1.318
1.319 -char *razor_uri_mkdtemp_near(const char *uri, const char *template,
1.320 - struct razor_error **error)
1.321 +RAZOR_EXPORT char *
1.322 +razor_uri_mkdtemp_near(const char *uri, const char *template,
1.323 + struct razor_error **error)
1.324 {
1.325 char *retval, *s;
1.326 char *path;
1.327 @@ -1011,7 +1162,8 @@
1.328 return retval;
1.329 }
1.330
1.331 -void *razor_uri_opendir(const char *uri, struct razor_error **error)
1.332 +RAZOR_EXPORT void *
1.333 +razor_uri_opendir(const char *uri, struct razor_error **error)
1.334 {
1.335 void *retval;
1.336 char *path;
1.337 @@ -1055,7 +1207,7 @@
1.338 return retval;
1.339 }
1.340
1.341 -char *razor_uri_readdir(void *dir, struct razor_error **error)
1.342 +RAZOR_EXPORT char *razor_uri_readdir(void *dir, struct razor_error **error)
1.343 {
1.344 int od;
1.345 char *retval;
1.346 @@ -1086,7 +1238,7 @@
1.347 return retval;
1.348 }
1.349
1.350 -int razor_uri_closedir(void *dir, struct razor_error **error)
1.351 +RAZOR_EXPORT int razor_uri_closedir(void *dir, struct razor_error **error)
1.352 {
1.353 int od;
1.354 int retval;