librazor/uri-io.c
changeset 478 8e4bf84a7bb8
parent 475 008c75a5e08d
child 479 4204db81cdbc
     1.1 --- a/librazor/uri-io.c	Mon Jul 04 10:48:18 2016 +0100
     1.2 +++ b/librazor/uri-io.c	Thu Jul 07 11:04:10 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;