1.1 --- a/librazor/Makefile.am Sat Jun 11 17:56:48 2016 +0100
1.2 +++ b/librazor/Makefile.am Mon Jul 04 10:48:18 2016 +0100
1.3 @@ -14,7 +14,7 @@
1.4 -DPACKAGE_LIB_DIR=\""$(libdir)"\"
1.5
1.6 lib_LTLIBRARIES = librazor.la
1.7 -check_PROGRAMS = test-pfu
1.8 +check_PROGRAMS = test-pfu test-uri
1.9 if HAVE_LUA
1.10 check_PROGRAMS += test-lua
1.11 endif
1.12 @@ -30,11 +30,14 @@
1.13
1.14 librazor_la_SOURCES = \
1.15 razor-internal.h \
1.16 + uri.h \
1.17 razor.h \
1.18 razor.c \
1.19 root.c \
1.20 dump.c \
1.21 util.c \
1.22 + uri-io.c \
1.23 + uri.c \
1.24 path.c \
1.25 rpm.c \
1.26 iterator.c \
1.27 @@ -58,15 +61,22 @@
1.28 -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
1.29
1.30 test_pfu_SOURCES = test-pfu.c
1.31 -test_pfu_LDADD = path.lo util.lo error.lo types/libtypes.la \
1.32 +test_pfu_LDADD = path.lo uri.lo util.lo error.lo types/libtypes.la \
1.33 ../gl/libgnu.la $(INTLLIBS) $(EXTRA_LIBS)
1.34
1.35 TESTS = test-pfu
1.36
1.37 +test_uri_SOURCES = test-uri.c
1.38 +test_uri_CFLAGS = $(AM_CFLAGS)
1.39 +test_uri_LDADD = uri.lo util.lo path.lo error.lo types/libtypes.la \
1.40 + $(LUA_LIBS) ../gl/libgnu.la $(INTLLIBS) $(EXTRA_LIBS)
1.41 +
1.42 +TESTS += test-uri
1.43 +
1.44 if HAVE_LUA
1.45 test_lua_SOURCES = test-lua.c
1.46 - test_lua_LDADD = lua.lo util.lo error.lo types/libtypes.la $(LUA_LIBS) \
1.47 - ../gl/libgnu.la $(INTLLIBS) $(EXTRA_LIBS)
1.48 + test_lua_LDADD = lua.lo uri.lo uri-io.lo util.lo path.lo error.lo \
1.49 + types/libtypes.la $(LUA_LIBS) ../gl/libgnu.la $(INTLLIBS) $(EXTRA_LIBS)
1.50
1.51 TESTS += test-lua
1.52 endif
2.1 --- a/librazor/atomic-actions.c Sat Jun 11 17:56:48 2016 +0100
2.2 +++ b/librazor/atomic-actions.c Mon Jul 04 10:48:18 2016 +0100
2.3 @@ -1,5 +1,5 @@
2.4 /*
2.5 - * Copyright (C) 2012 J. Ali Harlow <ali@juiblex.co.uk>
2.6 + * Copyright (C) 2012, 2016 J. Ali Harlow <ali@juiblex.co.uk>
2.7 *
2.8 * This program is free software; you can redistribute it and/or modify
2.9 * it under the terms of the GNU General Public License as published by
2.10 @@ -25,9 +25,6 @@
2.11 #include <string.h>
2.12 #include <limits.h>
2.13 #include <errno.h>
2.14 -#include <sys/stat.h>
2.15 -#include <sys/types.h>
2.16 -#include <dirent.h>
2.17 #include <assert.h>
2.18 #include "razor-internal.h"
2.19
2.20 @@ -87,7 +84,7 @@
2.21 while(action) {
2.22 a = atomic_action_list_pop_head(&action);
2.23
2.24 - free(a->args.path);
2.25 + free(a->args.uri);
2.26
2.27 switch(a->type) {
2.28 case ACTION_MAKE_DIRS:
2.29 @@ -166,13 +163,11 @@
2.30
2.31 strcpy(buffer, action->args.u.make_dirs.root);
2.32 p = buffer + strlen(buffer);
2.33 - slash = action->args.path;
2.34 + slash = action->args.uri;
2.35 + if (p > buffer && p[-1] != ':' && p[-1] != '/' && *slash != '/')
2.36 + *p++ = '/';
2.37 for (; *slash != '\0'; slash = next) {
2.38 -#ifdef MSWIN_API
2.39 - next = strpbrk(slash + 1, "/\\");
2.40 -#else
2.41 next = strchr(slash + 1, '/');
2.42 -#endif
2.43 if (next == NULL)
2.44 break;
2.45
2.46 @@ -184,7 +179,7 @@
2.47 continue;
2.48
2.49 prim = atomic_action_new(ACTION_CREATE_DIR);
2.50 - prim->args.path = strdup(buffer);
2.51 + prim->args.uri = strdup(buffer);
2.52 prim->args.u.create_dir.mode = S_IRWXU | S_IRWXG | S_IRWXO;
2.53 primitives = atomic_action_list_prepend(primitives, prim);
2.54 }
2.55 @@ -198,12 +193,8 @@
2.56 static struct atomic_action *
2.57 atomic_action_remove(struct razor_atomic *atomic, struct atomic_action *action)
2.58 {
2.59 -#ifdef MSWIN_API
2.60 - wchar_t *path;
2.61 - _WDIR *dir;
2.62 -#else
2.63 - DIR *dir;
2.64 -#endif
2.65 + void *dir;
2.66 + char *name;
2.67 struct atomic_action *prim;
2.68
2.69 if (razor_atomic_in_error_state(atomic)) {
2.70 @@ -214,27 +205,20 @@
2.71 /*
2.72 * Non-empty directories should NOT be removed
2.73 */
2.74 -#ifdef MSWIN_API
2.75 - path = razor_utf8_to_utf16(action->args.path, -1);
2.76 -
2.77 - dir = _wopendir(path);
2.78 - if (dir && _wreaddir(dir)) {
2.79 - atomic_action_free(action);
2.80 - action = NULL;
2.81 + dir = razor_uri_opendir(action->args.uri, NULL);
2.82 + if (dir) {
2.83 + name = razor_uri_readdir(dir, NULL);
2.84 + razor_uri_closedir(dir, NULL);
2.85 + if (name) {
2.86 + free(name);
2.87 + atomic_action_free(action);
2.88 + action = NULL;
2.89 + }
2.90 }
2.91 - _wclosedir(dir);
2.92 -#else
2.93 - dir = opendir(action->args.path);
2.94 - if (dir && readdir(dir)) {
2.95 - atomic_action_free(action);
2.96 - action = NULL;
2.97 - }
2.98 - closedir(dir);
2.99 -#endif
2.100
2.101 if (action) {
2.102 prim = atomic_action_new(ACTION_MOVE);
2.103 - prim->args.path = strdup(action->args.path);
2.104 + prim->args.uri = strdup(action->args.uri);
2.105 prim->args.u.move.dest = atomic_action_attic_tmpnam(atomic);
2.106
2.107 atomic_action_free(action);
2.108 @@ -249,7 +233,7 @@
2.109 struct atomic_action *action)
2.110 {
2.111 mode_t mode;
2.112 - struct stat buf;
2.113 + struct razor_error **error;
2.114
2.115 if (razor_atomic_in_error_state(atomic)) {
2.116 atomic_action_free(action);
2.117 @@ -258,21 +242,14 @@
2.118
2.119 mode = action->args.u.create_dir.mode & (S_IRWXU | S_IRWXG | S_IRWXO);
2.120
2.121 - if (!mkdir(action->args.path, mode))
2.122 + if (atomic->error)
2.123 + error = NULL;
2.124 + else
2.125 + error = &atomic->error;
2.126 +
2.127 + if (!razor_uri_mkdir(action->args.uri, mode, error))
2.128 return action;
2.129
2.130 - if (errno != EEXIST || stat(action->args.path, &buf)) {
2.131 - if (!atomic->error)
2.132 - atomic->error = razor_error_new_posix(action->args.path);
2.133 - atomic_action_free(action);
2.134 - return NULL;
2.135 - }
2.136 -
2.137 - if (!S_ISDIR(buf.st_mode) && !atomic->error)
2.138 - atomic->error = razor_error_new_str(RAZOR_POSIX_ERROR, EEXIST,
2.139 - action->args.path,
2.140 - "Not a directory");
2.141 -
2.142 atomic_action_free(action);
2.143 return NULL;
2.144 }
2.145 @@ -285,9 +262,9 @@
2.146 return NULL;
2.147 }
2.148
2.149 - if (rmdir(action->args.path) < 0) {
2.150 + if (rmdir(action->args.uri) < 0) {
2.151 if (!atomic->error)
2.152 - atomic->error = razor_error_new_posix(action->args.path);
2.153 + atomic->error = razor_error_new_posix(action->args.uri);
2.154 atomic_action_free(action);
2.155 return NULL;
2.156 } else
2.157 @@ -306,10 +283,10 @@
2.158 return NULL;
2.159 }
2.160
2.161 - r = symlink(action->args.u.create_symlink.target, action->args.path);
2.162 + r = symlink(action->args.u.create_symlink.target, action->args.uri);
2.163 if (r < 0) {
2.164 if (!atomic->error)
2.165 - atomic->error = razor_error_new_posix(action->args.path);
2.166 + atomic->error = razor_error_new_posix(action->args.uri);
2.167 atomic_action_free(action);
2.168 return NULL;
2.169 }
2.170 @@ -321,14 +298,19 @@
2.171 atomic_action_remove_symlink(struct razor_atomic *atomic,
2.172 struct atomic_action *action)
2.173 {
2.174 + struct razor_error **error;
2.175 +
2.176 if (razor_atomic_in_error_state(atomic)) {
2.177 atomic_action_free(action);
2.178 return NULL;
2.179 }
2.180
2.181 - if (unlink(action->args.path) < 0) {
2.182 - if (!atomic->error)
2.183 - atomic->error = razor_error_new_posix(action->args.path);
2.184 + if (atomic->error)
2.185 + error = NULL;
2.186 + else
2.187 + error = &atomic->error;
2.188 +
2.189 + if (razor_uri_unlink(action->args.uri, error)) {
2.190 atomic_action_free(action);
2.191 return NULL;
2.192 }
2.193 @@ -338,52 +320,16 @@
2.194 #endif
2.195
2.196 static int
2.197 -move_file(struct razor_atomic *atomic, const char *path, const char *dest)
2.198 +move_file(struct razor_atomic *atomic, const char *uri, const char *dest)
2.199 {
2.200 -#ifdef MSWIN_API
2.201 - wchar_t *oldbuf, *newbuf;
2.202 - const DWORD flags = MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING;
2.203 + struct razor_error **error;
2.204
2.205 - newbuf = razor_utf8_to_utf16(dest, -1);
2.206 - oldbuf = razor_utf8_to_utf16(path, -1);
2.207 + if (atomic->error)
2.208 + error = NULL;
2.209 + else
2.210 + error = &atomic->error;
2.211
2.212 - /*
2.213 - * Passing MOVEFILE_REPLACE_EXISTING to MoveFileEx() will
2.214 - * cover every case we care about _except_ replacing an empty
2.215 - * directory with a file. Calling RemoveDirectory() will deal
2.216 - * with this case while having no effect in all other cases.
2.217 - */
2.218 - (void)RemoveDirectoryW(newbuf);
2.219 -
2.220 - if (!MoveFileExW(oldbuf, newbuf, flags)) {
2.221 - if (!atomic->error)
2.222 - atomic->error = razor_error_new_mswin(newbuf,
2.223 - GetLastError());
2.224 - return -1;
2.225 - }
2.226 -
2.227 - free(newbuf);
2.228 - free(oldbuf);
2.229 -#else
2.230 - int code;
2.231 - const char *object;
2.232 -
2.233 - if (rename(path, dest)) {
2.234 - if (!atomic->error) {
2.235 - code = errno;
2.236 - if (access(path, F_OK) < 0)
2.237 - object = path;
2.238 - else
2.239 - object = dest;
2.240 - atomic->error = razor_error_new_str(RAZOR_POSIX_ERROR,
2.241 - code, object,
2.242 - strerror(code));
2.243 - }
2.244 - return -1;
2.245 - }
2.246 -#endif
2.247 -
2.248 - return 0;
2.249 + return razor_uri_move(uri, dest, error);
2.250 }
2.251
2.252 static struct atomic_action *
2.253 @@ -394,7 +340,7 @@
2.254 return NULL;
2.255 }
2.256
2.257 - if (move_file(atomic, action->args.path, action->args.u.move.dest)) {
2.258 + if (move_file(atomic, action->args.uri, action->args.u.move.dest)) {
2.259 atomic_action_free(action);
2.260 return NULL;
2.261 }
2.262 @@ -410,7 +356,7 @@
2.263 return NULL;
2.264 }
2.265
2.266 - if (move_file(atomic, action->args.u.move.dest, action->args.path)) {
2.267 + if (move_file(atomic, action->args.u.move.dest, action->args.uri)) {
2.268 atomic_action_free(action);
2.269 return NULL;
2.270 }
3.1 --- a/librazor/atomic-emulate.c Sat Jun 11 17:56:48 2016 +0100
3.2 +++ b/librazor/atomic-emulate.c Mon Jul 04 10:48:18 2016 +0100
3.3 @@ -1,5 +1,5 @@
3.4 /*
3.5 - * Copyright (C) 2012, 2014 J. Ali Harlow <ali@juiblex.co.uk>
3.6 + * Copyright (C) 2012, 2014, 2016 J. Ali Harlow <ali@juiblex.co.uk>
3.7 *
3.8 * This program is free software; you can redistribute it and/or modify
3.9 * it under the terms of the GNU General Public License as published by
3.10 @@ -24,12 +24,7 @@
3.11 #include <stdio.h>
3.12 #include <string.h>
3.13 #include <unistd.h>
3.14 -#include <sys/types.h>
3.15 -#include <sys/stat.h>
3.16 #include <fcntl.h>
3.17 -#include <dirent.h>
3.18 -#include <errno.h>
3.19 -#include <unistd.h>
3.20 #include "razor-internal.h"
3.21
3.22 /*
3.23 @@ -53,24 +48,23 @@
3.24
3.25 static void recursive_remove(const char *directory)
3.26 {
3.27 - DIR *dp;
3.28 - struct dirent *dirp;
3.29 - char *buf;
3.30 + void *dp;
3.31 + char *name, *buf;
3.32
3.33 - dp = opendir(directory);
3.34 - while((dirp = readdir(dp))) {
3.35 - if (strcmp(dirp->d_name, ".") && strcmp(dirp->d_name, "..")) {
3.36 - buf = malloc(strlen(directory) + strlen(dirp->d_name)
3.37 - + 2);
3.38 - sprintf(buf, "%s/%s", directory, dirp->d_name);
3.39 - if (remove(buf) < 0)
3.40 + dp = razor_uri_opendir(directory, NULL);
3.41 +
3.42 + if (dp) {
3.43 + while((name = razor_uri_readdir(dp, NULL))) {
3.44 + buf = razor_concat(directory, "/", name, NULL);
3.45 + free(name);
3.46 + if (razor_uri_unlink(buf, NULL) < 0)
3.47 recursive_remove(buf);
3.48 free(buf);
3.49 }
3.50 +
3.51 + razor_uri_closedir(dp, NULL);
3.52 }
3.53
3.54 - closedir(dp);
3.55 -
3.56 rmdir(directory);
3.57 }
3.58
3.59 @@ -129,53 +123,6 @@
3.60 free(atomic);
3.61 }
3.62
3.63 -#ifndef MSWIN_API
3.64 -static char *absolute_path(const char *path)
3.65 -{
3.66 - int len;
3.67 - char *result, *subpath, *p, *s, *t;
3.68 -
3.69 - result = realpath(path, NULL);
3.70 -
3.71 - if (!result && errno == ENOENT) {
3.72 - p = strdup(path);
3.73 - s = strrchr(p, '/');
3.74 -
3.75 - while (s) {
3.76 - if (s == p) {
3.77 - result = strdup("/");
3.78 - break;
3.79 - }
3.80 -
3.81 - *s = '\0';
3.82 - subpath = realpath(p, NULL);
3.83 -
3.84 - if (subpath) {
3.85 - *s = '/';
3.86 - len = strlen(subpath);
3.87 - result = malloc(len + strlen(s) + 1);
3.88 - memcpy(result, subpath, len);
3.89 - strcpy(result + len, s);
3.90 - free(subpath);
3.91 - break;
3.92 - } else if (errno != ENOENT)
3.93 - break;
3.94 -
3.95 - t = strrchr(p, '/');
3.96 - *s = '/';
3.97 - s = t;
3.98 - }
3.99 -
3.100 - if (!s)
3.101 - result = realpath(".", NULL);
3.102 -
3.103 - free(p);
3.104 - }
3.105 -
3.106 - return result;
3.107 -}
3.108 -#endif
3.109 -
3.110 /*
3.111 * We need a toplevel directory in which to hold temporary files
3.112 * before they are committed. Since we can generally assume that
3.113 @@ -186,14 +133,9 @@
3.114 */
3.115
3.116 static int
3.117 -razor_atomic_set_toplevel_from_path(struct razor_atomic *atomic,
3.118 - const char *path)
3.119 +razor_atomic_set_toplevel_from_uri(struct razor_atomic *atomic,
3.120 + const char *uri)
3.121 {
3.122 -#ifndef MSWIN_API
3.123 - dev_t filesystem;
3.124 - struct stat buf;
3.125 -#endif
3.126 -
3.127 if (razor_atomic_in_error_state(atomic))
3.128 return -1;
3.129
3.130 @@ -201,231 +143,113 @@
3.131 return 0;
3.132
3.133 #ifdef MSWIN_API
3.134 - if (path[0]=='\\' && path[1]=='\\' && path[2] && path[2]!='\\'
3.135 - && strchr(path+3,'\\')) {
3.136 - /* We have a UNC path: \\servername\sharename... */
3.137 - const char *sharename, *root;
3.138 - int disklen;
3.139 -
3.140 - sharename = strchr(path+3,'\\')+1;
3.141 - root = strchr(sharename,'\\');
3.142 - if (root)
3.143 - disklen = root - path;
3.144 - else
3.145 - disklen = strlen(path);
3.146 -
3.147 - atomic->toplevel =
3.148 - malloc(disklen + strlen("\\atomic-XXXXXX") + 1);
3.149 - memcpy(atomic->toplevel, path, disklen);
3.150 - strcpy(atomic->toplevel + disklen, "\\atomic-XXXXXX");
3.151 - } else if ((*path>='A' && *path<='Z' || *path>='a' && *path<='z') &&
3.152 - path[1]==':') {
3.153 - atomic->toplevel = strdup("X:\\atomic-XXXXXX");
3.154 - *atomic->toplevel = *path;
3.155 - } else {
3.156 - DWORD n;
3.157 - wchar_t *buf;
3.158 - char *dir;
3.159 -
3.160 - n = GetCurrentDirectoryW(0, NULL);
3.161 - buf = malloc(n * sizeof(wchar_t));
3.162 -
3.163 - if (GetCurrentDirectoryW(n, buf)) {
3.164 - dir = razor_utf16_to_utf8(buf, n - 1);
3.165 - razor_atomic_set_toplevel_from_path(atomic, dir);
3.166 -
3.167 - free(dir);
3.168 - free(buf);
3.169 - return;
3.170 - } else
3.171 - atomic->toplevel = strdup("C:\\atomic-XXXXXX");
3.172 -
3.173 - free(buf);
3.174 - }
3.175 + atomic->toplevel = razor_uri_mkdtemp_near(uri, "atomic-XXXXXX",
3.176 + &atomic->error);
3.177 #else
3.178 - {
3.179 - /*
3.180 - * Find the mount point (assuming we can write to the
3.181 - * whole filesystem). Otherwise stop at the first
3.182 - * unwritable directory and take one step back.
3.183 - */
3.184 - char *s, *abspath, saved;
3.185 - int len, can_step_back = 0;
3.186 -
3.187 - abspath = absolute_path(path);
3.188 - if (!abspath) {
3.189 - atomic->error = razor_error_new_posix(path);
3.190 - return -1;
3.191 - }
3.192 -
3.193 - if (stat(abspath, &buf) < 0) {
3.194 - if (errno == ENOENT)
3.195 - filesystem = 0;
3.196 - else {
3.197 - atomic->error = razor_error_new_posix(abspath);
3.198 - free(abspath);
3.199 - return -1;
3.200 - }
3.201 - } else
3.202 - filesystem = buf.st_dev;
3.203 -
3.204 - len = strlen(abspath);
3.205 - while(len > 1 && (s = strrchr(abspath, '/'))) {
3.206 - if (s == abspath) {
3.207 - saved = s[1];
3.208 - s[1] = '\0';
3.209 - len = s + 1 - abspath;
3.210 - } else {
3.211 - s[0] = '\0';
3.212 - len = s - abspath;
3.213 - }
3.214 -
3.215 - if (stat(abspath, &buf) < 0) {
3.216 - if (errno == ENOENT)
3.217 - continue;
3.218 - else {
3.219 - atomic->error = razor_error_new_posix(abspath);
3.220 - free(abspath);
3.221 - return -1;
3.222 - }
3.223 - } else if (!filesystem)
3.224 - filesystem = buf.st_dev;
3.225 -
3.226 - if (buf.st_dev != filesystem || access(abspath, W_OK)) {
3.227 - if (can_step_back) {
3.228 - if (s == abspath)
3.229 - s[1] = saved;
3.230 - else
3.231 - s[0] = '/';
3.232 - }
3.233 - len = strlen(abspath);
3.234 - break;
3.235 - } else
3.236 - can_step_back = 1;
3.237 - }
3.238 -
3.239 - if (len == 1)
3.240 - len = 0; /* Avoid an unslightly double slash. */
3.241 - atomic->toplevel = malloc(len + strlen("/.atomic-XXXXXX") + 1);
3.242 - memcpy(atomic->toplevel, abspath, len);
3.243 - strcpy(atomic->toplevel + len, "/.atomic-XXXXXX");
3.244 -
3.245 - free(abspath);
3.246 - }
3.247 + atomic->toplevel = razor_uri_mkdtemp_near(uri, ".atomic-XXXXXX",
3.248 + &atomic->error);
3.249 #endif
3.250
3.251 - if (!mkdtemp(atomic->toplevel)) {
3.252 - int err = errno;
3.253 -
3.254 -#ifdef EACCES
3.255 - if (err == EACCES) {
3.256 - char *s = strdup("atomic-XXXXXX");
3.257 -
3.258 -#ifndef MSWIN_API
3.259 - if (stat(".", &buf) < 0) {
3.260 - atomic->error = razor_error_new_posix(".");
3.261 - free(s);
3.262 - free(atomic->toplevel);
3.263 - atomic->toplevel = NULL;
3.264 - return -1;
3.265 - }
3.266 - if (buf.st_dev != filesystem)
3.267 - /*
3.268 - * Don't use a different filesystem. It will
3.269 - * only fail later on (in rename) and cause
3.270 - * an unhelpful error message (EXDEV).
3.271 - */
3.272 - free(s);
3.273 - else
3.274 -#endif
3.275 - if (mkdtemp(s)) {
3.276 - free(atomic->toplevel);
3.277 - atomic->toplevel = s;
3.278 - return 0;
3.279 - } else
3.280 - free(s);
3.281 - }
3.282 -#endif
3.283 -
3.284 - atomic->error = razor_error_new_str(RAZOR_POSIX_ERROR, err,
3.285 - atomic->toplevel,
3.286 - strerror(err));
3.287 -
3.288 - free(atomic->toplevel);
3.289 - atomic->toplevel = NULL;
3.290 - }
3.291 -
3.292 return !atomic->toplevel;
3.293 }
3.294
3.295 +/*
3.296 + * If root_uri is empty, then uri can be a URI (but not a relative-ref; ie.,
3.297 + * a scheme must be specified). If root_uri is non-empty, then it must be a
3.298 + * URI (but not a relative-ref) and uri must be a non-empty path.
3.299 + */
3.300 RAZOR_EXPORT int
3.301 -razor_atomic_make_dirs(struct razor_atomic *atomic, const char *root,
3.302 - const char *path)
3.303 +razor_atomic_make_dirs(struct razor_atomic *atomic, const char *root_uri,
3.304 + const char *uri)
3.305 {
3.306 struct atomic_action *a;
3.307 + struct razor_uri ru;
3.308 + struct razor_error *tmp_error = NULL;
3.309 + char *fakeroot = NULL;
3.310
3.311 - razor_atomic_set_toplevel_from_path(atomic, *root ? root : path);
3.312 + razor_atomic_set_toplevel_from_uri(atomic, *root_uri ? root_uri : uri);
3.313
3.314 if (razor_atomic_in_error_state(atomic))
3.315 return -1;
3.316
3.317 + if (!*root_uri) {
3.318 + if (razor_uri_parse(&ru, uri, &tmp_error)) {
3.319 + razor_atomic_propagate_error(atomic, tmp_error, NULL);
3.320 + return -1;
3.321 + }
3.322 + if (*ru.path == '/') {
3.323 + free(ru.path);
3.324 + ru.path = strdup("/");
3.325 + } else {
3.326 + free(ru.path);
3.327 + ru.path = strdup("");
3.328 + }
3.329 + fakeroot = razor_uri_recompose(&ru);
3.330 + razor_uri_destroy(&ru);
3.331 + root_uri = fakeroot;
3.332 + uri += strlen(fakeroot);
3.333 + }
3.334 +
3.335 a = atomic_action_new(ACTION_MAKE_DIRS);
3.336 - a->args.path = strdup(path);
3.337 - a->args.u.make_dirs.root = strdup(root);
3.338 + a->args.uri = strdup(uri);
3.339 + a->args.u.make_dirs.root = strdup(root_uri);
3.340 + atomic->actions = atomic_action_list_prepend(atomic->actions, a);
3.341 +
3.342 + if (fakeroot)
3.343 + free(fakeroot);
3.344 +
3.345 + return 0;
3.346 +}
3.347 +
3.348 +RAZOR_EXPORT int
3.349 +razor_atomic_remove(struct razor_atomic *atomic, const char *uri)
3.350 +{
3.351 + struct atomic_action *a;
3.352 +
3.353 + razor_atomic_set_toplevel_from_uri(atomic, uri);
3.354 +
3.355 + if (razor_atomic_in_error_state(atomic))
3.356 + return -1;
3.357 +
3.358 + a = atomic_action_new(ACTION_REMOVE);
3.359 + a->args.uri = strdup(uri);
3.360 atomic->actions = atomic_action_list_prepend(atomic->actions, a);
3.361
3.362 return 0;
3.363 }
3.364
3.365 RAZOR_EXPORT int
3.366 -razor_atomic_remove(struct razor_atomic *atomic, const char *path)
3.367 +razor_atomic_rename_file(struct razor_atomic *atomic, const char *old_uri,
3.368 + const char *new_uri)
3.369 {
3.370 struct atomic_action *a;
3.371
3.372 - razor_atomic_set_toplevel_from_path(atomic, path);
3.373 + razor_atomic_set_toplevel_from_uri(atomic, new_uri);
3.374
3.375 if (razor_atomic_in_error_state(atomic))
3.376 return -1;
3.377
3.378 - a = atomic_action_new(ACTION_REMOVE);
3.379 - a->args.path = strdup(path);
3.380 + a = atomic_action_new(ACTION_MOVE);
3.381 + a->args.uri = strdup(old_uri);
3.382 + a->args.u.move.dest = strdup(new_uri);
3.383 atomic->actions = atomic_action_list_prepend(atomic->actions, a);
3.384
3.385 return 0;
3.386 }
3.387
3.388 RAZOR_EXPORT int
3.389 -razor_atomic_rename_file(struct razor_atomic *atomic, const char *oldpath,
3.390 - const char *newpath)
3.391 -{
3.392 - struct atomic_action *a;
3.393 -
3.394 - razor_atomic_set_toplevel_from_path(atomic, newpath);
3.395 -
3.396 - if (razor_atomic_in_error_state(atomic))
3.397 - return -1;
3.398 -
3.399 - a = atomic_action_new(ACTION_MOVE);
3.400 - a->args.path = strdup(oldpath);
3.401 - a->args.u.move.dest = strdup(newpath);
3.402 - atomic->actions = atomic_action_list_prepend(atomic->actions, a);
3.403 -
3.404 - return 0;
3.405 -}
3.406 -
3.407 -RAZOR_EXPORT int
3.408 -razor_atomic_create_dir(struct razor_atomic *atomic, const char *dirname,
3.409 +razor_atomic_create_dir(struct razor_atomic *atomic, const char *uri,
3.410 mode_t mode)
3.411 {
3.412 struct atomic_action *a;
3.413
3.414 - razor_atomic_set_toplevel_from_path(atomic, dirname);
3.415 + razor_atomic_set_toplevel_from_uri(atomic, uri);
3.416
3.417 if (razor_atomic_in_error_state(atomic))
3.418 return -1;
3.419
3.420 a = atomic_action_new(ACTION_CREATE_DIR);
3.421 - a->args.path = strdup(dirname);
3.422 + a->args.uri = strdup(uri);
3.423 a->args.u.create_dir.mode = mode;
3.424 atomic->actions = atomic_action_list_prepend(atomic->actions, a);
3.425
3.426 @@ -434,12 +258,12 @@
3.427
3.428 RAZOR_EXPORT int
3.429 razor_atomic_create_symlink(struct razor_atomic *atomic, const char *target,
3.430 - const char *path)
3.431 + const char *uri)
3.432 {
3.433 #if HAVE_SYMLINK
3.434 struct atomic_action *a;
3.435
3.436 - razor_atomic_set_toplevel_from_path(atomic, path);
3.437 + razor_atomic_set_toplevel_from_uri(atomic, uri);
3.438 #endif
3.439
3.440 if (razor_atomic_in_error_state(atomic))
3.441 @@ -447,7 +271,7 @@
3.442
3.443 #if HAVE_SYMLINK
3.444 a = atomic_action_new(ACTION_CREATE_SYMLINK);
3.445 - a->args.path = strdup(path);
3.446 + a->args.uri = strdup(uri);
3.447 a->args.u.create_symlink.target = strdup(target);
3.448 atomic->actions = atomic_action_list_prepend(atomic->actions, a);
3.449
3.450 @@ -462,28 +286,27 @@
3.451 }
3.452
3.453 RAZOR_EXPORT int
3.454 -razor_atomic_create_file(struct razor_atomic *atomic, const char *filename,
3.455 +razor_atomic_create_file(struct razor_atomic *atomic, const char *uri,
3.456 mode_t mode)
3.457 {
3.458 int fd;
3.459 struct atomic_action *a;
3.460 char *tmpnam;
3.461
3.462 - razor_atomic_set_toplevel_from_path(atomic, filename);
3.463 + razor_atomic_set_toplevel_from_uri(atomic, uri);
3.464
3.465 if (razor_atomic_in_error_state(atomic))
3.466 return -1;
3.467
3.468 tmpnam = atomic_action_attic_tmpnam(atomic);
3.469 - fd = open(tmpnam, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
3.470 - mode & (S_IRWXU | S_IRWXG | S_IRWXO));
3.471 + fd = razor_uri_open(tmpnam, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
3.472 + mode & (S_IRWXU | S_IRWXG | S_IRWXO),
3.473 + &atomic->error);
3.474
3.475 - if (fd == -1)
3.476 - atomic->error = razor_error_new_posix(filename);
3.477 - else {
3.478 + if (fd >= 0) {
3.479 a = atomic_action_new(ACTION_MOVE);
3.480 - a->args.path = tmpnam;
3.481 - a->args.u.move.dest = strdup(filename);
3.482 + a->args.uri = tmpnam;
3.483 + a->args.u.move.dest = strdup(uri);
3.484 atomic->actions = atomic_action_list_prepend(atomic->actions,
3.485 a);
3.486 }
4.1 --- a/librazor/atomic-ktm.c Sat Jun 11 17:56:48 2016 +0100
4.2 +++ b/librazor/atomic-ktm.c Mon Jul 04 10:48:18 2016 +0100
4.3 @@ -24,10 +24,8 @@
4.4 #include <windows.h>
4.5 #include <stdio.h>
4.6 #include <limits.h>
4.7 +#include <unistd.h>
4.8 #include <errno.h>
4.9 -#include <unistd.h>
4.10 -#include <fcntl.h>
4.11 -#include <sys/stat.h>
4.12 #include <string.h>
4.13 #include <assert.h>
4.14 #include <wchar.h>
5.1 --- a/librazor/atomic-none.c Sat Jun 11 17:56:48 2016 +0100
5.2 +++ b/librazor/atomic-none.c Mon Jul 04 10:48:18 2016 +0100
5.3 @@ -244,8 +244,8 @@
5.4 if (razor_atomic_in_error_state(atomic))
5.5 return -1;
5.6
5.7 - fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
5.8 - mode & (S_IRWXU | S_IRWXG | S_IRWXO));
5.9 + fd = razor_uri_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
5.10 + mode & (S_IRWXU | S_IRWXG | S_IRWXO));
5.11
5.12 if (fd == -1)
5.13 atomic->error = razor_error_new_posix(filename);
6.1 --- a/librazor/atomic.c Sat Jun 11 17:56:48 2016 +0100
6.2 +++ b/librazor/atomic.c Mon Jul 04 10:48:18 2016 +0100
6.3 @@ -1,5 +1,5 @@
6.4 /*
6.5 - * Copyright (C) 2011-2012 J. Ali Harlow <ali@juiblex.co.uk>
6.6 + * Copyright (C) 2011-2012, 2016 J. Ali Harlow <ali@juiblex.co.uk>
6.7 *
6.8 * This program is free software; you can redistribute it and/or modify
6.9 * it under the terms of the GNU General Public License as published by
6.10 @@ -23,9 +23,6 @@
6.11 #include <limits.h>
6.12 #include <errno.h>
6.13 #include <unistd.h>
6.14 -#include <sys/types.h>
6.15 -#include <sys/stat.h>
6.16 -#include <fcntl.h>
6.17 #include <string.h>
6.18 #include <assert.h>
6.19
6.20 @@ -81,8 +78,15 @@
6.21 razor_atomic_propagate_error(struct razor_atomic *atomic,
6.22 struct razor_error *error, const char *summary)
6.23 {
6.24 - if (!atomic->error)
6.25 - atomic->error = razor_error_dup(error, summary);
6.26 + if (!atomic->error) {
6.27 + if (!summary) {
6.28 + atomic->error = error;
6.29 + return;
6.30 + } else
6.31 + atomic->error = razor_error_dup(error, summary);
6.32 + }
6.33 +
6.34 + razor_error_free(error);
6.35 }
6.36
6.37 RAZOR_EXPORT int
7.1 --- a/librazor/dump.c Sat Jun 11 17:56:48 2016 +0100
7.2 +++ b/librazor/dump.c Mon Jul 04 10:48:18 2016 +0100
7.3 @@ -1,5 +1,5 @@
7.4 /*
7.5 - * Copyright (C) 2014 J. Ali Harlow <ali@juiblex.co.uk>
7.6 + * Copyright (C) 2014, 2016 J. Ali Harlow <ali@juiblex.co.uk>
7.7 *
7.8 * This program is free software; you can redistribute it and/or modify
7.9 * it under the terms of the GNU General Public License as published by
7.10 @@ -356,11 +356,11 @@
7.11 }
7.12
7.13 RAZOR_EXPORT int
7.14 -razor_dump_database(FILE *fp, const char *root, const char *filename,
7.15 +razor_dump_database(FILE *fp, const char *root_uri, const char *filename,
7.16 struct razor_error **error)
7.17 {
7.18 int i;
7.19 - char *s, *path, *data;
7.20 + char *s, *uri, *data;
7.21 struct array pool = { 0, };
7.22 struct array string_pool = { 0, };
7.23 struct array file_string_pool = { 0, };
7.24 @@ -377,11 +377,14 @@
7.25 if (!filename)
7.26 filename = "system.rzdb";
7.27
7.28 - s = razor_concat(razor_get_database_path(), "/", filename, NULL);
7.29 - path = razor_path_add_root(s, root);
7.30 - free(s);
7.31 - contents = razor_file_get_contents(path, &length, 0, error);
7.32 - free(path);
7.33 + uri = razor_resolve_database_file(root_uri, filename, error);
7.34 +
7.35 + if (!uri)
7.36 + return -1;
7.37 +
7.38 + contents = razor_uri_get_contents(uri, &length, 0, error);
7.39 +
7.40 + free(uri);
7.41
7.42 if (!contents)
7.43 return -1;
7.44 @@ -482,7 +485,7 @@
7.45
7.46 fprintf(fp, "%05lX EOF\n", (unsigned long)n);
7.47
7.48 - razor_file_free_contents(contents, length);
7.49 + razor_uri_free_contents(contents, length);
7.50
7.51 return 0;
7.52 }
8.1 --- a/librazor/path.c Sat Jun 11 17:56:48 2016 +0100
8.2 +++ b/librazor/path.c Mon Jul 04 10:48:18 2016 +0100
8.3 @@ -1,5 +1,5 @@
8.4 /*
8.5 - * Copyright (C) 2014 J. Ali Harlow <ali@juiblex.co.uk>
8.6 + * Copyright (C) 2014, 2016 J. Ali Harlow <ali@juiblex.co.uk>
8.7 *
8.8 * This program is free software; you can redistribute it and/or modify
8.9 * it under the terms of the GNU General Public License as published by
8.10 @@ -19,78 +19,10 @@
8.11 #include "config.h"
8.12 #include <stdlib.h>
8.13 #include <string.h>
8.14 +#include <ctype.h>
8.15 #include "razor.h"
8.16 #include "razor-internal.h"
8.17 -
8.18 -/**
8.19 - * razor_path_add_root:
8.20 - *
8.21 - * Adds a root to a path. path must be an absolute pathname. In POSIX
8.22 - * environments this is equivalent to the concationation of root and path.
8.23 - * In Microsoft Windows an adjustment may need to be made for a drive letter
8.24 - * in path (which will be dropped).
8.25 - *
8.26 - * Returns: The new pathname.
8.27 - **/
8.28 -RAZOR_EXPORT char *razor_path_add_root(const char *path, const char *root)
8.29 -{
8.30 - if (root && *root)
8.31 - return razor_concat(root, SKIP_DRIVE_LETTER(path), NULL);
8.32 - else
8.33 - return strdup(path);
8.34 -}
8.35 -
8.36 -#if 0
8.37 -
8.38 -/*
8.39 - * This should work, but for some reason PathCreateFromUrlW()
8.40 - * treats the percent-encoded bytes as being in CP 850 rather
8.41 - * than UTF-8 as expected even if we set the codepage.
8.42 - */
8.43 -RAZOR_EXPORT char *razor_path_from_url(const char *url)
8.44 -{
8.45 - UINT saved_cp;
8.46 - HRESULT result;
8.47 - DWORD len = MAX_PATH;
8.48 - wchar_t *url16;
8.49 - wchar_t path16[MAX_PATH];
8.50 - char *path;
8.51 -
8.52 - url16 = razor_utf8_to_utf16(url, -1);
8.53 -
8.54 - saved_cp = GetConsoleCP();
8.55 - SetConsoleCP(CP_UTF8);
8.56 -
8.57 - result = PathCreateFromUrlW(url16, path16, &len, NULL);
8.58 -
8.59 - SetConsoleCP(saved_cp);
8.60 -
8.61 - if (result == S_OK)
8.62 - path = razor_utf16_to_utf8(path16, len);
8.63 - else
8.64 - path = NULL;
8.65 -
8.66 - free(url16);
8.67 -
8.68 - return path;
8.69 -}
8.70 -
8.71 -#else
8.72 -
8.73 -#ifdef MSWIN_API
8.74 -static int is_ascii_letter(char c)
8.75 -{
8.76 - return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
8.77 -}
8.78 -#endif
8.79 -
8.80 -static int xdigit_value(char c)
8.81 -{
8.82 - if (c >= '0' && c <= '9')
8.83 - return c - '0';
8.84 - else
8.85 - return (c | 0x20) - 'a' + 10;
8.86 -}
8.87 +#include "uri.h"
8.88
8.89 static int valid_unicode(unsigned unicode)
8.90 {
8.91 @@ -101,54 +33,74 @@
8.92 return unicode < 0xD800 || (unicode >= 0xE000 && unicode < 0x110000);
8.93 }
8.94
8.95 -RAZOR_EXPORT char *razor_path_from_url(const char *url)
8.96 +char *razor_path_from_parsed_uri(const struct razor_uri *ru,
8.97 + struct razor_error **error)
8.98 {
8.99 int continuation_bytes = 0;
8.100 - char *path, *p;
8.101 + char *path, *p, *s, *uri;
8.102 unsigned char c;
8.103 unsigned unicode;
8.104
8.105 - if (strncmp(url, "file://", 7) == 0)
8.106 - url += 7;
8.107 - else
8.108 + if (!ru->scheme) {
8.109 + uri = razor_uri_recompose(ru);
8.110 + razor_set_error(error, RAZOR_GENERAL_ERROR,
8.111 + RAZOR_GENERAL_ERROR_BAD_URI, uri,
8.112 + "URI does not include a scheme");
8.113 + free(uri);
8.114 return NULL;
8.115 + }
8.116
8.117 - if (strncmp(url, "localhost/", 10) == 0)
8.118 - url += 9;
8.119 - else if (strncmp(url, "/", 1) != 0)
8.120 + if (strcmp(ru->scheme, "file")) {
8.121 + uri = razor_uri_recompose(ru);
8.122 + razor_set_error(error, RAZOR_GENERAL_ERROR,
8.123 + RAZOR_GENERAL_ERROR_UNSUPPORTED_URI, uri,
8.124 + "Not a file URI");
8.125 + free(uri);
8.126 return NULL;
8.127 + }
8.128
8.129 + if (ru->host && *ru->host && strcmp(ru->host, "localhost") ||
8.130 + ru->userinfo || ru->port) {
8.131 + uri = razor_uri_recompose(ru);
8.132 + razor_set_error(error, RAZOR_GENERAL_ERROR,
8.133 + RAZOR_GENERAL_ERROR_UNSUPPORTED_URI, uri,
8.134 + "URI refers to a non-local file");
8.135 + free(uri);
8.136 + return NULL;
8.137 + }
8.138 +
8.139 + s = ru->path;
8.140 #ifdef MSWIN_API
8.141 /*
8.142 - * Under MS-Windows, file:///c:/xxx maps to c:/xxx
8.143 + * Under MS-Windows, a path of /c:/xxx maps to c:/xxx
8.144 * Note that PathCreateFromUrl converts / to \ as well.
8.145 */
8.146 - if (is_ascii_letter(url[1]) && url[2] == ':' && url[3] == '/')
8.147 - url++;
8.148 + if (s[0] == '/' && is_alpha(s[1]) && s[2] == ':' && s[3] == '/')
8.149 + s++;
8.150 #endif
8.151
8.152 - p = path = malloc(strlen(url) + 1);
8.153 + p = path = malloc(strlen(s) + 1);
8.154
8.155 - while(*url) {
8.156 - if (*url >= 0x7F || *url < 0x20) {
8.157 - free(path);
8.158 - return NULL;
8.159 - } else if (*url != '%') {
8.160 - if (continuation_bytes) {
8.161 - free(path);
8.162 - return NULL;
8.163 - } else
8.164 - *p++ = *url++;
8.165 - } else if (isxdigit(url[1]) && isxdigit(url[2])) {
8.166 - c = xdigit_value(url[1]) * 16 + xdigit_value(url[2]);
8.167 - if (c == '/') {
8.168 - free(path);
8.169 - return NULL;
8.170 - } else if (!continuation_bytes) {
8.171 - if (c >= 0xF5 || c == 0xC0 || c == 0xC1) {
8.172 - free(path);
8.173 - return NULL;
8.174 - } else if (c >= 0xF0) {
8.175 + while (*s) {
8.176 + if (*s >= 0x7F || *s < 0x20)
8.177 + break;
8.178 + else if (*s != '%') {
8.179 + if (continuation_bytes)
8.180 + break;
8.181 + else
8.182 + *p++ = *s++;
8.183 + } else {
8.184 + c = pchar_get_char(s);
8.185 +#ifdef MSWIN_API
8.186 + if (c == '/' || c == '\\')
8.187 +#else
8.188 + if (c == '/')
8.189 +#endif
8.190 + break;
8.191 + else if (!continuation_bytes) {
8.192 + if (c >= 0xF5 || c == 0xC0 || c == 0xC1)
8.193 + break;
8.194 + else if (c >= 0xF0) {
8.195 unicode = c & 7;
8.196 continuation_bytes = 3;
8.197 } else if (c >= 0xE0) {
8.198 @@ -158,29 +110,28 @@
8.199 unicode = c & 1;
8.200 continuation_bytes = 1;
8.201 }
8.202 - } else if ((c & 0xC0) != 0x80) {
8.203 - free(path);
8.204 - return NULL;
8.205 - } else {
8.206 + } else if ((c & 0xC0) != 0x80)
8.207 + break;
8.208 + else {
8.209 unicode <<= 6;
8.210 unicode |= (c & 0x3F);
8.211
8.212 if (!--continuation_bytes &&
8.213 - !valid_unicode(unicode)) {
8.214 - free(path);
8.215 - return NULL;
8.216 - }
8.217 + !valid_unicode(unicode))
8.218 + break;
8.219 }
8.220
8.221 *p++ = c;
8.222 - url += 3;
8.223 - } else {
8.224 - free(path);
8.225 - return NULL;
8.226 + s += 3;
8.227 }
8.228 }
8.229
8.230 - if (continuation_bytes) {
8.231 + if (*s || continuation_bytes) {
8.232 + uri = razor_uri_recompose(ru);
8.233 + razor_set_error(error, RAZOR_GENERAL_ERROR,
8.234 + RAZOR_GENERAL_ERROR_BAD_URI,
8.235 + uri, "Illegal character in file URI path");
8.236 + free(uri);
8.237 free(path);
8.238 return NULL;
8.239 }
8.240 @@ -190,4 +141,72 @@
8.241 return realloc(path, p - path);
8.242 }
8.243
8.244 -#endif /* 0 */
8.245 +RAZOR_EXPORT char *razor_path_from_uri(const char *uri,
8.246 + struct razor_error **error)
8.247 +{
8.248 + struct razor_uri ru;
8.249 + char *path;
8.250 +
8.251 + if (razor_uri_parse(&ru, uri, error))
8.252 + return NULL;
8.253 +
8.254 + path = razor_path_from_parsed_uri(&ru, error);
8.255 +
8.256 + razor_uri_destroy(&ru);
8.257 +
8.258 + return path;
8.259 +}
8.260 +
8.261 +RAZOR_EXPORT char *razor_path_to_uri(const char *path)
8.262 +{
8.263 + char *uri, *p;
8.264 +
8.265 + uri = malloc(6 + 3 * strlen(path) + 1);
8.266 +
8.267 + strcpy(uri, "file:");
8.268 +
8.269 + p = uri + 5;
8.270 +
8.271 +#ifdef MSWIN_API
8.272 + /*
8.273 + * Under MS-Windows, c:/xxx maps to a path of /c:/xxx
8.274 + */
8.275 + if (is_alpha(path[0]) && path[1] == ':' && path[2] == '/')
8.276 + *p++ = '/';
8.277 +#endif
8.278 +
8.279 + while(*path) {
8.280 + if (*path == '/' || is_unreserved(*path) ||
8.281 + is_sub_delim(*path) || *path == ':' || *path == '@')
8.282 + *p++ = *path;
8.283 +#ifdef MSWIN_API
8.284 + else if (*path == '\\')
8.285 + *p++ = '/';
8.286 +#endif
8.287 + else {
8.288 + *p++ = '%';
8.289 + *p++ = "0123456789ABCDEF"[(*(unsigned char *)path)/16];
8.290 + *p++ = "0123456789ABCDEF"[(*(unsigned char *)path)%16];
8.291 + }
8.292 + path++;
8.293 + }
8.294 + *p++ = '\0';
8.295 +
8.296 + return realloc(uri, p - uri);
8.297 +}
8.298 +
8.299 +RAZOR_EXPORT char *
8.300 +razor_path_relative_to_uri(const char *uri, const char *path,
8.301 + struct razor_error **error)
8.302 +{
8.303 + char *rel_uri, *result;
8.304 +
8.305 + /* Strictly wrong if uri isn't a file URI, but probably okay */
8.306 + rel_uri = razor_path_to_uri(path);
8.307 +
8.308 + result = razor_resolve_uri_root(uri, rel_uri + 5, 1, error);
8.309 +
8.310 + free(rel_uri);
8.311 +
8.312 + return result;
8.313 +}
9.1 --- a/librazor/razor-internal.h Sat Jun 11 17:56:48 2016 +0100
9.2 +++ b/librazor/razor-internal.h Mon Jul 04 10:48:18 2016 +0100
9.3 @@ -1,7 +1,7 @@
9.4 /*
9.5 * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
9.6 * Copyright (C) 2008 Red Hat, Inc
9.7 - * Copyright (C) 2009, 2011-2012, 2014 J. Ali Harlow <ali@juiblex.co.uk>
9.8 + * Copyright (C) 2009, 2011-2012, 2014, 2016 J. Ali Harlow <ali@juiblex.co.uk>
9.9 *
9.10 * This program is free software; you can redistribute it and/or modify
9.11 * it under the terms of the GNU General Public License as published by
9.12 @@ -42,6 +42,9 @@
9.13 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
9.14 #define PADDING(value, base) (-(value) & (base - 1))
9.15 #define ALIGN(value, base) ((value) + PADDING(value, base))
9.16 +
9.17 +#define str_has_prefix(s, prefix) (!strncmp(s, prefix, strlen(prefix)))
9.18 +
9.19 void *zalloc(size_t size);
9.20
9.21 struct razor_set_section {
9.22 @@ -181,7 +184,7 @@
9.23 };
9.24
9.25 int
9.26 -razor_set_aquire_lock(struct razor_set *set, const char *path, int exclusive);
9.27 +razor_set_acquire_lock(struct razor_set *set, const char *path, int exclusive);
9.28
9.29 struct razor_entry *
9.30 razor_set_find_entry(struct razor_set *set,
9.31 @@ -206,7 +209,72 @@
9.32 ssize_t len, int arg1);
9.33
9.34 int razor_run_script(const char *root, enum razor_property_flags script,
9.35 - const char *program, const char *body, int arg1);
9.36 + const char *program, const char *body, int arg1,
9.37 + struct razor_error **error);
9.38 +
9.39 +/* URI functions */
9.40 +
9.41 +struct razor_uri {
9.42 + char *scheme;
9.43 + char *userinfo;
9.44 + char *host;
9.45 + char *port;
9.46 + char *path;
9.47 + char *query;
9.48 + char *fragment;
9.49 +};
9.50 +
9.51 +void razor_uri_destroy(struct razor_uri *ru);
9.52 +int razor_uri_parse_uri(struct razor_uri *ru, const char *uri, int absolute,
9.53 + struct razor_error **error);
9.54 +int razor_uri_parse_relative_ref(struct razor_uri *ru, const char *uri,
9.55 + struct razor_error **error);
9.56 +int razor_uri_parse(struct razor_uri *ru, const char *uri,
9.57 + struct razor_error **error);
9.58 +void razor_uri_normalize(struct razor_uri *ru);
9.59 +char *razor_uri_get_authority(const struct razor_uri *ru) RAZOR_MALLOC;
9.60 +char *razor_uri_recompose(const struct razor_uri *ru) RAZOR_MALLOC;
9.61 +void razor_uri_resolve(struct razor_uri *T, const struct razor_uri *base,
9.62 + const struct razor_uri *R);
9.63 +
9.64 +char *razor_resolve_uri_root(const char *root_uri, const char *relative_uri,
9.65 + int is_relative, struct razor_error **error)
9.66 + RAZOR_MALLOC;
9.67 +
9.68 +int razor_file_mkdir(const char *path, mode_t mode, struct razor_error **error);
9.69 +int razor_file_unlink(const char *path, struct razor_error **error);
9.70 +int razor_file_open(const char *path, int flags, mode_t mode,
9.71 + struct razor_error **error);
9.72 +int razor_file_move(const char *path, const char *dest,
9.73 + struct razor_error **error);
9.74 +void *razor_file_get_contents(const char *path, size_t *length, int _private,
9.75 + struct razor_error **error);
9.76 +int razor_file_free_contents(void *addr, size_t length);
9.77 +int razor_file_is_directory(const char *path, struct razor_error **error);
9.78 +char *razor_file_mkdtemp_near(const char *path, const char *_template,
9.79 + struct razor_error **error);
9.80 +void *razor_file_opendir(const char *path, struct razor_error **error);
9.81 +char *razor_file_readdir(void *dir, struct razor_error **error);
9.82 +int razor_file_closedir(void *dir, struct razor_error **error);
9.83 +
9.84 +int razor_uri_mkdir(const char *uri, mode_t mode, struct razor_error **error);
9.85 +int razor_uri_unlink(const char *uri, struct razor_error **error);
9.86 +int razor_uri_open(const char *uri, int flags, mode_t mode,
9.87 + struct razor_error **error);
9.88 +int razor_uri_move(const char *uri, const char *dest,
9.89 + struct razor_error **error);
9.90 +int razor_uri_is_directory(const char *uri, struct razor_error **error);
9.91 +char *razor_uri_mkdtemp_near(const char *uri, const char *template,
9.92 + struct razor_error **error) RAZOR_MALLOC;
9.93 +void *razor_uri_opendir(const char *uri, struct razor_error **error);
9.94 +char *razor_uri_readdir(void *dir, struct razor_error **error) RAZOR_MALLOC;
9.95 +int razor_uri_closedir(void *dir, struct razor_error **error);
9.96 +void *razor_uri_get_contents(const char *uri, size_t *length, int private,
9.97 + struct razor_error **error);
9.98 +int razor_uri_free_contents(void *addr, size_t length);
9.99 +
9.100 +char *razor_path_from_parsed_uri(const struct razor_uri *ru,
9.101 + struct razor_error **error);
9.102
9.103 /* Utility functions */
9.104
9.105 @@ -216,16 +284,6 @@
9.106 va_list args);
9.107 void razor_rpm_get_details_varg(struct razor_rpm *rpm, va_list args);
9.108
9.109 -int razor_create_dir(const char *root, const char *path);
9.110 -int razor_remove(const char *path);
9.111 -int razor_write(int fd, const void *data, size_t size);
9.112 -
9.113 -void *
9.114 -razor_file_get_contents(const char *filename, size_t *length, int private,
9.115 - struct razor_error **error);
9.116 -int razor_file_free_contents(void *addr, size_t length);
9.117 -
9.118 -
9.119 typedef int (*razor_compare_with_data_func_t)(const void *p1,
9.120 const void *p,
9.121 void *data);
9.122 @@ -267,6 +325,10 @@
9.123 if (error) \
9.124 *(error) = razor_error_new_posix(object); \
9.125 else
9.126 +#define razor_set_error(error, domain, code, object, str) \
9.127 + if (error) \
9.128 + *(error) = razor_error_new_str(domain, code, object, str); \
9.129 + else
9.130
9.131 #ifdef MSWIN_API
9.132 struct razor_error *razor_error_new_mswin(const wchar_t *object, DWORD error);
9.133 @@ -312,7 +374,7 @@
9.134 ACTION_MOVE,
9.135 } type;
9.136 struct {
9.137 - char *path;
9.138 + char *uri;
9.139 union atomic_action_args {
9.140 struct {
9.141 char *root;
9.142 @@ -359,6 +421,9 @@
9.143 };
9.144 #endif
9.145
9.146 +char *razor_resolve_database_file(const char *root_uri, const char *filename,
9.147 + struct razor_error **error);
9.148 +
9.149 int razor_allow_all_root_names(void);
9.150 int razor_valid_root_name(const char *name);
9.151
10.1 --- a/librazor/razor.c Sat Jun 11 17:56:48 2016 +0100
10.2 +++ b/librazor/razor.c Mon Jul 04 10:48:18 2016 +0100
10.3 @@ -1,7 +1,7 @@
10.4 /*
10.5 * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
10.6 * Copyright (C) 2008 Red Hat, Inc
10.7 - * Copyright (C) 2009-2012 J. Ali Harlow <ali@juiblex.co.uk>
10.8 + * Copyright (C) 2009-2012, 2016 J. Ali Harlow <ali@juiblex.co.uk>
10.9 *
10.10 * This program is free software; you can redistribute it and/or modify
10.11 * it under the terms of the GNU General Public License as published by
10.12 @@ -28,10 +28,8 @@
10.13 #include <stdio.h>
10.14 #include <stdarg.h>
10.15 #include <string.h>
10.16 -#include <sys/types.h>
10.17 -#include <sys/stat.h>
10.18 +#include <fcntl.h>
10.19 #include <unistd.h>
10.20 -#include <fcntl.h>
10.21 #include <errno.h>
10.22 #include <ctype.h>
10.23 #include <fnmatch.h>
10.24 @@ -140,7 +138,7 @@
10.25 };
10.26
10.27 RAZOR_EXPORT int
10.28 -razor_set_bind_sections(struct razor_set *set, const char *filename,
10.29 +razor_set_bind_sections(struct razor_set *set, const char *uri,
10.30 enum razor_set_flags flags, struct razor_error **error)
10.31 {
10.32 struct razor_set_section *s, *sections;
10.33 @@ -156,9 +154,9 @@
10.34 return -1;
10.35 }
10.36
10.37 - file->header = razor_file_get_contents(filename, &file->size,
10.38 - flags & RAZOR_SET_PRIVATE,
10.39 - error);
10.40 + file->header = razor_uri_get_contents(uri, &file->size,
10.41 + flags & RAZOR_SET_PRIVATE,
10.42 + error);
10.43 if (!file->header) {
10.44 free(file);
10.45 return -1;
10.46 @@ -178,9 +176,8 @@
10.47 reason = NULL;
10.48
10.49 if (reason) {
10.50 - razor_set_error(error, RAZOR_GENERAL_ERROR, code, filename,
10.51 - reason);
10.52 - razor_file_free_contents(file->header, file->size);
10.53 + razor_set_error(error, RAZOR_GENERAL_ERROR, code, uri, reason);
10.54 + razor_uri_free_contents(file->header, file->size);
10.55 free(file);
10.56 return -1;
10.57 }
10.58 @@ -220,7 +217,7 @@
10.59 }
10.60
10.61 RAZOR_EXPORT struct razor_set *
10.62 -razor_set_open(const char *filename, enum razor_set_flags flags,
10.63 +razor_set_open(const char *uri, enum razor_set_flags flags,
10.64 struct razor_error **error)
10.65 {
10.66 struct razor_set *set;
10.67 @@ -234,7 +231,7 @@
10.68
10.69 set->lock_fd = -1;
10.70 set->ref_count = 1;
10.71 - if (razor_set_bind_sections(set, filename, flags, error)) {
10.72 + if (razor_set_bind_sections(set, uri, flags, error)) {
10.73 free(set);
10.74 return NULL;
10.75 }
10.76 @@ -242,18 +239,18 @@
10.77 }
10.78
10.79 int
10.80 -razor_set_aquire_lock(struct razor_set *set, const char *path, int exclusive)
10.81 +razor_set_acquire_lock(struct razor_set *set, const char *uri, int exclusive)
10.82 {
10.83 int fd;
10.84 assert(set != NULL);
10.85
10.86 - if (path) {
10.87 - fd = open(path, O_CREAT | O_RDWR | O_TRUNC | O_BINARY, 0666);
10.88 + if (uri) {
10.89 + fd = razor_uri_open(uri, O_CREAT | O_RDWR | O_TRUNC | O_BINARY,
10.90 + 0666, NULL);
10.91 if (fd < 0)
10.92 return -1;
10.93 - } else {
10.94 + } else
10.95 fd = -1;
10.96 - }
10.97
10.98 #ifdef MSWIN_API
10.99 DWORD flags = LOCKFILE_FAIL_IMMEDIATELY;
10.100 @@ -310,12 +307,12 @@
10.101 } else {
10.102 for (file = set->mapped_files; file != NULL; file = next) {
10.103 next = file->next;
10.104 - razor_file_free_contents(file->header, file->size);
10.105 + razor_uri_free_contents(file->header, file->size);
10.106 free(file);
10.107 }
10.108 }
10.109
10.110 - razor_set_aquire_lock(set, NULL, 0);
10.111 + razor_set_acquire_lock(set, NULL, 0);
10.112 free(set);
10.113 }
10.114
10.115 @@ -390,11 +387,11 @@
10.116
10.117 RAZOR_EXPORT int
10.118 razor_set_write(struct razor_set *set, struct razor_atomic *atomic,
10.119 - const char *filename, uint32_t sections)
10.120 + const char *uri, uint32_t sections)
10.121 {
10.122 int h;
10.123
10.124 - h = razor_atomic_create_file(atomic, filename,
10.125 + h = razor_atomic_create_file(atomic, uri,
10.126 S_IRWXU | S_IRWXG | S_IRWXO);
10.127 if (h < 0)
10.128 return -1;
10.129 @@ -636,6 +633,7 @@
10.130 struct environment env;
10.131 struct list *link;
10.132 const char *prefix;
10.133 + struct razor_error *tmp_error = NULL;
10.134
10.135 if (stage & RAZOR_STAGE_SCRIPTS) {
10.136 environment_init(&env);
10.137 @@ -658,7 +656,12 @@
10.138 RAZOR_DETAIL_LAST);
10.139
10.140 retval = razor_run_script(root, RAZOR_PROPERTY_PREUN, program,
10.141 - script, install_count);
10.142 + script, install_count, &tmp_error);
10.143 +
10.144 + if (retval < 0) {
10.145 + razor_atomic_propagate_error(atomic, tmp_error, NULL);
10.146 + tmp_error = NULL;
10.147 + }
10.148 }
10.149
10.150 if (!retval && (stage & RAZOR_STAGE_FILES)) {
10.151 @@ -690,7 +693,12 @@
10.152 RAZOR_DETAIL_LAST);
10.153
10.154 retval |= razor_run_script(root, RAZOR_PROPERTY_POSTUN, program,
10.155 - script, install_count);
10.156 + script, install_count, &tmp_error);
10.157 +
10.158 + if (retval < 0) {
10.159 + razor_atomic_propagate_error(atomic, tmp_error, NULL);
10.160 + tmp_error = NULL;
10.161 + }
10.162 }
10.163
10.164 if (stage & RAZOR_STAGE_SCRIPTS) {
11.1 --- a/librazor/razor.h.in Sat Jun 11 17:56:48 2016 +0100
11.2 +++ b/librazor/razor.h.in Mon Jul 04 10:48:18 2016 +0100
11.3 @@ -1,7 +1,7 @@
11.4 /*
11.5 * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
11.6 * Copyright (C) 2008 Red Hat, Inc
11.7 - * Copyright (C) 2009, 2011, 2012, 2014 J. Ali Harlow <ali@juiblex.co.uk>
11.8 + * Copyright (C) 2009, 2011, 2012, 2014, 2016 J. Ali Harlow <ali@juiblex.co.uk>
11.9 *
11.10 * This program is free software; you can redistribute it and/or modify
11.11 * it under the terms of the GNU General Public License as published by
11.12 @@ -23,7 +23,7 @@
11.13
11.14 #include <stdio.h>
11.15 #include <stdint.h>
11.16 -#include <sys/types.h>
11.17 +#include <sys/stat.h>
11.18
11.19 /* GCC extensions */
11.20 #if defined(__GNUC__)
11.21 @@ -130,6 +130,10 @@
11.22 *(dest) = razor_error_dup(src, summary); \
11.23 else
11.24
11.25 +#define razor_error_matches(error, domain, code) \
11.26 + ((error) && razor_error_get_domain(error) == (domain) && \
11.27 + razor_error_get_code(error) == (code))
11.28 +
11.29 #define RAZOR_ERROR_DOMAIN(i1,i2,i3,c) \
11.30 (((i1)&0xff)<<24|((i2)&0xff)<<16|((i3)&0xff)<<8|(c)&0xff)
11.31
11.32 @@ -145,6 +149,8 @@
11.33 RAZOR_GENERAL_ERROR_DATABASE_EXISTS,
11.34 RAZOR_GENERAL_ERROR_DATABASE_LOCKED,
11.35 RAZOR_GENERAL_ERROR_RPM_UNSUPPORTED,
11.36 + RAZOR_GENERAL_ERROR_UNSUPPORTED_URI,
11.37 + RAZOR_GENERAL_ERROR_BAD_URI,
11.38 };
11.39
11.40 int razor_error_get_domain(struct razor_error *error);
11.41 @@ -195,11 +201,11 @@
11.42 *
11.43 * Returns: non-zero on error.
11.44 **/
11.45 -int razor_atomic_make_dirs(struct razor_atomic *atomic, const char *root,
11.46 - const char *path);
11.47 +int razor_atomic_make_dirs(struct razor_atomic *atomic, const char *root_uri,
11.48 + const char *uri);
11.49 int razor_atomic_remove(struct razor_atomic *atomic, const char *path);
11.50 -int razor_atomic_rename_file(struct razor_atomic *atomic, const char *oldpath,
11.51 - const char *newpath);
11.52 +int razor_atomic_rename_file(struct razor_atomic *atomic, const char *old_uri,
11.53 + const char *new_uri);
11.54
11.55 /**
11.56 * razor_atomic_create_dir
11.57 @@ -209,8 +215,8 @@
11.58 *
11.59 * Returns: non-zero on error.
11.60 */
11.61 -int razor_atomic_create_dir(struct razor_atomic *atomic, const char *dirname,
11.62 - mode_t mode);
11.63 +int razor_atomic_create_dir(struct razor_atomic *atomic, const char *uri,
11.64 + mode_t mode);
11.65
11.66 /**
11.67 * razor_atomic_create_symlink
11.68 @@ -224,7 +230,7 @@
11.69 * Returns: non-zero on error.
11.70 */
11.71 int razor_atomic_create_symlink(struct razor_atomic *atomic, const char *target,
11.72 - const char *path);
11.73 + const char *uri);
11.74 /**
11.75 * razor_atomic_create_file
11.76 *
11.77 @@ -234,16 +240,17 @@
11.78 * Returns: A handle to be passed to razor_atomic_write() and
11.79 * razor_atomic_close() or a negative value on error.
11.80 */
11.81 -int razor_atomic_create_file(struct razor_atomic *atomic, const char *filename,
11.82 - mode_t mode);
11.83 +int razor_atomic_create_file(struct razor_atomic *atomic, const char *uri,
11.84 + mode_t mode);
11.85 int razor_atomic_write(struct razor_atomic *atomic, int handle,
11.86 - const void *data, size_t size);
11.87 + const void *data, size_t size);
11.88 int razor_atomic_close(struct razor_atomic *atomic, int handle);
11.89 int razor_atomic_sync(struct razor_atomic *atomic, int handle);
11.90 void razor_atomic_abort(struct razor_atomic *atomic, int domain, int code,
11.91 - const char *error_msg);
11.92 -void razor_atomic_propagate_error(struct razor_atomic *atomic,
11.93 - struct razor_error *error, const char *summary);
11.94 + const char *error_msg);
11.95 +void
11.96 +razor_atomic_propagate_error(struct razor_atomic *atomic,
11.97 + struct razor_error *error, const char *summary);
11.98 int razor_atomic_in_error_state(struct razor_atomic *atomic);
11.99
11.100 /**
11.101 @@ -272,7 +279,7 @@
11.102 struct razor_set *razor_set_create_without_root(void);
11.103 struct razor_set *razor_set_create(void);
11.104 struct razor_set *
11.105 -razor_set_open(const char *filename, enum razor_set_flags flags,
11.106 +razor_set_open(const char *uri, enum razor_set_flags flags,
11.107 struct razor_error **error);
11.108 uint32_t razor_set_get_header_version(struct razor_set *set);
11.109 int razor_set_set_header_version(struct razor_set *set,
11.110 @@ -283,9 +290,9 @@
11.111 struct razor_atomic *atomic, int handle,
11.112 uint32_t section_mask);
11.113 int razor_set_write(struct razor_set *set, struct razor_atomic *atomic,
11.114 - const char *filename, uint32_t setions);
11.115 + const char *uri, uint32_t setions);
11.116 int
11.117 -razor_set_bind_sections(struct razor_set *set, const char *filename,
11.118 +razor_set_bind_sections(struct razor_set *set, const char *uri,
11.119 enum razor_set_flags flags, struct razor_error **error);
11.120
11.121 void
11.122 @@ -506,13 +513,12 @@
11.123 const char *path);
11.124 void razor_relocations_destroy(struct razor_relocations *relocations);
11.125
11.126 -struct razor_rpm *razor_rpm_open(const char *filename,
11.127 - struct razor_error **error);
11.128 +struct razor_rpm *razor_rpm_open(const char *uri, struct razor_error **error);
11.129 void razor_rpm_get_details(struct razor_rpm *rpm, ...);
11.130 void razor_rpm_set_relocations(struct razor_rpm *rpm,
11.131 struct razor_relocations *relocations);
11.132 int razor_rpm_install(struct razor_rpm *rpm, struct razor_atomic *atomic,
11.133 - const char *root, int install_count,
11.134 + const char *root_uri, int install_count,
11.135 enum razor_stage_type stage);
11.136 int razor_rpm_close(struct razor_rpm *rpm);
11.137
11.138 @@ -599,13 +605,13 @@
11.139 **/
11.140 struct razor_root;
11.141
11.142 -const char *razor_get_database_path();
11.143 -void razor_set_database_path(const char *database_path);
11.144 -int razor_root_create(const char *root, struct razor_error **error);
11.145 +const char *razor_get_database_uri(void);
11.146 +void razor_set_database_uri(const char *database_uri);
11.147 +int razor_root_create(const char *root_uri, struct razor_error **error);
11.148 struct razor_root *
11.149 -razor_root_open(const char *root, struct razor_error **error);
11.150 +razor_root_open(const char *root_uri, struct razor_error **error);
11.151 struct razor_set *
11.152 -razor_root_open_read_only(const char *root, struct razor_error **error);
11.153 +razor_root_open_read_only(const char *root_uri, struct razor_error **error);
11.154 struct razor_set *razor_root_get_system_set(struct razor_root *root);
11.155 int razor_root_close(struct razor_root *root);
11.156 int
11.157 @@ -613,6 +619,41 @@
11.158 struct razor_atomic *atomic);
11.159
11.160 /**
11.161 + * SECTION:uri-io
11.162 + * @title: URI Input/Output
11.163 + * @short_description: Functions to support non-file URI handlers
11.164 + *
11.165 + * Libraries that want to support URIs other than file URIs (which razor
11.166 + * handles internally), can install their own URI handlers. Unsupported
11.167 + * virtual functions should be set to %NULL. A fallback URI handler (which
11.168 + * will be used if no scheme-specific handler is found) can be installed
11.169 + * by passing scheme as %NULL. Finally, URI handlers can be removed by
11.170 + * passing vtable as %NULL.
11.171 + **/
11.172 +
11.173 +struct razor_uri_vtable {
11.174 + unsigned structure_size;
11.175 + int (*mkdir)(const char *path, mode_t mode, struct razor_error **error);
11.176 + int (*unlink)(const char *path, struct razor_error **error);
11.177 + int (*open)(const char *path, int flags, mode_t mode,
11.178 + struct razor_error **error);
11.179 + int (*move)(const char *path, const char *dest,
11.180 + struct razor_error **error);
11.181 + void *(*get_contents)(const char *path, size_t *length, int _private,
11.182 + struct razor_error **error);
11.183 + int (*free_contents)(void *addr, size_t length);
11.184 + int (*is_directory)(const char *path, struct razor_error **error);
11.185 + char *(*mkdtemp_near)(const char *path, const char *_template,
11.186 + struct razor_error **error);
11.187 + void *(*opendir)(const char *path, struct razor_error **error);
11.188 + char *(*readdir)(void *dir, struct razor_error **error);
11.189 + int (*closedir)(void *dir, struct razor_error **error);
11.190 +};
11.191 +
11.192 +int razor_uri_set_vtable(const char *scheme, struct razor_uri_vtable *vtable,
11.193 + struct razor_error **error);
11.194 +
11.195 +/**
11.196 * SECTION:misc
11.197 * @title: Miscellaneous Functions
11.198 * @short_description: Various helper functions
11.199 @@ -636,12 +677,15 @@
11.200
11.201 char *razor_concat(const char *s, ...) RAZOR_MALLOC RAZOR_NULL_TERMINATED;
11.202
11.203 -char *razor_path_add_root(const char *path, const char *root) RAZOR_MALLOC;
11.204 -char *razor_path_from_url(const char *url) RAZOR_MALLOC;
11.205 +char *razor_path_from_uri(const char *uri, struct razor_error **error)
11.206 + RAZOR_MALLOC;
11.207 +char *razor_path_to_uri(const char *path) RAZOR_MALLOC;
11.208 +char *razor_path_relative_to_uri(const char *file_uri, const char *path,
11.209 + struct razor_error **error) RAZOR_MALLOC;
11.210
11.211 const char *razor_system_arch(void);
11.212
11.213 -int razor_dump_database(FILE *fp, const char *root, const char *filename,
11.214 +int razor_dump_database(FILE *fp, const char *root_uri, const char *filename,
11.215 struct razor_error **error);
11.216
11.217 #endif /* _RAZOR_H_ */
12.1 --- a/librazor/root.c Sat Jun 11 17:56:48 2016 +0100
12.2 +++ b/librazor/root.c Mon Jul 04 10:48:18 2016 +0100
12.3 @@ -1,7 +1,7 @@
12.4 /*
12.5 * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
12.6 * Copyright (C) 2008 Red Hat, Inc
12.7 - * Copyright (C) 2009, 2011, 2012, 2014 J. Ali Harlow <ali@juiblex.co.uk>
12.8 + * Copyright (C) 2009, 2011, 2012, 2014, 2016 J. Ali Harlow <ali@juiblex.co.uk>
12.9 *
12.10 * This program is free software; you can redistribute it and/or modify
12.11 * it under the terms of the GNU General Public License as published by
12.12 @@ -25,7 +25,6 @@
12.13 #include <stdio.h>
12.14 #include <string.h>
12.15 #include <errno.h>
12.16 -#include <sys/stat.h>
12.17 #include <dirent.h>
12.18 #include <unistd.h>
12.19 #include <fcntl.h>
12.20 @@ -59,102 +58,130 @@
12.21 */
12.22 static const char system_lock_filename[] = "system-next.rzdb";
12.23 #ifdef MSWIN_API
12.24 -#define RAZOR_DATABASE_PATH NULL
12.25 +#define RAZOR_DATABASE_URI NULL
12.26 #else
12.27 -#define RAZOR_DATABASE_PATH "/var/lib/razor"
12.28 +/*
12.29 + * The non-MSWIN default is a relative-ref and thus affected by the root
12.30 + */
12.31 +#define RAZOR_DATABASE_URI "var/lib/razor"
12.32 #endif
12.33 -static char *razor_database_path = RAZOR_DATABASE_PATH;
12.34 -static int razor_database_path_alloced = FALSE;
12.35 +static char *razor_database_uri = RAZOR_DATABASE_URI;
12.36 +static int razor_database_uri_alloced = FALSE;
12.37
12.38 struct razor_root {
12.39 struct razor_set *system;
12.40 - char *path;
12.41 + char *uri;
12.42 };
12.43
12.44 static void
12.45 razor_root_init(void)
12.46 {
12.47 #ifdef MSWIN_API
12.48 - static char database_path[MAX_PATH];
12.49 - if (!razor_database_path) {
12.50 + /*
12.51 + * The MSWIN default is an absolute-URI and thus unaffected by the root
12.52 + */
12.53 + char database_path[MAX_PATH];
12.54 + if (!razor_database_uri) {
12.55 SHGetFolderPath(NULL,
12.56 CSIDL_COMMON_APPDATA | CSIDL_FLAG_DONT_VERIFY, NULL, 0,
12.57 database_path);
12.58 strcat(database_path, "\\Razor");
12.59 - razor_database_path = database_path;
12.60 - razor_database_path_alloced = FALSE;
12.61 + razor_database_uri = razor_path_to_uri(database_path);
12.62 + razor_database_uri_alloced = TRUE;
12.63 }
12.64 #endif
12.65 }
12.66
12.67 -RAZOR_EXPORT const char *
12.68 -razor_get_database_path()
12.69 +RAZOR_EXPORT const char *razor_get_database_uri(void)
12.70 {
12.71 razor_root_init();
12.72 -
12.73 - return razor_database_path;
12.74 + return razor_database_uri;
12.75 }
12.76
12.77 RAZOR_EXPORT void
12.78 -razor_set_database_path(const char *database_path)
12.79 +razor_set_database_uri(const char *database_uri)
12.80 {
12.81 - if (razor_database_path_alloced)
12.82 - free(razor_database_path);
12.83 + if (razor_database_uri_alloced)
12.84 + free(razor_database_uri);
12.85
12.86 - if (database_path) {
12.87 - razor_database_path = strdup(database_path);
12.88 - razor_database_path_alloced = TRUE;
12.89 + if (database_uri) {
12.90 + razor_database_uri = strdup(database_uri);
12.91 + razor_database_uri_alloced = TRUE;
12.92 } else {
12.93 - razor_database_path = RAZOR_DATABASE_PATH;
12.94 - razor_database_path_alloced = FALSE;
12.95 + razor_database_uri = RAZOR_DATABASE_URI;
12.96 + razor_database_uri_alloced = FALSE;
12.97 }
12.98 }
12.99
12.100 +char *razor_resolve_database_file(const char *root_uri, const char *filename,
12.101 + struct razor_error **error)
12.102 +{
12.103 + char *s, *uri;
12.104 +
12.105 + razor_root_init();
12.106 +
12.107 + s = razor_concat(razor_database_uri, "/", filename, NULL);
12.108 +
12.109 + uri = razor_resolve_uri_root(root_uri, s, -1, error);
12.110 +
12.111 + free(s);
12.112 +
12.113 + return uri;
12.114 +}
12.115 +
12.116 RAZOR_EXPORT int
12.117 -razor_root_create(const char *root, struct razor_error **error)
12.118 +razor_root_create(const char *root_uri, struct razor_error **error)
12.119 {
12.120 - int retval;
12.121 - struct stat buf;
12.122 + int retval, is_within_root, is_directory;
12.123 struct razor_set *set;
12.124 struct razor_atomic *atomic;
12.125 - char *file, *path;
12.126 + struct razor_error *tmp_err = NULL;
12.127 + char *uri;
12.128
12.129 - assert (root != NULL);
12.130 + uri = razor_resolve_database_file(root_uri, system_repo_filename,
12.131 + error);
12.132
12.133 - razor_root_init();
12.134 - if (root[0] == '\0') {
12.135 - /* root is file system root */
12.136 - } else if (stat(root, &buf) < 0) {
12.137 - if (mkdir(root, 0777) < 0) {
12.138 - razor_set_error(error, RAZOR_POSIX_ERROR, errno, root,
12.139 + if (!uri)
12.140 + return -1;
12.141 +
12.142 + if (razor_uri_is_directory(uri, NULL) >= 0) {
12.143 + razor_set_error(error, RAZOR_GENERAL_ERROR,
12.144 + RAZOR_GENERAL_ERROR_DATABASE_EXISTS, NULL,
12.145 + "A razor install root is already initialized");
12.146 + free(uri);
12.147 + return -1;
12.148 + }
12.149 +
12.150 + is_within_root = root_uri && strchr(root_uri, '/') &&
12.151 + str_has_prefix(uri, root_uri);
12.152 +
12.153 + atomic = razor_atomic_open("Create initial package set");
12.154 +
12.155 + if (is_within_root) {
12.156 + is_directory = razor_uri_is_directory(root_uri, NULL);
12.157 +
12.158 + if (!is_directory) {
12.159 + razor_set_error(error, RAZOR_POSIX_ERROR, ENOTDIR,
12.160 + root_uri, "Not a directory");
12.161 + return -1;
12.162 + } else if (is_directory < 0 &&
12.163 + razor_uri_mkdir(root_uri, 0777, &tmp_err) < 0) {
12.164 + razor_set_error(error,
12.165 + razor_error_get_domain(tmp_err),
12.166 + razor_error_get_code(tmp_err),
12.167 + root_uri,
12.168 "Could not create install root");
12.169 return -1;
12.170 }
12.171 - } else if (!S_ISDIR(buf.st_mode)) {
12.172 - razor_set_error(error, RAZOR_POSIX_ERROR, ENOTDIR, root,
12.173 - "Not a directory");
12.174 - return -1;
12.175 - }
12.176
12.177 - file = razor_concat(razor_database_path, "/", system_repo_filename,
12.178 - NULL);
12.179 - path = razor_path_add_root(file, root);
12.180 - retval = !stat(path, &buf);
12.181 - if (retval) {
12.182 - razor_set_error(error, RAZOR_GENERAL_ERROR,
12.183 - RAZOR_GENERAL_ERROR_DATABASE_EXISTS, NULL,
12.184 - "A razor install root is already initialized");
12.185 - free(path);
12.186 - free(file);
12.187 - return retval;
12.188 - }
12.189 + razor_atomic_make_dirs(atomic, root_uri,
12.190 + uri + strlen(root_uri));
12.191 + } else
12.192 + razor_atomic_make_dirs(atomic, "", uri);
12.193
12.194 - atomic = razor_atomic_open("Create initial package set");
12.195 - razor_atomic_make_dirs(atomic, root, file);
12.196 set = razor_set_create();
12.197 - razor_set_write(set, atomic, path, RAZOR_SECTION_ALL);
12.198 - free(path);
12.199 - free(file);
12.200 + razor_set_write(set, atomic, uri, RAZOR_SECTION_ALL);
12.201 + free(uri);
12.202 retval = razor_atomic_commit(atomic);
12.203 if (retval)
12.204 razor_propagate_error(error,
12.205 @@ -167,17 +194,21 @@
12.206 }
12.207
12.208 RAZOR_EXPORT struct razor_root *
12.209 -razor_root_open(const char *root, struct razor_error **error)
12.210 +razor_root_open(const char *root_uri, struct razor_error **error)
12.211 {
12.212 struct razor_root *image;
12.213 - char *s, *lock_path;
12.214 + char *lock_uri;
12.215 int r;
12.216
12.217 - assert (root != NULL);
12.218 + lock_uri = razor_resolve_database_file(root_uri, system_lock_filename,
12.219 + error);
12.220
12.221 - razor_root_init();
12.222 + if (!lock_uri)
12.223 + return NULL;
12.224 +
12.225 image = malloc(sizeof *image);
12.226 if (image == NULL) {
12.227 + free(lock_uri);
12.228 razor_set_error(error, RAZOR_POSIX_ERROR, ENOMEM, NULL,
12.229 "Not enough memory");
12.230 return NULL;
12.231 @@ -186,35 +217,37 @@
12.232 image->system = razor_set_create_without_root();
12.233 if (image->system == NULL) {
12.234 free(image);
12.235 + free(lock_uri);
12.236 razor_set_error(error, RAZOR_POSIX_ERROR, ENOMEM, NULL,
12.237 "Not enough memory");
12.238 return NULL;
12.239 }
12.240
12.241 - s = razor_concat(razor_database_path, "/", system_lock_filename, NULL);
12.242 - lock_path = razor_path_add_root(s, root);
12.243 - free(s);
12.244 + r = razor_set_acquire_lock(image->system, lock_uri, 1);
12.245
12.246 - r = razor_set_aquire_lock(image->system, lock_path, 1);
12.247 -
12.248 - free(lock_path);
12.249 + free(lock_uri);
12.250
12.251 if (r < 0) {
12.252 razor_set_error(error, RAZOR_GENERAL_ERROR,
12.253 RAZOR_GENERAL_ERROR_DATABASE_LOCKED, NULL,
12.254 - "Failed to aquire exclusive system lock");
12.255 + "Failed to acquire exclusive system lock");
12.256 razor_set_unref(image->system);
12.257 free(image);
12.258 return NULL;
12.259 }
12.260
12.261 - s = razor_concat(razor_database_path, "/", system_repo_filename, NULL);
12.262 - image->path = razor_path_add_root(s, root);
12.263 - free(s);
12.264 + image->uri = razor_resolve_database_file(root_uri, system_repo_filename,
12.265 + error);
12.266
12.267 - if (razor_set_bind_sections(image->system, image->path,
12.268 + if (!image->uri) {
12.269 + razor_set_unref(image->system);
12.270 + free(image);
12.271 + return NULL;
12.272 + }
12.273 +
12.274 + if (razor_set_bind_sections(image->system, image->uri,
12.275 RAZOR_SET_PRIVATE, error)) {
12.276 - free(image->path);
12.277 + free(image->uri);
12.278 razor_set_unref(image->system);
12.279 free(image);
12.280 return NULL;
12.281 @@ -224,46 +257,47 @@
12.282 }
12.283
12.284 RAZOR_EXPORT struct razor_set *
12.285 -razor_root_open_read_only(const char *root, struct razor_error **error)
12.286 +razor_root_open_read_only(const char *root_uri, struct razor_error **error)
12.287 {
12.288 - char *s, *path;
12.289 + int r;
12.290 + char *uri;
12.291 struct razor_set *set;
12.292
12.293 - assert (root != NULL);
12.294 + uri = razor_resolve_database_file(root_uri, system_lock_filename,
12.295 + error);
12.296
12.297 - razor_root_init();
12.298 + if (!uri)
12.299 + return NULL;
12.300 +
12.301 set = razor_set_create_without_root();
12.302 if (set == NULL) {
12.303 + free(uri);
12.304 razor_set_error(error, RAZOR_POSIX_ERROR, ENOMEM, NULL,
12.305 "Not enough memory");
12.306 return NULL;
12.307 }
12.308
12.309 - s = razor_concat(razor_database_path, "/", system_lock_filename, NULL);
12.310 - path = razor_path_add_root(s, root);
12.311 - free(s);
12.312 + r = razor_set_acquire_lock(set, uri, 0);
12.313
12.314 - if (razor_set_aquire_lock(set, path, 0) < 0) {
12.315 + free(uri);
12.316 +
12.317 + if (r < 0) {
12.318 razor_set_error(error, RAZOR_GENERAL_ERROR,
12.319 RAZOR_GENERAL_ERROR_DATABASE_LOCKED, NULL,
12.320 - "Failed to aquire non-exclusive system lock");
12.321 - free(path);
12.322 + "Failed to acquire non-exclusive system lock");
12.323 razor_set_unref(set);
12.324 return NULL;
12.325 }
12.326
12.327 - free(path);
12.328 + uri = razor_resolve_database_file(root_uri, system_repo_filename,
12.329 + error);
12.330
12.331 - s = razor_concat(razor_database_path, "/", system_repo_filename, NULL);
12.332 - path = razor_path_add_root(s, root);
12.333 - free(s);
12.334 -
12.335 - if (razor_set_bind_sections(set, path, 0, error)) {
12.336 + if (!uri || razor_set_bind_sections(set, uri, 0, error)) {
12.337 razor_set_unref(set);
12.338 set = NULL;
12.339 }
12.340
12.341 - free(path);
12.342 + free(uri);
12.343
12.344 return set;
12.345 }
12.346 @@ -282,7 +316,7 @@
12.347 assert (root != NULL);
12.348
12.349 razor_set_unref(root->system);
12.350 - free(root->path);
12.351 + free(root->uri);
12.352 free(root);
12.353
12.354 return 0;
12.355 @@ -297,7 +331,7 @@
12.356 assert (root != NULL);
12.357 assert (next != NULL);
12.358
12.359 - handle = razor_atomic_create_file(atomic, root->path,
12.360 + handle = razor_atomic_create_file(atomic, root->uri,
12.361 S_IRWXU | S_IRWXG | S_IRWXO);
12.362 if (handle < 0)
12.363 return handle;
13.1 --- a/librazor/rpm.c Sat Jun 11 17:56:48 2016 +0100
13.2 +++ b/librazor/rpm.c Mon Jul 04 10:48:18 2016 +0100
13.3 @@ -1,7 +1,7 @@
13.4 /*
13.5 * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
13.6 * Copyright (C) 2008 Red Hat, Inc
13.7 - * Copyright (C) 2009, 2011, 2012, 2014 J. Ali Harlow <ali@juiblex.co.uk>
13.8 + * Copyright (C) 2009, 2011, 2012, 2014, 2016 J. Ali Harlow <ali@juiblex.co.uk>
13.9 *
13.10 * This program is free software; you can redistribute it and/or modify
13.11 * it under the terms of the GNU General Public License as published by
13.12 @@ -25,13 +25,10 @@
13.13 #include <stdlib.h>
13.14 #include <string.h>
13.15 #include <errno.h>
13.16 -#include <sys/stat.h>
13.17 -#include <sys/types.h>
13.18 #if HAVE_SYS_WAIT_H
13.19 #include <sys/wait.h>
13.20 #endif
13.21 #include <fcntl.h>
13.22 -#include <dirent.h>
13.23 #include <unistd.h>
13.24 #if MSWIN_API
13.25 #include <winsock2.h> /* For ntohl() */
13.26 @@ -620,7 +617,7 @@
13.27 }
13.28
13.29 RAZOR_EXPORT struct razor_rpm *
13.30 -razor_rpm_open(const char *filename, struct razor_error **error)
13.31 +razor_rpm_open(const char *uri, struct razor_error **error)
13.32 {
13.33 struct rpm_lead *lead;
13.34 struct razor_rpm *rpm;
13.35 @@ -628,7 +625,7 @@
13.36 unsigned int count, i, nindex, hsize;
13.37 const char *name, *prefix;
13.38
13.39 - assert (filename != NULL);
13.40 + assert (uri != NULL);
13.41
13.42 rpm = zalloc(sizeof *rpm);
13.43 if (rpm == NULL) {
13.44 @@ -638,7 +635,7 @@
13.45 }
13.46 memset(rpm, 0, sizeof *rpm);
13.47
13.48 - rpm->map = razor_file_get_contents(filename, &rpm->size, 0, error);
13.49 + rpm->map = razor_uri_get_contents(uri, &rpm->size, 0, error);
13.50 if (!rpm->map) {
13.51 free(rpm);
13.52 return NULL;
13.53 @@ -646,11 +643,11 @@
13.54
13.55 lead = rpm->map;
13.56 if (rpm->size < RPM_LEAD_SIZE ||
13.57 - strncmp(lead->magic,RPM_LEAD_MAGIC,4) || lead->major != 3) {
13.58 + strncmp((char *)lead->magic,RPM_LEAD_MAGIC,4) || lead->major != 3) {
13.59 razor_rpm_close(rpm);
13.60 razor_set_error(error, RAZOR_GENERAL_ERROR,
13.61 RAZOR_GENERAL_ERROR_RPM_UNSUPPORTED,
13.62 - filename, "Not a recognized RPM format file");
13.63 + uri, "Not a recognized RPM format file");
13.64 return NULL;
13.65 }
13.66
13.67 @@ -682,8 +679,7 @@
13.68 razor_rpm_close(rpm);
13.69 razor_set_error(error, RAZOR_GENERAL_ERROR,
13.70 RAZOR_GENERAL_ERROR_RPM_UNSUPPORTED,
13.71 - filename,
13.72 - "Old filenames not supported");
13.73 + uri, "Old filenames not supported");
13.74 return NULL;
13.75 }
13.76 }
13.77 @@ -704,8 +700,7 @@
13.78 razor_rpm_close(rpm);
13.79 razor_set_error(error, RAZOR_GENERAL_ERROR,
13.80 RAZOR_GENERAL_ERROR_RPM_UNSUPPORTED,
13.81 - filename,
13.82 - "Default prefix not supported");
13.83 + uri, "Default prefix not supported");
13.84 return NULL;
13.85 }
13.86 }
13.87 @@ -748,7 +743,7 @@
13.88 #define RESERVED 0xE0 /* bits 5..7: reserved */
13.89
13.90 struct installer {
13.91 - const char *root;
13.92 + const char *root_uri;
13.93 struct razor_rpm *rpm;
13.94 struct razor_atomic *atomic;
13.95 z_stream stream;
13.96 @@ -808,13 +803,47 @@
13.97 static int
13.98 create_path(struct installer *installer, const char *path, unsigned int mode)
13.99 {
13.100 - char *s, *buffer;
13.101 - int h, ret;
13.102 + const char *s, *relative;
13.103 + char *uri, *buffer;
13.104 + int h, ret, is_within_root;
13.105 + struct razor_error *tmp_error = NULL;
13.106
13.107 - if (razor_atomic_make_dirs(installer->atomic, installer->root, path))
13.108 + uri = razor_path_to_uri(path);
13.109 +
13.110 + if (str_has_prefix(uri, "file:///"))
13.111 + relative = uri + 8;
13.112 + else if (str_has_prefix(uri, "file:/"))
13.113 + relative = uri + 6;
13.114 + else if (str_has_prefix(uri, "file:"))
13.115 + relative = uri + 5;
13.116 + else if (str_has_prefix(uri, "/"))
13.117 + relative = uri + 1;
13.118 + else
13.119 + relative = uri;
13.120 +
13.121 + buffer = razor_resolve_uri_root(installer->root_uri, relative, 1,
13.122 + &tmp_error);
13.123 +
13.124 + if (!buffer) {
13.125 + razor_atomic_propagate_error(installer->atomic, tmp_error,
13.126 + NULL);
13.127 + free(uri);
13.128 return -1;
13.129 + }
13.130
13.131 - buffer = razor_concat(installer->root, path, NULL);
13.132 + is_within_root = installer->root_uri &&
13.133 + str_has_prefix(buffer, installer->root_uri);
13.134 +
13.135 + if (is_within_root)
13.136 + ret = razor_atomic_make_dirs(installer->atomic,
13.137 + installer->root_uri, relative);
13.138 + else
13.139 + ret = razor_atomic_make_dirs(installer->atomic, "", buffer);
13.140 +
13.141 + free(uri);
13.142 +
13.143 + if (ret)
13.144 + return ret;
13.145
13.146 switch (mode >> 12) {
13.147 case REG:
13.148 @@ -831,7 +860,8 @@
13.149 installer->length))
13.150 return -1;
13.151 }
13.152 - return razor_atomic_close(installer->atomic, h);
13.153 + ret = razor_atomic_close(installer->atomic, h);
13.154 + break;
13.155 case XDIR:
13.156 ret = razor_atomic_create_dir(installer->atomic, buffer, mode);
13.157 free(buffer);
13.158 @@ -842,16 +872,17 @@
13.159 return -1;
13.160 if (installer->length >= sizeof installer->buffer) {
13.161 razor_atomic_abort(installer->atomic,
13.162 - RAZOR_GENERAL_ERROR,
13.163 - RAZOR_GENERAL_ERROR_RPM_UNSUPPORTED,
13.164 - "Link target too long");
13.165 + RAZOR_GENERAL_ERROR,
13.166 + RAZOR_GENERAL_ERROR_RPM_UNSUPPORTED,
13.167 + "Link target too long");
13.168 return -1;
13.169 }
13.170 installer->buffer[installer->length] = '\0';
13.171 ret = razor_atomic_create_symlink(installer->atomic,
13.172 - (const char *)installer->buffer, buffer);
13.173 + (const char *)installer->buffer,
13.174 + buffer);
13.175 free(buffer);
13.176 - return ret;
13.177 + break;
13.178 #else
13.179 s = "Symbolic links";
13.180 goto unsupported;
13.181 @@ -861,9 +892,9 @@
13.182 unsupported:
13.183 free(buffer);
13.184 buffer = razor_concat(s, " are not supported on this platform",
13.185 - NULL);
13.186 + NULL);
13.187 razor_atomic_abort(installer->atomic, RAZOR_GENERAL_ERROR,
13.188 - RAZOR_GENERAL_ERROR_RPM_UNSUPPORTED, buffer);
13.189 + RAZOR_GENERAL_ERROR_RPM_UNSUPPORTED, buffer);
13.190 free(buffer);
13.191 return -1;
13.192 case CDEV:
13.193 @@ -878,9 +909,12 @@
13.194 default:
13.195 free(buffer);
13.196 razor_atomic_abort(installer->atomic, RAZOR_GENERAL_ERROR,
13.197 - RAZOR_GENERAL_ERROR_RPM_UNSUPPORTED, "Unknown file type");
13.198 + RAZOR_GENERAL_ERROR_RPM_UNSUPPORTED,
13.199 + "Unknown file type");
13.200 return -1;
13.201 }
13.202 +
13.203 + return ret;
13.204 }
13.205
13.206 static int chroot_push(const char *root)
13.207 @@ -912,12 +946,14 @@
13.208 }
13.209
13.210 static int
13.211 -run_script_lua(const char *root, unsigned int script_tag, const char *script,
13.212 - int arg1)
13.213 +run_script_lua(const char *root_uri, unsigned int script_tag,
13.214 + const char *script, int arg1, struct razor_error **error)
13.215 {
13.216 int root_fd, retval;
13.217 + const char *name;
13.218 #if HAVE_LUA
13.219 - const char *name;
13.220 + char *root;
13.221 +#endif
13.222
13.223 switch(script_tag) {
13.224 case RPMTAG_PREIN:
13.225 @@ -936,12 +972,19 @@
13.226 name = "script";
13.227 break;
13.228 }
13.229 - root_fd = chroot_push(root);
13.230 +
13.231 +#if HAVE_LUA
13.232 + root = razor_path_from_uri(root_uri, error);
13.233 + if (!root)
13.234 + return -1;
13.235 + root_fd = root ? chroot_push(root) : -1;
13.236 retval = run_lua_script(root_fd < 0 ? root : NULL, name, script, -1,
13.237 arg1);
13.238 + free(root);
13.239 chroot_pop(root_fd);
13.240 #else /* HAVE_LUA */
13.241 - fprintf(stderr, "lua not available to run script\n");
13.242 + razor_set_error(error, RAZOR_GENERAL_ERROR, RAZOR_GENERAL_ERROR_FAILED,
13.243 + name, "lua not available to run script");
13.244 retval = -1;
13.245 #endif /* HAVE_LUA */
13.246
13.247 @@ -949,12 +992,12 @@
13.248 }
13.249
13.250 static int
13.251 -run_script_external(const char *root, const char *program, const char *script,
13.252 - int arg1)
13.253 +run_script_external(const char *root_uri, const char *program,
13.254 + const char *script, int arg1, struct razor_error **error)
13.255 {
13.256 int root_fd, retval;
13.257 FILE *fp;
13.258 - char buf[32], *command;
13.259 + char buf[32], *command, *root;
13.260
13.261 if (program == NULL) {
13.262 #if MSWIN_API
13.263 @@ -971,7 +1014,11 @@
13.264 #endif
13.265 }
13.266
13.267 + root = razor_path_from_uri(root_uri, error);
13.268 + if (!root)
13.269 + return -1;
13.270 root_fd = chroot_push(root);
13.271 + free(root);
13.272 if (arg1 >= 0) {
13.273 sprintf(buf, "%d", arg1);
13.274 command = malloc(strlen(program) + strlen(buf) + 2);
13.275 @@ -982,10 +1029,11 @@
13.276 free(command);
13.277
13.278 if (!fp) {
13.279 - perror(program);
13.280 + razor_set_error_posix(error, program);
13.281 retval = -1;
13.282 } else if (script && fwrite(script, strlen(script), 1, fp) != 1) {
13.283 - perror("failed to write script to program");
13.284 + razor_set_error_posix(error,
13.285 + "failed to write script to program");
13.286 retval = -1;
13.287 } else
13.288 retval = 0;
13.289 @@ -998,8 +1046,8 @@
13.290 }
13.291
13.292 static int
13.293 -run_script(struct installer *installer,
13.294 - unsigned int program_tag, unsigned int script_tag, int arg1)
13.295 +run_script(struct installer *installer, unsigned int program_tag,
13.296 + unsigned int script_tag, int arg1, struct razor_error **error)
13.297 {
13.298 int i, retval;
13.299 struct razor_rpm *rpm = installer->rpm;
13.300 @@ -1024,11 +1072,11 @@
13.301 }
13.302
13.303 if (program && strcmp(program, "<lua>") == 0)
13.304 - retval = run_script_lua(installer->root, script_tag, script,
13.305 - arg1);
13.306 + retval = run_script_lua(installer->root_uri, script_tag,
13.307 + script, arg1, error);
13.308 else
13.309 - retval = run_script_external(installer->root, program, script,
13.310 - arg1);
13.311 + retval = run_script_external(installer->root_uri, program,
13.312 + script, arg1, error);
13.313
13.314 if (rpm->relocations) {
13.315 environment_unset(&env);
13.316 @@ -1040,7 +1088,8 @@
13.317
13.318 int
13.319 razor_run_script(const char *root, enum razor_property_flags script,
13.320 - const char *program, const char *body, int arg1)
13.321 + const char *program, const char *body, int arg1,
13.322 + struct razor_error **error)
13.323 {
13.324 int retval;
13.325 unsigned int script_tag;
13.326 @@ -1071,10 +1120,10 @@
13.327 script_tag = 0;
13.328 break;
13.329 }
13.330 - retval = run_script_lua(root, script_tag, body, arg1);
13.331 + retval = run_script_lua(root, script_tag, body, arg1, error);
13.332 }
13.333 else
13.334 - retval = run_script_external(root, program, body, arg1);
13.335 + retval = run_script_external(root, program, body, arg1, error);
13.336
13.337 return retval;
13.338 }
13.339 @@ -1164,30 +1213,38 @@
13.340
13.341 RAZOR_EXPORT int
13.342 razor_rpm_install(struct razor_rpm *rpm, struct razor_atomic *atomic,
13.343 - const char *root, int install_count,
13.344 + const char *root_uri, int install_count,
13.345 enum razor_stage_type stage)
13.346 {
13.347 struct installer installer;
13.348 struct cpio_file_header *header;
13.349 - struct stat buf;
13.350 unsigned int mode;
13.351 const char *path;
13.352 size_t filesize;
13.353 char *s;
13.354 - int retval = 0, code;
13.355 + int retval = 0, domain, code;
13.356 + struct razor_error *tmp_error = NULL;
13.357
13.358 assert (rpm != NULL);
13.359 - assert (root != NULL);
13.360 + assert (root_uri != NULL);
13.361
13.362 installer.rpm = rpm;
13.363 - installer.root = root;
13.364 + installer.root_uri = root_uri;
13.365 installer.atomic = atomic;
13.366
13.367 /* FIXME: Only do this before a transaction, not per rpm. */
13.368 - if (*root && ((retval = stat(root, &buf)) || !S_ISDIR(buf.st_mode))) {
13.369 - code = retval ? errno : ENOTDIR;
13.370 - s = razor_concat(root, ": Directory does not exist", NULL);
13.371 - razor_atomic_abort(atomic, RAZOR_POSIX_ERROR, code, s);
13.372 + if (*root_uri && razor_uri_is_directory(root_uri, &tmp_error) <= 0) {
13.373 + if (tmp_error) {
13.374 + domain = razor_error_get_domain(tmp_error);
13.375 + code = razor_error_get_code(tmp_error);
13.376 + razor_error_free(tmp_error);
13.377 + tmp_error = NULL;
13.378 + } else {
13.379 + domain = RAZOR_POSIX_ERROR;
13.380 + code = ENOTDIR;
13.381 + }
13.382 + s = razor_concat(root_uri, ": Directory does not exist", NULL);
13.383 + razor_atomic_abort(atomic, domain, code, s);
13.384 free(s);
13.385 return -1;
13.386 }
13.387 @@ -1195,9 +1252,14 @@
13.388 if (rpm->relocations)
13.389 razor_relocations_set_rpm(rpm->relocations, rpm);
13.390
13.391 - if (stage & RAZOR_STAGE_SCRIPTS_PRE)
13.392 + if (stage & RAZOR_STAGE_SCRIPTS_PRE) {
13.393 retval = run_script(&installer, RPMTAG_PREINPROG, RPMTAG_PREIN,
13.394 - install_count);
13.395 + install_count, &tmp_error);
13.396 + if (retval) {
13.397 + razor_atomic_propagate_error(atomic, tmp_error, NULL);
13.398 + tmp_error = NULL;
13.399 + }
13.400 + }
13.401
13.402 if (!retval && (stage & RAZOR_STAGE_FILES)) {
13.403 if (installer_init(&installer))
13.404 @@ -1244,9 +1306,14 @@
13.405 retval = razor_atomic_in_error_state(atomic);
13.406 }
13.407
13.408 - if (!retval && (stage & RAZOR_STAGE_SCRIPTS_POST))
13.409 + if (!retval && (stage & RAZOR_STAGE_SCRIPTS_POST)) {
13.410 retval = run_script(&installer, RPMTAG_POSTINPROG,
13.411 - RPMTAG_POSTIN, install_count);
13.412 + RPMTAG_POSTIN, install_count, &tmp_error);
13.413 + if (retval) {
13.414 + razor_atomic_propagate_error(atomic, tmp_error, NULL);
13.415 + tmp_error = NULL;
13.416 + }
13.417 + }
13.418
13.419 return retval;
13.420 }
13.421 @@ -1260,7 +1327,7 @@
13.422
13.423 free(rpm->dirs);
13.424 free(rpm->prefixes);
13.425 - err = razor_file_free_contents(rpm->map, rpm->size);
13.426 + err = razor_uri_free_contents(rpm->map, rpm->size);
13.427 free(rpm->evr);
13.428 free(rpm);
13.429
14.1 --- a/librazor/test-lua.c Sat Jun 11 17:56:48 2016 +0100
14.2 +++ b/librazor/test-lua.c Mon Jul 04 10:48:18 2016 +0100
14.3 @@ -1,5 +1,5 @@
14.4 /*
14.5 - * Copyright (C) 2009 J. Ali Harlow <ali@juiblex.co.uk>
14.6 + * Copyright (C) 2009, 2016 J. Ali Harlow <ali@juiblex.co.uk>
14.7 *
14.8 * This program is free software; you can redistribute it and/or modify
14.9 * it under the terms of the GNU General Public License as published by
14.10 @@ -22,8 +22,6 @@
14.11 #include <stdio.h>
14.12 #include <string.h>
14.13 #include <errno.h>
14.14 -#include <sys/types.h>
14.15 -#include <sys/stat.h>
14.16 #include <dirent.h>
14.17 #include <unistd.h>
14.18 #include <math.h>
14.19 @@ -63,18 +61,19 @@
14.20 int r;
14.21 void *script;
14.22 size_t len;
14.23 - char *s, *test_file, *srcdir;
14.24 + char *s, *test_uri, *srcdir, *suffix, *cwd;
14.25 FILE *fp;
14.26 struct razor_error *error = NULL;
14.27 + struct razor_uri base_ru, test_ru, ru;
14.28
14.29 if (argc > 2) {
14.30 - fprintf(stderr, "usage: %s [TESTS-FILE]\n", argv[0]);
14.31 + fprintf(stderr, "usage: %s [TESTS-URI]\n", argv[0]);
14.32 exit(1);
14.33 }
14.34 if (argc == 2)
14.35 - test_file = argv[1];
14.36 + test_uri = argv[1];
14.37 else
14.38 - test_file = "test.lua";
14.39 + test_uri = "test.lua";
14.40
14.41 if (!mkdtemp(root)) {
14.42 perror(root);
14.43 @@ -95,31 +94,68 @@
14.44 chmod(s, S_IRUSR | S_IWUSR | S_IXUSR);
14.45 free(s);
14.46
14.47 - script = razor_file_get_contents(test_file, &len, 0, &error);
14.48 + for (len = 32;; len *= 2) {
14.49 + cwd = malloc(len);
14.50 + if (getcwd(cwd, len))
14.51 + break;
14.52 + free(cwd);
14.53 + }
14.54 + cwd = realloc(cwd, strlen(cwd) + 1);
14.55 +
14.56 + s = razor_concat("file:", cwd, NULL);
14.57 + if (razor_uri_parse(&test_ru, test_uri, &error) ||
14.58 + razor_uri_parse(&base_ru, s, &error)) {
14.59 + fprintf(stderr, "%s\n", razor_error_get_msg(error));
14.60 + razor_error_free(error);
14.61 + exit(1);
14.62 + }
14.63 + free(s);
14.64 +
14.65 + razor_uri_resolve(&ru, &base_ru, &test_ru);
14.66 + razor_uri_destroy(&base_ru);
14.67 + s = razor_uri_recompose(&ru);
14.68 + razor_uri_destroy(&ru);
14.69 + script = razor_uri_get_contents(s, &len, 0, &error);
14.70 + free(s);
14.71 if (!script) {
14.72 srcdir = getenv("srcdir");
14.73 - if (srcdir && errno == ENOENT && *test_file != '/') {
14.74 + if (srcdir && errno == ENOENT) {
14.75 razor_error_free(error);
14.76 - s = malloc(strlen(srcdir) + strlen(test_file) + 2);
14.77 - strcpy(s, srcdir);
14.78 - strcat(s, "/");
14.79 - strcat(s, test_file);
14.80 - script = razor_file_get_contents(s, &len, 0, &error);
14.81 - if (!script) {
14.82 + error = NULL;
14.83 + suffix = srcdir[strlen(srcdir) - 1] == '/' ? NULL : "/";
14.84 + if (*srcdir == '/')
14.85 + s = razor_concat("file:", srcdir, suffix, NULL);
14.86 + else
14.87 + s = razor_concat("file:", cwd, "/", srcdir,
14.88 + suffix, NULL);
14.89 + razor_uri_parse(&base_ru, s, &error);
14.90 + free(s);
14.91 + if (!error) {
14.92 + razor_uri_resolve(&ru, &base_ru, &test_ru);
14.93 + razor_uri_destroy(&base_ru);
14.94 + s = razor_uri_recompose(&ru);
14.95 + razor_uri_destroy(&ru);
14.96 + script = razor_uri_get_contents(s, &len, 0,
14.97 + &error);
14.98 + free(s);
14.99 + }
14.100 + if (error) {
14.101 fprintf(stderr, "%s\n",
14.102 razor_error_get_msg(error));
14.103 razor_error_free(error);
14.104 exit(1);
14.105 }
14.106 - free(s);
14.107 } else {
14.108 fprintf(stderr, "%s\n", razor_error_get_msg(error));
14.109 razor_error_free(error);
14.110 exit(1);
14.111 }
14.112 }
14.113 - r = run_lua_script(root, test_file, script, len, -1);
14.114 - razor_file_free_contents(script, len);
14.115 + razor_uri_destroy(&test_ru);
14.116 + free(cwd);
14.117 +
14.118 + r = run_lua_script(root, test_uri, script, len, -1);
14.119 + razor_uri_free_contents(script, len);
14.120
14.121 recursive_remove(root);
14.122 exit(r ? 1 : 0);
15.1 --- a/librazor/test-pfu.c Sat Jun 11 17:56:48 2016 +0100
15.2 +++ b/librazor/test-pfu.c Mon Jul 04 10:48:18 2016 +0100
15.3 @@ -1,5 +1,5 @@
15.4 /*
15.5 - * Copyright (C) 2014 J. Ali Harlow <ali@juiblex.co.uk>
15.6 + * Copyright (C) 2014, 2016 J. Ali Harlow <ali@juiblex.co.uk>
15.7 *
15.8 * This program is free software; you can redistribute it and/or modify
15.9 * it under the terms of the GNU General Public License as published by
15.10 @@ -26,17 +26,18 @@
15.11 #endif
15.12 #include "razor.h"
15.13
15.14 -int is_ascii_letter(char c)
15.15 +#ifdef MSWIN_API
15.16 +static int is_ascii_letter(char c)
15.17 {
15.18 return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
15.19 }
15.20
15.21 -int is_slash(char c)
15.22 +static int is_slash(char c)
15.23 {
15.24 return c == '/' || c == '\\';
15.25 }
15.26
15.27 -const char *mswin_path(const char *path)
15.28 +static const char *mswin_path(const char *path)
15.29 {
15.30 if (path == NULL)
15.31 return NULL;
15.32 @@ -47,8 +48,9 @@
15.33
15.34 return path;
15.35 }
15.36 +#endif
15.37
15.38 -int path_cmp(const char *p1, const char *p2)
15.39 +static int path_cmp(const char *p1, const char *p2)
15.40 {
15.41 #ifdef MSWIN_API
15.42 while(*p1 && *p2) {
15.43 @@ -65,12 +67,13 @@
15.44 #endif
15.45 }
15.46
15.47 -int test_pfu(const char *url, const char *path)
15.48 +static int test_pfu(const char *uri, const char *path)
15.49 {
15.50 char *s;
15.51 int r;
15.52 + struct razor_error *error = NULL;
15.53
15.54 - s = razor_path_from_url(url);
15.55 + s = razor_path_from_uri(uri, &error);
15.56
15.57 #ifdef MSWIN_API
15.58 path = mswin_path(path);
15.59 @@ -82,18 +85,21 @@
15.60 r = (s != path);
15.61
15.62 if (r) {
15.63 - fprintf(stderr, "Fail: razor_path_from_url(\"%s\")", url);
15.64 + fprintf(stderr, "Fail: razor_path_from_uri(\"%s\")", uri);
15.65 if (s)
15.66 fprintf(stderr, " returns \"%s\", expected", s);
15.67 else
15.68 - fprintf(stderr, " returns NULL, expected");
15.69 + fprintf(stderr, " fails (%s), expected",
15.70 + razor_error_get_msg(error));
15.71 if (path)
15.72 fprintf(stderr, " \"%s\"\n", path);
15.73 else
15.74 - fprintf(stderr, " NULL\n");
15.75 + fprintf(stderr, " failure\n");
15.76 }
15.77
15.78 free(s);
15.79 + if (error)
15.80 + razor_error_free(error);
15.81
15.82 return r;
15.83 }
15.84 @@ -101,7 +107,7 @@
15.85 #ifdef MSWIN_API
15.86 UINT saved_cp;
15.87
15.88 -void cleanup_on_exit(void)
15.89 +static void cleanup_on_exit(void)
15.90 {
15.91 SetConsoleOutputCP(saved_cp);
15.92 }
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
16.2 +++ b/librazor/test-uri.c Mon Jul 04 10:48:18 2016 +0100
16.3 @@ -0,0 +1,244 @@
16.4 +/*
16.5 + * Copyright (C) 2016 J. Ali Harlow <ali@juiblex.co.uk>
16.6 + *
16.7 + * This program is free software; you can redistribute it and/or modify
16.8 + * it under the terms of the GNU General Public License as published by
16.9 + * the Free Software Foundation; either version 2 of the License, or
16.10 + * (at your option) any later version.
16.11 + *
16.12 + * This program is distributed in the hope that it will be useful,
16.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
16.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16.15 + * GNU General Public License for more details.
16.16 + *
16.17 + * You should have received a copy of the GNU General Public License along
16.18 + * with this program; if not, write to the Free Software Foundation, Inc.,
16.19 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16.20 + */
16.21 +
16.22 +#include "config.h"
16.23 +
16.24 +#include <stdlib.h>
16.25 +#include <stdio.h>
16.26 +#include <string.h>
16.27 +#include "razor.h"
16.28 +#include "razor-internal.h"
16.29 +
16.30 +static int test_parse(const char *uri)
16.31 +{
16.32 + struct razor_uri ru;
16.33 + struct razor_error *error = NULL;
16.34 + int r;
16.35 +
16.36 + r = razor_uri_parse(&ru, uri, &error);
16.37 + razor_uri_destroy(&ru);
16.38 +
16.39 + if (r < 0) {
16.40 + fprintf(stderr, "Fail: razor_uri_parse(\"%s\") reports %s\n",
16.41 + uri, razor_error_get_msg(error));
16.42 + return -1;
16.43 + }
16.44 +
16.45 + return r;
16.46 +}
16.47 +
16.48 +static int test_normalize(const char *uri, const char *expected_normalized_uri)
16.49 +{
16.50 + struct razor_uri ru;
16.51 + struct razor_error *error = NULL;
16.52 + int r;
16.53 + char *normalized_uri;
16.54 +
16.55 + r = razor_uri_parse(&ru, uri, &error);
16.56 +
16.57 + if (r < 0) {
16.58 + razor_uri_destroy(&ru);
16.59 + fprintf(stderr, "Fail: razor_uri_parse(\"%s\") reports %s\n",
16.60 + uri, razor_error_get_msg(error));
16.61 + return -1;
16.62 + }
16.63 +
16.64 + razor_uri_normalize(&ru);
16.65 + normalized_uri = razor_uri_recompose(&ru);
16.66 + razor_uri_destroy(&ru);
16.67 +
16.68 + if (strcmp(normalized_uri, expected_normalized_uri)) {
16.69 + fprintf(stderr, "Fail: normalization of \"%s\" produces "
16.70 + "\"%s\", expected \"%s\"\n", uri, normalized_uri,
16.71 + expected_normalized_uri);
16.72 + r = -1;
16.73 + }
16.74 +
16.75 + free(normalized_uri);
16.76 + return r;
16.77 +}
16.78 +
16.79 +static int test_resolve(const char *base_uri, const char *relative_reference,
16.80 + const char *expected_target_uri)
16.81 +{
16.82 + struct razor_uri base_ru, rr_ru, target_ru;
16.83 + struct razor_error *error = NULL;
16.84 + char *target_uri;
16.85 + int r;
16.86 +
16.87 + r = razor_uri_parse(&base_ru, base_uri, &error);
16.88 +
16.89 + if (r < 0) {
16.90 + fprintf(stderr, "Fail: razor_uri_parse(\"%s\") reports %s\n",
16.91 + base_uri, razor_error_get_msg(error));
16.92 + return -1;
16.93 + }
16.94 +
16.95 + r = razor_uri_parse(&rr_ru, relative_reference, &error);
16.96 +
16.97 + if (r < 0) {
16.98 + fprintf(stderr, "Fail: razor_uri_parse(\"%s\") reports %s\n",
16.99 + relative_reference, razor_error_get_msg(error));
16.100 + razor_uri_destroy(&base_ru);
16.101 + return -1;
16.102 + }
16.103 +
16.104 + razor_uri_resolve(&target_ru, &base_ru, &rr_ru);
16.105 + razor_uri_destroy(&base_ru);
16.106 + razor_uri_destroy(&rr_ru);
16.107 +
16.108 + target_uri = razor_uri_recompose(&target_ru);
16.109 + razor_uri_destroy(&target_ru);
16.110 +
16.111 + if (strcmp(target_uri, expected_target_uri)) {
16.112 + fprintf(stderr,
16.113 + "Fail: razor_uri_resolve(\"%s\", \"%s\") returns %s\n",
16.114 + base_uri, relative_reference, target_uri);
16.115 + free(target_uri);
16.116 + return -1;
16.117 + }
16.118 +
16.119 + free(target_uri);
16.120 +
16.121 + return 0;
16.122 +}
16.123 +
16.124 +int main(int argc, char *argv[])
16.125 +{
16.126 + int r = 0;
16.127 +
16.128 + r |= test_parse("file:");
16.129 + r |= test_parse("file:/");
16.130 + r |= test_parse("file:///");
16.131 +
16.132 + /* From RFC 3986 § 6.2.2 */
16.133 + r |= test_normalize("eXAMPLE://a/./b/../b/%63/%7bfoo%7d",
16.134 + "example://a/b/c/%7Bfoo%7D");
16.135 +
16.136 + /* From RFC 3986 § 5.4.1 */
16.137 + r |= test_resolve("http://a/b/c/d;p?q", "g:h", "g:h");
16.138 + r |= test_resolve("http://a/b/c/d;p?q", "g", "http://a/b/c/g");
16.139 + r |= test_resolve("http://a/b/c/d;p?q", "./g", "http://a/b/c/g");
16.140 + r |= test_resolve("http://a/b/c/d;p?q", "g/", "http://a/b/c/g/");
16.141 + r |= test_resolve("http://a/b/c/d;p?q", "/g", "http://a/g");
16.142 + r |= test_resolve("http://a/b/c/d;p?q", "//g", "http://g");
16.143 + r |= test_resolve("http://a/b/c/d;p?q", "?y", "http://a/b/c/d;p?y");
16.144 + r |= test_resolve("http://a/b/c/d;p?q", "g?y", "http://a/b/c/g?y");
16.145 + r |= test_resolve("http://a/b/c/d;p?q", "#s", "http://a/b/c/d;p?q#s");
16.146 + r |= test_resolve("http://a/b/c/d;p?q", "g#s", "http://a/b/c/g#s");
16.147 + r |= test_resolve("http://a/b/c/d;p?q", "g?y#s", "http://a/b/c/g?y#s");
16.148 + r |= test_resolve("http://a/b/c/d;p?q", ";x", "http://a/b/c/;x");
16.149 + r |= test_resolve("http://a/b/c/d;p?q", "g;x", "http://a/b/c/g;x");
16.150 + r |= test_resolve("http://a/b/c/d;p?q", "g;x?y#s",
16.151 + "http://a/b/c/g;x?y#s");
16.152 + r |= test_resolve("http://a/b/c/d;p?q", "", "http://a/b/c/d;p?q");
16.153 + r |= test_resolve("http://a/b/c/d;p?q", ".", "http://a/b/c/");
16.154 + r |= test_resolve("http://a/b/c/d;p?q", "./", "http://a/b/c/");
16.155 + r |= test_resolve("http://a/b/c/d;p?q", "..", "http://a/b/");
16.156 + r |= test_resolve("http://a/b/c/d;p?q", "../", "http://a/b/");
16.157 + r |= test_resolve("http://a/b/c/d;p?q", "../g", "http://a/b/g");
16.158 + r |= test_resolve("http://a/b/c/d;p?q", "../..", "http://a/");
16.159 + r |= test_resolve("http://a/b/c/d;p?q", "../../", "http://a/");
16.160 + r |= test_resolve("http://a/b/c/d;p?q", "../../g", "http://a/g");
16.161 +
16.162 + r |= test_resolve("http://a/b/c/d;p?q", "../../../g", "http://a/g");
16.163 + r |= test_resolve("http://a/b/c/d;p?q", "../../../../g", "http://a/g");
16.164 +
16.165 + r |= test_resolve("http://a/b/c/d;p?q", "/./g", "http://a/g");
16.166 + r |= test_resolve("http://a/b/c/d;p?q", "/../g", "http://a/g");
16.167 + r |= test_resolve("http://a/b/c/d;p?q", "g.", "http://a/b/c/g.");
16.168 + r |= test_resolve("http://a/b/c/d;p?q", ".g", "http://a/b/c/.g");
16.169 + r |= test_resolve("http://a/b/c/d;p?q", "g..", "http://a/b/c/g..");
16.170 + r |= test_resolve("http://a/b/c/d;p?q", "..g", "http://a/b/c/..g");
16.171 +
16.172 + r |= test_resolve("http://a/b/c/d;p?q", "./../g", "http://a/b/g");
16.173 + r |= test_resolve("http://a/b/c/d;p?q", "./g/.", "http://a/b/c/g/");
16.174 + r |= test_resolve("http://a/b/c/d;p?q", "g/./h", "http://a/b/c/g/h");
16.175 + r |= test_resolve("http://a/b/c/d;p?q", "g/../h", "http://a/b/c/h");
16.176 + r |= test_resolve("http://a/b/c/d;p?q", "g;x=1/./y",
16.177 + "http://a/b/c/g;x=1/y");
16.178 + r |= test_resolve("http://a/b/c/d;p?q", "g;x=1/../y", "http://a/b/c/y");
16.179 +
16.180 + r |= test_resolve("http://a/b/c/d;p?q", "g?y/./x",
16.181 + "http://a/b/c/g?y/./x");
16.182 + r |= test_resolve("http://a/b/c/d;p?q", "g?y/../x",
16.183 + "http://a/b/c/g?y/../x");
16.184 + r |= test_resolve("http://a/b/c/d;p?q", "g#s/./x",
16.185 + "http://a/b/c/g#s/./x");
16.186 + r |= test_resolve("http://a/b/c/d;p?q", "g#s/../x",
16.187 + "http://a/b/c/g#s/../x");
16.188 +
16.189 + r |= test_resolve("http://a/b/c/d;p?q", "http:g", "http:g");
16.190 +
16.191 + /* From http://www.w3.org/2000/10/swap/uripath.py */
16.192 + r |= test_resolve("foo:xyz", "bar:abc", "bar:abc");
16.193 +
16.194 + r |= test_resolve("http://example/x/y/z", "../abc",
16.195 + "http://example/x/abc");
16.196 + r |= test_resolve("http://example2/x/y/z", "http://example/x/abc",
16.197 + "http://example/x/abc");
16.198 + r |= test_resolve("http://ex/x/y/z", "../r", "http://ex/x/r");
16.199 + // "http://ex/x/y/z", "../../r", "http://ex/r"); // DanC had this.
16.200 + r |= test_resolve("http://ex/x/y", "q/r", "http://ex/x/q/r");
16.201 + r |= test_resolve("http://ex/x/y", "q/r#s", "http://ex/x/q/r#s");
16.202 + r |= test_resolve("http://ex/x/y", "q/r#s/t", "http://ex/x/q/r#s/t");
16.203 + r |= test_resolve("http://ex/x/y", "ftp://ex/x/q/r", "ftp://ex/x/q/r");
16.204 + r |= test_resolve("http://ex/x/y", "", "http://ex/x/y");
16.205 + r |= test_resolve("http://ex/x/y/", "", "http://ex/x/y/");
16.206 + r |= test_resolve("http://ex/x/y/pdq", "", "http://ex/x/y/pdq");
16.207 + r |= test_resolve("http://ex/x/y/", "z/", "http://ex/x/y/z/");
16.208 + r |= test_resolve("file:/swap/test/animal.rdf", "#Animal",
16.209 + "file:/swap/test/animal.rdf#Animal");
16.210 + r |= test_resolve("file:/e/x/y/z", "../abc", "file:/e/x/abc");
16.211 + r |= test_resolve("file:/example2/x/y/z", "/example/x/abc",
16.212 + "file:/example/x/abc");
16.213 + r |= test_resolve("file:/ex/x/y/z", "../r", "file:/ex/x/r");
16.214 + r |= test_resolve("file:/ex/x/y/z", "/r", "file:/r");
16.215 + r |= test_resolve("file:/ex/x/y", "q/r", "file:/ex/x/q/r");
16.216 + r |= test_resolve("file:/ex/x/y", "q/r#s", "file:/ex/x/q/r#s");
16.217 + r |= test_resolve("file:/ex/x/y", "q/r#", "file:/ex/x/q/r#");
16.218 + r |= test_resolve("file:/ex/x/y", "q/r#s/t", "file:/ex/x/q/r#s/t");
16.219 + r |= test_resolve("file:/ex/x/y", "ftp://ex/x/q/r", "ftp://ex/x/q/r");
16.220 + r |= test_resolve("file:/ex/x/y", "", "file:/ex/x/y");
16.221 + r |= test_resolve("file:/ex/x/y/", "", "file:/ex/x/y/");
16.222 + r |= test_resolve("file:/ex/x/y/pdq", "", "file:/ex/x/y/pdq");
16.223 + r |= test_resolve("file:/ex/x/y/", "z/", "file:/ex/x/y/z/");
16.224 + r |= test_resolve("file:/devel/WWW/2000/10/swap/test/reluri-1.n3",
16.225 + "file://meetings.example.com/cal#m1",
16.226 + "file://meetings.example.com/cal#m1");
16.227 + r |= test_resolve("file:/home/connolly/w3ccvs/WWW/2000/10/swap/test/reluri-1.n3",
16.228 + "file://meetings.example.com/cal#m1",
16.229 + "file://meetings.example.com/cal#m1");
16.230 + r |= test_resolve("file:/some/dir/foo", "./#blort",
16.231 + "file:/some/dir/#blort");
16.232 + r |= test_resolve("file:/some/dir/foo", "./#", "file:/some/dir/#");
16.233 + /* From Graham Klyne Thu, 20 Feb 2003 18:08:17 +0000 */
16.234 + r |= test_resolve("http://example/x/y%2Fz", "abc",
16.235 + "http://example/x/abc");
16.236 + r |= test_resolve("http://example/x/y/z", "/x%2Fabc",
16.237 + "http://example/x%2Fabc");
16.238 + r |= test_resolve("http://example/x/y%2Fz", "/x%2Fabc",
16.239 + "http://example/x%2Fabc");
16.240 + r |= test_resolve("http://example/x%2Fy/z", "abc",
16.241 + "http://example/x%2Fy/abc");
16.242 + /* Ryan Lee */
16.243 + r |= test_resolve("http://example/x/abc.efg", "./",
16.244 + "http://example/x/");
16.245 +
16.246 + exit(r ? 1 : 0);
16.247 +}
17.1 --- a/librazor/transaction.c Sat Jun 11 17:56:48 2016 +0100
17.2 +++ b/librazor/transaction.c Mon Jul 04 10:48:18 2016 +0100
17.3 @@ -26,11 +26,7 @@
17.4 #include <stdint.h>
17.5 #include <stdio.h>
17.6 #include <string.h>
17.7 -#include <sys/types.h>
17.8 -#include <sys/stat.h>
17.9 #include <unistd.h>
17.10 -#include <fcntl.h>
17.11 -#include <errno.h>
17.12 #include <ctype.h>
17.13 #include <assert.h>
17.14
18.1 --- a/librazor/types/array.c Sat Jun 11 17:56:48 2016 +0100
18.2 +++ b/librazor/types/array.c Mon Jul 04 10:48:18 2016 +0100
18.3 @@ -1,6 +1,7 @@
18.4 /*
18.5 * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
18.6 * Copyright (C) 2008 Red Hat, Inc
18.7 + * Copyright (C) 2016 J. Ali Harlow <ali@juiblex.co.uk>
18.8 *
18.9 * This program is free software; you can redistribute it and/or modify
18.10 * it under the terms of the GNU General Public License as published by
18.11 @@ -23,42 +24,100 @@
18.12
18.13 #include "types.h"
18.14
18.15 -void
18.16 -array_init(struct array *array)
18.17 +void array_init(struct array *array)
18.18 {
18.19 memset(array, 0, sizeof *array);
18.20 }
18.21
18.22 -void
18.23 -array_release(struct array *array)
18.24 +void array_release(struct array *array)
18.25 {
18.26 free(array->data);
18.27 }
18.28
18.29 -void *
18.30 -array_add(struct array *array, int size)
18.31 +int array_set_size(struct array *array, int size)
18.32 {
18.33 int alloc;
18.34 - void *data, *p;
18.35 + void *data;
18.36
18.37 if (array->alloc > 0)
18.38 alloc = array->alloc;
18.39 + else if (size > 0)
18.40 + alloc = 16;
18.41 else
18.42 - alloc = 16;
18.43 + alloc = 0;
18.44
18.45 - while (alloc < array->size + size)
18.46 + while (alloc < size)
18.47 alloc *= 2;
18.48
18.49 - if (array->alloc < alloc) {
18.50 + if (!alloc) {
18.51 + free(array->data);
18.52 + array->data = NULL;
18.53 + array->alloc = 0;
18.54 + } else if (array->alloc < alloc) {
18.55 data = realloc(array->data, alloc);
18.56 if (data == NULL)
18.57 - return 0;
18.58 + return -1;
18.59 array->data = data;
18.60 array->alloc = alloc;
18.61 }
18.62
18.63 - p = array->data + array->size;
18.64 - array->size += size;
18.65 + array->size = size;
18.66
18.67 - return p;
18.68 + return 0;
18.69 }
18.70 +
18.71 +void *array_add(struct array *array, int size)
18.72 +{
18.73 + if (array_set_size(array, array->size + size) < 0)
18.74 + return NULL;
18.75 +
18.76 + return array->data + array->size - size;
18.77 +}
18.78 +
18.79 +void ptr_array_add(struct array *ptr_array, void *data)
18.80 +{
18.81 + void **ptr, **ptrend;
18.82 +
18.83 + ptrend = ptr_array->data + ptr_array->size;
18.84 + for (ptr = ptr_array->data; ptr < ptrend; ptr++)
18.85 + if (!*ptr)
18.86 + break;
18.87 +
18.88 + if (ptr == ptrend)
18.89 + ptr = array_add(ptr_array, sizeof *ptr);
18.90 +
18.91 + *ptr = data;
18.92 +}
18.93 +
18.94 +int ptr_array_find(struct array *ptr_array, void *data)
18.95 +{
18.96 + void **ptr, **ptrend;
18.97 +
18.98 + ptrend = ptr_array->data + ptr_array->size;
18.99 + for (ptr = ptr_array->data; ptr < ptrend; ptr++)
18.100 + if (*ptr == data)
18.101 + return ptr - (void **)ptr_array->data;
18.102 +
18.103 + return -1;
18.104 +}
18.105 +
18.106 +void ptr_array_remove_index(struct array *ptr_array, int indx)
18.107 +{
18.108 + void **ptr, **ptrend;
18.109 +
18.110 + ptrend = ptr_array->data + ptr_array->size;
18.111 +
18.112 + ptr = (void **)ptr_array->data + indx;
18.113 + if (ptr >= ptrend)
18.114 + return;
18.115 + *ptr = NULL;
18.116 +
18.117 + for (ptr = ptr_array->data; ptr < ptrend; ptr++)
18.118 + if (*ptr)
18.119 + break;
18.120 +
18.121 + if (ptr == ptrend) {
18.122 + array_release(ptr_array);
18.123 + array_init(ptr_array);
18.124 + }
18.125 +}
19.1 --- a/librazor/types/types.h Sat Jun 11 17:56:48 2016 +0100
19.2 +++ b/librazor/types/types.h Mon Jul 04 10:48:18 2016 +0100
19.3 @@ -35,7 +35,11 @@
19.4
19.5 void array_init(struct array *array);
19.6 void array_release(struct array *array);
19.7 +int array_set_size(struct array *array, int size);
19.8 void *array_add(struct array *array, int size);
19.9 +void ptr_array_add(struct array *ptr_array, void *data);
19.10 +int ptr_array_find(struct array *ptr_array, void *data);
19.11 +void ptr_array_remove_index(struct array *ptr_array, int indx);
19.12
19.13
19.14 #define RAZOR_ENTRY_LAST 0x80
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
20.2 +++ b/librazor/uri-io.c Mon Jul 04 10:48:18 2016 +0100
20.3 @@ -0,0 +1,1177 @@
20.4 +/*
20.5 + * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
20.6 + * Copyright (C) 2008 Red Hat, Inc
20.7 + * Copyright (C) 2009, 2011, 2012, 2014, 2016 J. Ali Harlow <ali@juiblex.co.uk>
20.8 + *
20.9 + * This program is free software; you can redistribute it and/or modify
20.10 + * it under the terms of the GNU General Public License as published by
20.11 + * the Free Software Foundation; either version 2 of the License, or
20.12 + * (at your option) any later version.
20.13 + *
20.14 + * This program is distributed in the hope that it will be useful,
20.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
20.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20.17 + * GNU General Public License for more details.
20.18 + *
20.19 + * You should have received a copy of the GNU General Public License along
20.20 + * with this program; if not, write to the Free Software Foundation, Inc.,
20.21 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20.22 + */
20.23 +
20.24 +#include "config.h"
20.25 +
20.26 +#include <limits.h>
20.27 +#include <string.h>
20.28 +#include <sys/types.h>
20.29 +#include <sys/stat.h>
20.30 +#include <stdlib.h>
20.31 +#include <stdio.h>
20.32 +#include <stdint.h>
20.33 +#include <errno.h>
20.34 +#include <unistd.h>
20.35 +#include <fcntl.h>
20.36 +#include <dirent.h>
20.37 +#ifdef MSWIN_API
20.38 +#include <windows.h>
20.39 +#include <direct.h>
20.40 +#endif
20.41 +#if HAVE_SYS_MMAN_H
20.42 +#include <sys/mman.h>
20.43 +#endif
20.44 +#include <assert.h>
20.45 +
20.46 +#include "razor.h"
20.47 +#include "types/types.h"
20.48 +#include "razor-internal.h"
20.49 +
20.50 +#ifndef O_BINARY
20.51 +#define O_BINARY 0
20.52 +#endif
20.53 +
20.54 +#define strcmp0(s1, s2) ((s1) && (s2) ? strcmp(s1, s2) : \
20.55 + (s1) ? 1 : (s2) ? -1 : 0)
20.56 +
20.57 +#define OPEN_FILE_USED (1U<<0)
20.58 +#define OPEN_FILE_MMAPPED (1U<<1)
20.59 +
20.60 +struct open_file {
20.61 + void *addr;
20.62 + size_t length;
20.63 + uint32_t flags;
20.64 +};
20.65 +
20.66 +struct array open_files = { 0, };
20.67 +
20.68 +void *razor_file_get_contents(const char *filename, size_t *length, int private,
20.69 + struct razor_error **error)
20.70 +{
20.71 + int fd;
20.72 + struct stat st;
20.73 + void *addr = NULL;
20.74 + size_t nb;
20.75 + ssize_t res;
20.76 + struct open_file *of, *ofend;
20.77 +
20.78 + fd = open(filename, O_RDONLY | O_BINARY);
20.79 + if (fd < 0) {
20.80 + razor_set_error_posix(error, filename);
20.81 + return NULL;
20.82 + }
20.83 +
20.84 + if (fstat(fd, &st) < 0) {
20.85 + razor_set_error_posix(error, filename);
20.86 + close(fd);
20.87 + return NULL;
20.88 + }
20.89 +
20.90 + *length = st.st_size;
20.91 +
20.92 + ofend = open_files.data + open_files.size;
20.93 + for (of = open_files.data; of < ofend; of++)
20.94 + if (!(of->flags & OPEN_FILE_USED))
20.95 + break;
20.96 + if (of == ofend) {
20.97 + of = array_add(&open_files, sizeof *of);
20.98 + of->flags = 0;
20.99 + }
20.100 +
20.101 +#if HAVE_SYS_MMAN_H
20.102 + if (!private) {
20.103 + addr = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
20.104 + if (addr == MAP_FAILED)
20.105 + addr = NULL;
20.106 + else
20.107 + of->flags = OPEN_FILE_USED | OPEN_FILE_MMAPPED;
20.108 + }
20.109 +#endif /* HAVE_SYS_MMAN_H */
20.110 + if (!addr) {
20.111 + addr = malloc(st.st_size);
20.112 + if (addr) {
20.113 + of->flags = OPEN_FILE_USED;
20.114 + nb = 0;
20.115 + while(nb < st.st_size) {
20.116 + res = read(fd, addr + nb, st.st_size - nb);
20.117 + if (res <= 0) {
20.118 + razor_set_error_posix(error, filename);
20.119 + free(addr);
20.120 + addr = NULL;
20.121 + break;
20.122 + }
20.123 + nb += res;
20.124 + }
20.125 + } else
20.126 + razor_set_error(error, RAZOR_POSIX_ERROR, ENOMEM, NULL,
20.127 + "Not enough memory");
20.128 + }
20.129 + close(fd);
20.130 +
20.131 + of->addr = addr;
20.132 + of->length = st.st_size;
20.133 +
20.134 + return addr;
20.135 +}
20.136 +
20.137 +int razor_file_free_contents(void *addr, size_t length)
20.138 +{
20.139 +#if HAVE_SYS_MMAN_H
20.140 + int mmapped;
20.141 +#endif
20.142 + struct open_file *of, *ofend;
20.143 +
20.144 + ofend = open_files.data + open_files.size;
20.145 + for (of = open_files.data; of < ofend; of++)
20.146 + if ((of->flags & OPEN_FILE_USED) && of->addr == addr)
20.147 + break;
20.148 +
20.149 + if (of == ofend)
20.150 + return -2;
20.151 +
20.152 + length = of->length;
20.153 +#if HAVE_SYS_MMAN_H
20.154 + mmapped = of->flags & OPEN_FILE_MMAPPED;
20.155 +#endif
20.156 + of->flags &= ~OPEN_FILE_USED;
20.157 +
20.158 + for (of = open_files.data; of < ofend; of++)
20.159 + if (of->flags & OPEN_FILE_USED)
20.160 + break;
20.161 +
20.162 + if (of == ofend) {
20.163 + array_release(&open_files);
20.164 + array_init(&open_files);
20.165 + }
20.166 +
20.167 +#if HAVE_SYS_MMAN_H
20.168 + if (mmapped)
20.169 + return munmap(addr, length);
20.170 +#endif
20.171 +
20.172 + free(addr);
20.173 + return 0;
20.174 +}
20.175 +
20.176 +int razor_file_mkdir(const char *path, mode_t mode, struct razor_error **error)
20.177 +{
20.178 + int retval, code;
20.179 + struct stat buf;
20.180 +
20.181 + retval = mkdir(path, mode);
20.182 +
20.183 + if (retval) {
20.184 + /*
20.185 + * Ignore the case of a pre-existing directory and give
20.186 + * an explicit error message if there is something other
20.187 + * than a directory already at path.
20.188 + */
20.189 + code = errno;
20.190 + if (code != EEXIST || stat(path, &buf))
20.191 + razor_set_error(error, RAZOR_POSIX_ERROR, code, path,
20.192 + strerror(code));
20.193 + else if (!S_ISDIR(buf.st_mode))
20.194 + razor_set_error(error, RAZOR_POSIX_ERROR, code, path,
20.195 + "Not a directory");
20.196 + }
20.197 +
20.198 + return retval;
20.199 +}
20.200 +
20.201 +int razor_file_unlink(const char *path, struct razor_error **error)
20.202 +{
20.203 + int retval;
20.204 +
20.205 + retval = unlink(path);
20.206 +
20.207 + if (retval)
20.208 + razor_set_error_posix(error, path);
20.209 +
20.210 + return retval;
20.211 +}
20.212 +
20.213 +int razor_file_open(const char *path, int flags, mode_t mode,
20.214 + struct razor_error **error)
20.215 +{
20.216 + int retval;
20.217 +
20.218 + retval = open(path, flags, mode);
20.219 +
20.220 + if (retval < 0)
20.221 + razor_set_error_posix(error, path);
20.222 +
20.223 + return retval;
20.224 +}
20.225 +
20.226 +int razor_file_move(const char *path, const char *dest,
20.227 + struct razor_error **error)
20.228 +{
20.229 + int retval = 0;
20.230 +
20.231 +#ifdef MSWIN_API
20.232 + wchar_t *oldbuf, *newbuf;
20.233 + const DWORD flags = MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING;
20.234 +
20.235 + newbuf = razor_utf8_to_utf16(dest, -1);
20.236 + oldbuf = razor_utf8_to_utf16(path, -1);
20.237 +
20.238 + /*
20.239 + * Passing MOVEFILE_REPLACE_EXISTING to MoveFileEx() will
20.240 + * cover every case we care about _except_ replacing an empty
20.241 + * directory with a file. Calling RemoveDirectory() will deal
20.242 + * with this case while having no effect in all other cases.
20.243 + */
20.244 + (void)RemoveDirectoryW(newbuf);
20.245 +
20.246 + if (!MoveFileExW(oldbuf, newbuf, flags)) {
20.247 + razor_set_error_mswin(error, newbuf, GetLastError());
20.248 + retval = -1;
20.249 + }
20.250 +
20.251 + free(newbuf);
20.252 + free(oldbuf);
20.253 +#else
20.254 + int code;
20.255 + const char *object;
20.256 +
20.257 + if (rename(path, dest)) {
20.258 + if (error) {
20.259 + code = errno;
20.260 + if (access(path, F_OK) < 0)
20.261 + object = path;
20.262 + else
20.263 + object = dest;
20.264 + razor_set_error(error, RAZOR_POSIX_ERROR, code, object,
20.265 + strerror(code));
20.266 + }
20.267 + retval = -1;
20.268 + }
20.269 +#endif
20.270 +
20.271 + return retval;
20.272 +}
20.273 +
20.274 +#ifndef MSWIN_API
20.275 +static char *absolute_path(const char *path)
20.276 +{
20.277 + int len;
20.278 + char *result, *subpath, *p, *s, *t;
20.279 +
20.280 + result = realpath(path, NULL);
20.281 +
20.282 + if (!result && errno == ENOENT) {
20.283 + p = strdup(path);
20.284 + s = strrchr(p, '/');
20.285 +
20.286 + while (s) {
20.287 + if (s == p) {
20.288 + result = strdup("/");
20.289 + break;
20.290 + }
20.291 +
20.292 + *s = '\0';
20.293 + subpath = realpath(p, NULL);
20.294 +
20.295 + if (subpath) {
20.296 + *s = '/';
20.297 + len = strlen(subpath);
20.298 + result = malloc(len + strlen(s) + 1);
20.299 + memcpy(result, subpath, len);
20.300 + strcpy(result + len, s);
20.301 + free(subpath);
20.302 + break;
20.303 + } else if (errno != ENOENT)
20.304 + break;
20.305 +
20.306 + t = strrchr(p, '/');
20.307 + *s = '/';
20.308 + s = t;
20.309 + }
20.310 +
20.311 + if (!s)
20.312 + result = realpath(".", NULL);
20.313 +
20.314 + free(p);
20.315 + }
20.316 +
20.317 + return result;
20.318 +}
20.319 +#endif
20.320 +
20.321 +int razor_file_is_directory(const char *path, struct razor_error **error)
20.322 +{
20.323 + struct stat st;
20.324 +
20.325 + if (stat(path, &st) < 0) {
20.326 + razor_set_error_posix(error, path);
20.327 + return -1;
20.328 + }
20.329 +
20.330 + return !!S_ISDIR(st.st_mode);
20.331 +}
20.332 +
20.333 +char *razor_file_mkdtemp_near(const char *path, const char *template,
20.334 + struct razor_error **error)
20.335 +{
20.336 + char *retval;
20.337 +
20.338 +#ifdef MSWIN_API
20.339 + if (path[0]=='\\' && path[1]=='\\' && path[2] && path[2]!='\\'
20.340 + && strchr(path+3,'\\')) {
20.341 + /* We have a UNC path: \\servername\sharename... */
20.342 + const char *sharename, *root;
20.343 + int disklen;
20.344 +
20.345 + sharename = strchr(path+3,'\\')+1;
20.346 + root = strchr(sharename,'\\');
20.347 + if (root)
20.348 + disklen = root - path;
20.349 + else
20.350 + disklen = strlen(path);
20.351 +
20.352 + retval = malloc(disklen + 1 + strlen(template) + 1);
20.353 + memcpy(retval, path, disklen);
20.354 + retval[disklen] = '\\';
20.355 + strcpy(retval + disklen + 1, template);
20.356 + } else if ((*path>='A' && *path<='Z' || *path>='a' && *path<='z') &&
20.357 + path[1]==':') {
20.358 + retval = malloc(3 + strlen(template) + 1);
20.359 + retval[0] = path[0];
20.360 + retval[1] = ':';
20.361 + retval[2] = '\\';
20.362 + strcpy(retval + 3, template);
20.363 + } else {
20.364 + DWORD n;
20.365 + wchar_t *buf;
20.366 + char *dir;
20.367 +
20.368 + n = GetCurrentDirectoryW(0, NULL);
20.369 + buf = malloc(n * sizeof(wchar_t));
20.370 +
20.371 + if (GetCurrentDirectoryW(n, buf)) {
20.372 + dir = razor_utf16_to_utf8(buf, n - 1);
20.373 + free(buf);
20.374 + retval = razor_file_mkdtemp_near(dir, template, error);
20.375 + free(dir);
20.376 + return retval;
20.377 + } else {
20.378 + retval = malloc(3 + strlen(template) + 1);
20.379 + retval[0] = 'C';
20.380 + retval[1] = ':';
20.381 + retval[2] = '\\';
20.382 + strcpy(retval + 3, template);
20.383 + }
20.384 +
20.385 + free(buf);
20.386 + }
20.387 +#else
20.388 + /*
20.389 + * Find the mount point (assuming we can write to the
20.390 + * whole filesystem). Otherwise stop at the first
20.391 + * unwritable directory and take one step back.
20.392 + */
20.393 + char *s, *abspath, saved;
20.394 + int len, can_step_back = 0;
20.395 + dev_t filesystem;
20.396 + struct stat buf;
20.397 +
20.398 + abspath = absolute_path(path);
20.399 + if (!abspath) {
20.400 + razor_set_error_posix(error, path);
20.401 + return NULL;
20.402 + }
20.403 +
20.404 + if (stat(abspath, &buf) < 0) {
20.405 + if (errno == ENOENT)
20.406 + filesystem = 0;
20.407 + else {
20.408 + razor_set_error_posix(error, abspath);
20.409 + free(abspath);
20.410 + return NULL;
20.411 + }
20.412 + } else
20.413 + filesystem = buf.st_dev;
20.414 +
20.415 + len = strlen(abspath);
20.416 + while(len > 1 && (s = strrchr(abspath, '/'))) {
20.417 + if (s == abspath) {
20.418 + saved = s[1];
20.419 + s[1] = '\0';
20.420 + len = s + 1 - abspath;
20.421 + } else {
20.422 + s[0] = '\0';
20.423 + len = s - abspath;
20.424 + }
20.425 +
20.426 + if (stat(abspath, &buf) < 0) {
20.427 + if (errno == ENOENT)
20.428 + continue;
20.429 + else {
20.430 + razor_set_error_posix(error, abspath);
20.431 + free(abspath);
20.432 + return NULL;
20.433 + }
20.434 + } else if (!filesystem)
20.435 + filesystem = buf.st_dev;
20.436 +
20.437 + if (buf.st_dev != filesystem || access(abspath, W_OK)) {
20.438 + if (can_step_back) {
20.439 + if (s == abspath)
20.440 + s[1] = saved;
20.441 + else
20.442 + s[0] = '/';
20.443 + }
20.444 + len = strlen(abspath);
20.445 + break;
20.446 + } else
20.447 + can_step_back = 1;
20.448 + }
20.449 +
20.450 + if (len == 1)
20.451 + len = 0; /* Avoid an unslightly double slash. */
20.452 + retval = malloc(len + 1 + strlen(template) + 1);
20.453 + memcpy(retval, abspath, len);
20.454 + retval[len] = '/';
20.455 + strcpy(retval + len + 1, template);
20.456 +
20.457 + free(abspath);
20.458 +#endif
20.459 +
20.460 + if (!mkdtemp(retval)) {
20.461 + int err = errno;
20.462 +
20.463 +#ifdef EACCES
20.464 + if (err == EACCES) {
20.465 + char *s = strdup(template);
20.466 +
20.467 +#ifndef MSWIN_API
20.468 + if (stat(".", &buf) < 0) {
20.469 + razor_set_error_posix(error, ".");
20.470 + free(s);
20.471 + free(retval);
20.472 + return NULL;
20.473 + }
20.474 + if (buf.st_dev != filesystem)
20.475 + /*
20.476 + * Don't use a different filesystem. It will
20.477 + * only fail later on (in rename) and cause
20.478 + * an unhelpful error message (EXDEV).
20.479 + */
20.480 + free(s);
20.481 + else
20.482 +#endif
20.483 + if (mkdtemp(s)) {
20.484 + free(retval);
20.485 + retval = s;
20.486 + return retval;
20.487 + } else
20.488 + free(s);
20.489 + }
20.490 +#endif
20.491 +
20.492 + razor_set_error(error, RAZOR_POSIX_ERROR, err, retval,
20.493 + strerror(err));
20.494 +
20.495 + free(retval);
20.496 + retval = NULL;
20.497 + }
20.498 +
20.499 + return retval;
20.500 +}
20.501 +
20.502 +struct open_dir {
20.503 + uint32_t flags;
20.504 +#ifdef MSWIN_API
20.505 + _WDIR *dp;
20.506 + wchar_t *path2;
20.507 +#else
20.508 + DIR *dp;
20.509 + char *path;
20.510 +#endif
20.511 +};
20.512 +
20.513 +#define OPEN_DIR_USED (1U<<0)
20.514 +
20.515 +struct array open_dirs = { 0, };
20.516 +
20.517 +void *razor_file_opendir(const char *path, struct razor_error **error)
20.518 +{
20.519 + struct open_dir *od, *odend;
20.520 +
20.521 + odend = open_dirs.data + open_dirs.size;
20.522 + for (od = open_dirs.data; od < odend; od++)
20.523 + if (!(od->flags & OPEN_DIR_USED))
20.524 + break;
20.525 + if (od == odend) {
20.526 + od = array_add(&open_dirs, sizeof *od);
20.527 + od->flags = 0;
20.528 + }
20.529 +
20.530 +#ifdef MSWIN_API
20.531 + od->path2 = razor_utf8_to_utf16(path, -1);
20.532 + od->dp = _wopendir(od->path2);
20.533 +#else
20.534 + od->path = strdup(path);
20.535 + od->dp = opendir(od->path);
20.536 +#endif
20.537 +
20.538 + if (!od->dp) {
20.539 +#ifdef MSWIN_API
20.540 + razor_set_error_mswin(error, od->path2, GetLastError());
20.541 + free(od->path2);
20.542 +#else
20.543 + razor_set_error_posix(error, od->path);
20.544 + free(od->path);
20.545 +#endif
20.546 + return NULL;
20.547 + }
20.548 +
20.549 + od->flags = OPEN_DIR_USED;
20.550 + return od;
20.551 +}
20.552 +
20.553 +char *razor_file_readdir(void *dp, struct razor_error **error)
20.554 +{
20.555 + struct open_dir *od = dp, *odend;
20.556 +#ifdef MSWIN_API
20.557 + struct _wdirent *dirp;
20.558 + char *path;
20.559 +#else
20.560 + struct dirent *dirp;
20.561 +#endif
20.562 +
20.563 + odend = open_dirs.data + open_dirs.size;
20.564 + if (dp < open_dirs.data || od >= odend || !(od->flags & OPEN_DIR_USED))
20.565 + return (char *)-1;
20.566 +
20.567 + errno = 0;
20.568 +
20.569 +#ifdef MSWIN_API
20.570 + while((dirp = _wreaddir(od->dp))) {
20.571 + path = razor_utf16_to_utf8(dirp->d_name, -1);
20.572 + if (strcmp(path, ".") && strcmp(path, ".."))
20.573 + return path;
20.574 + else
20.575 + free(path);
20.576 + }
20.577 +#else
20.578 + while((dirp = readdir(od->dp)))
20.579 + if (strcmp(dirp->d_name, ".") && strcmp(dirp->d_name, ".."))
20.580 + return strdup(dirp->d_name);
20.581 +#endif
20.582 +
20.583 + if (errno) {
20.584 +#ifdef MSWIN_API
20.585 + razor_set_error_mswin(error, od->path2, GetLastError());
20.586 +#else
20.587 + razor_set_error_posix(error, od->path);
20.588 +#endif
20.589 + }
20.590 +
20.591 + return NULL;
20.592 +}
20.593 +
20.594 +int razor_file_closedir(void *dp, struct razor_error **error)
20.595 +{
20.596 + struct open_dir *od = dp, *odend;
20.597 + int retval;
20.598 +
20.599 + odend = open_dirs.data + open_dirs.size;
20.600 + if (dp < open_dirs.data || od >= odend || !(od->flags & OPEN_DIR_USED))
20.601 + return -2;
20.602 +
20.603 +#ifdef MSWIN_API
20.604 + /*
20.605 + * I can't find documentation to state that _wclosedir()
20.606 + * returns -1 on failure, so be paranoid.
20.607 + */
20.608 + retval = _wclosedir(od->dp) ? -1 : 0;
20.609 +#else
20.610 + retval = closedir(od->dp);
20.611 +#endif
20.612 +
20.613 + if (retval) {
20.614 +#ifdef MSWIN_API
20.615 + razor_set_error_mswin(error, od->path2, GetLastError());
20.616 +#else
20.617 + razor_set_error_posix(error, od->path);
20.618 +#endif
20.619 + }
20.620 +
20.621 +#ifdef MSWIN_API
20.622 + free(od->path2);
20.623 +#else
20.624 + free(od->path);
20.625 +#endif
20.626 +
20.627 + od->flags &= ~OPEN_DIR_USED;
20.628 +
20.629 + for (od = open_dirs.data; od < odend; od++)
20.630 + if (od->flags & OPEN_DIR_USED)
20.631 + break;
20.632 +
20.633 + if (od == odend) {
20.634 + array_release(&open_dirs);
20.635 + array_init(&open_dirs);
20.636 + }
20.637 +
20.638 + return retval;
20.639 +}
20.640 +
20.641 +struct razor_uri_vtable_entry {
20.642 + struct razor_uri_vtable vtable;
20.643 + char *scheme;
20.644 + struct array open_files, open_directories;
20.645 +};
20.646 +
20.647 +static struct array razor_uri_vtable_entries;
20.648 +
20.649 +static struct razor_uri_vtable_entry *
20.650 + razor_uri_get_vtable_entry(const char *scheme)
20.651 +{
20.652 + struct razor_uri_vtable_entry *entry, *eend, *fallback = NULL;
20.653 +
20.654 + eend = razor_uri_vtable_entries.data + razor_uri_vtable_entries.size;
20.655 + for(entry = razor_uri_vtable_entries.data; entry < eend; entry++) {
20.656 + if (!strcmp0(entry->scheme, scheme))
20.657 + return entry;
20.658 + else if (!entry->scheme)
20.659 + fallback = entry;
20.660 + }
20.661 +
20.662 + return fallback;
20.663 +}
20.664 +
20.665 +int razor_uri_mkdir(const char *uri, mode_t mode, struct razor_error **error)
20.666 +{
20.667 + int retval;
20.668 + char *path;
20.669 + struct razor_uri ru;
20.670 + struct razor_uri_vtable_entry *entry;
20.671 + struct razor_error *tmp_error = NULL;
20.672 +
20.673 + if (razor_uri_parse(&ru, uri, error))
20.674 + return -1;
20.675 +
20.676 + path = razor_path_from_parsed_uri(&ru, &tmp_error);
20.677 +
20.678 + if (razor_error_matches(tmp_error, RAZOR_GENERAL_ERROR,
20.679 + RAZOR_GENERAL_ERROR_UNSUPPORTED_URI))
20.680 + razor_error_free(tmp_error);
20.681 + else if (!path) {
20.682 + razor_propagate_error(error, tmp_error, NULL);
20.683 + razor_uri_destroy(&ru);
20.684 + return -1;
20.685 + }
20.686 +
20.687 + if (path) {
20.688 + razor_uri_destroy(&ru);
20.689 + retval = razor_file_mkdir(path, mode, error);
20.690 + free(path);
20.691 + } else {
20.692 + entry = razor_uri_get_vtable_entry(ru.scheme);
20.693 + razor_uri_destroy(&ru);
20.694 + if (!entry || !entry->vtable.mkdir) {
20.695 + retval = -1;
20.696 + razor_set_error(error, RAZOR_GENERAL_ERROR,
20.697 + RAZOR_GENERAL_ERROR_UNSUPPORTED_URI,
20.698 + uri, "No URI handler installed");
20.699 + } else
20.700 + retval = entry->vtable.mkdir(uri, mode, error);
20.701 + }
20.702 +
20.703 + return retval;
20.704 +}
20.705 +
20.706 +int razor_uri_unlink(const char *uri, struct razor_error **error)
20.707 +{
20.708 + int retval;
20.709 + char *path;
20.710 + struct razor_uri ru;
20.711 + struct razor_uri_vtable_entry *entry;
20.712 + struct razor_error *tmp_error = NULL;
20.713 +
20.714 + if (razor_uri_parse(&ru, uri, error))
20.715 + return -1;
20.716 +
20.717 + path = razor_path_from_parsed_uri(&ru, &tmp_error);
20.718 +
20.719 + if (razor_error_matches(tmp_error, RAZOR_GENERAL_ERROR,
20.720 + RAZOR_GENERAL_ERROR_UNSUPPORTED_URI))
20.721 + razor_error_free(tmp_error);
20.722 + else if (!path) {
20.723 + razor_propagate_error(error, tmp_error, NULL);
20.724 + razor_uri_destroy(&ru);
20.725 + return -1;
20.726 + }
20.727 +
20.728 + if (path) {
20.729 + razor_uri_destroy(&ru);
20.730 + retval = razor_file_unlink(path, error);
20.731 + free(path);
20.732 + } else {
20.733 + entry = razor_uri_get_vtable_entry(ru.scheme);
20.734 + razor_uri_destroy(&ru);
20.735 + if (!entry || !entry->vtable.unlink) {
20.736 + retval = -1;
20.737 + razor_set_error(error, RAZOR_GENERAL_ERROR,
20.738 + RAZOR_GENERAL_ERROR_UNSUPPORTED_URI,
20.739 + uri, "No URI handler installed");
20.740 + } else
20.741 + retval = entry->vtable.unlink(uri, error);
20.742 + }
20.743 +
20.744 + return retval;
20.745 +}
20.746 +
20.747 +int razor_uri_open(const char *uri, int flags, mode_t mode,
20.748 + struct razor_error **error)
20.749 +{
20.750 + int retval;
20.751 + char *path;
20.752 + struct razor_uri ru;
20.753 + struct razor_uri_vtable_entry *entry;
20.754 + struct razor_error *tmp_error = NULL;
20.755 +
20.756 + if (razor_uri_parse(&ru, uri, error))
20.757 + return -1;
20.758 +
20.759 + path = razor_path_from_parsed_uri(&ru, &tmp_error);
20.760 +
20.761 + if (razor_error_matches(tmp_error, RAZOR_GENERAL_ERROR,
20.762 + RAZOR_GENERAL_ERROR_UNSUPPORTED_URI))
20.763 + razor_error_free(tmp_error);
20.764 + else if (!path) {
20.765 + razor_propagate_error(error, tmp_error, NULL);
20.766 + razor_uri_destroy(&ru);
20.767 + return -1;
20.768 + }
20.769 +
20.770 + if (path) {
20.771 + razor_uri_destroy(&ru);
20.772 + retval = razor_file_open(path, flags, mode, error);
20.773 + free(path);
20.774 + } else {
20.775 + entry = razor_uri_get_vtable_entry(ru.scheme);
20.776 + razor_uri_destroy(&ru);
20.777 + if (!entry || !entry->vtable.open) {
20.778 + retval = -1;
20.779 + razor_set_error(error, RAZOR_GENERAL_ERROR,
20.780 + RAZOR_GENERAL_ERROR_UNSUPPORTED_URI,
20.781 + uri, "No URI handler installed");
20.782 + } else
20.783 + retval = entry->vtable.open(uri, flags, mode, error);
20.784 + }
20.785 +
20.786 + return retval;
20.787 +}
20.788 +
20.789 +int razor_uri_move(const char *src_uri, const char *dst_uri,
20.790 + struct razor_error **error)
20.791 +{
20.792 + int retval;
20.793 + char *src_path, *dst_path;
20.794 + struct razor_uri src_ru, dst_ru;
20.795 + struct razor_uri_vtable_entry *entry;
20.796 + struct razor_error *tmp_error = NULL;
20.797 +
20.798 + if (razor_uri_parse(&src_ru, src_uri, error) ||
20.799 + razor_uri_parse(&dst_ru, dst_uri, error))
20.800 + return -1;
20.801 +
20.802 + src_path = razor_path_from_parsed_uri(&src_ru, &tmp_error);
20.803 +
20.804 + if (razor_error_matches(tmp_error, RAZOR_GENERAL_ERROR,
20.805 + RAZOR_GENERAL_ERROR_UNSUPPORTED_URI))
20.806 + razor_error_free(tmp_error);
20.807 + else if (!src_path) {
20.808 + razor_propagate_error(error, tmp_error, NULL);
20.809 + razor_uri_destroy(&src_ru);
20.810 + return -1;
20.811 + }
20.812 +
20.813 + dst_path = razor_path_from_parsed_uri(&dst_ru, &tmp_error);
20.814 +
20.815 + if (razor_error_matches(tmp_error, RAZOR_GENERAL_ERROR,
20.816 + RAZOR_GENERAL_ERROR_UNSUPPORTED_URI))
20.817 + razor_error_free(tmp_error);
20.818 + else if (!dst_path) {
20.819 + razor_propagate_error(error, tmp_error, NULL);
20.820 + razor_uri_destroy(&dst_ru);
20.821 + razor_uri_destroy(&src_ru);
20.822 + free(src_path);
20.823 + return -1;
20.824 + }
20.825 +
20.826 + if (src_path && dst_path)
20.827 + retval = razor_file_move(src_path, dst_path, error);
20.828 + else {
20.829 + if (!strcmp(src_ru.scheme, dst_ru.scheme))
20.830 + entry = razor_uri_get_vtable_entry(src_ru.scheme);
20.831 + else
20.832 + entry = NULL;
20.833 + if (entry && entry->vtable.move)
20.834 + retval = entry->vtable.move(src_uri, dst_uri, error);
20.835 + else if (strcmp(src_ru.scheme, dst_ru.scheme)) {
20.836 + retval = -1;
20.837 + razor_set_error(error, RAZOR_GENERAL_ERROR,
20.838 + RAZOR_GENERAL_ERROR_UNSUPPORTED_URI,
20.839 + dst_uri, "Cross-scheme URI move");
20.840 + } else {
20.841 + retval = -1;
20.842 + razor_set_error(error, RAZOR_GENERAL_ERROR,
20.843 + RAZOR_GENERAL_ERROR_UNSUPPORTED_URI,
20.844 + src_path ? dst_uri : src_uri,
20.845 + "No URI handler installed");
20.846 + }
20.847 + }
20.848 +
20.849 + razor_uri_destroy(&src_ru);
20.850 + razor_uri_destroy(&dst_ru);
20.851 + free(src_path);
20.852 + free(dst_path);
20.853 +
20.854 + return retval;
20.855 +}
20.856 +
20.857 +void *razor_uri_get_contents(const char *uri, size_t *length, int private,
20.858 + struct razor_error **error)
20.859 +{
20.860 + void *retval;
20.861 + char *path;
20.862 + struct razor_uri ru;
20.863 + struct razor_uri_vtable_entry *entry;
20.864 + struct razor_error *tmp_error = NULL;
20.865 +
20.866 + if (razor_uri_parse(&ru, uri, error))
20.867 + return NULL;
20.868 +
20.869 + path = razor_path_from_parsed_uri(&ru, &tmp_error);
20.870 +
20.871 + if (razor_error_matches(tmp_error, RAZOR_GENERAL_ERROR,
20.872 + RAZOR_GENERAL_ERROR_UNSUPPORTED_URI))
20.873 + razor_error_free(tmp_error);
20.874 + else if (!path) {
20.875 + razor_propagate_error(error, tmp_error, NULL);
20.876 + razor_uri_destroy(&ru);
20.877 + return NULL;
20.878 + }
20.879 +
20.880 + if (path) {
20.881 + razor_uri_destroy(&ru);
20.882 + retval = razor_file_get_contents(path, length, private, error);
20.883 + free(path);
20.884 + } else {
20.885 + entry = razor_uri_get_vtable_entry(ru.scheme);
20.886 + razor_uri_destroy(&ru);
20.887 + if (!entry || !entry->vtable.get_contents) {
20.888 + retval = NULL;
20.889 + razor_set_error(error, RAZOR_GENERAL_ERROR,
20.890 + RAZOR_GENERAL_ERROR_UNSUPPORTED_URI,
20.891 + uri, "No URI handler installed");
20.892 + } else {
20.893 + retval = entry->vtable.get_contents(uri, length,
20.894 + private, error);
20.895 + if (retval)
20.896 + ptr_array_add(&entry->open_files, retval);
20.897 + }
20.898 + }
20.899 +
20.900 + return retval;
20.901 +}
20.902 +
20.903 +int razor_uri_free_contents(void *addr, size_t length)
20.904 +{
20.905 + int retval, of;
20.906 + struct razor_uri_vtable_entry *entry, *eend;
20.907 +
20.908 + if (!addr)
20.909 + return 0;
20.910 +
20.911 + retval = razor_file_free_contents(addr, length);
20.912 +
20.913 + if (retval != -2)
20.914 + return retval;
20.915 +
20.916 + eend = razor_uri_vtable_entries.data + razor_uri_vtable_entries.size;
20.917 + for (entry = razor_uri_vtable_entries.data; entry < eend; entry++) {
20.918 + of = ptr_array_find(&entry->open_files, addr);
20.919 + if (of >= 0) {
20.920 + if (entry->vtable.free_contents)
20.921 + retval = entry->vtable.free_contents(addr,
20.922 + length);
20.923 + ptr_array_remove_index(&entry->open_files, of);
20.924 + break;
20.925 + }
20.926 + }
20.927 +
20.928 + return retval;
20.929 +}
20.930 +
20.931 +int razor_uri_is_directory(const char *uri, struct razor_error **error)
20.932 +{
20.933 + int retval;
20.934 + char *path;
20.935 + struct razor_uri ru;
20.936 + struct razor_uri_vtable_entry *entry;
20.937 + struct razor_error *tmp_error = NULL;
20.938 +
20.939 + if (razor_uri_parse(&ru, uri, error))
20.940 + return -1;
20.941 +
20.942 + path = razor_path_from_parsed_uri(&ru, &tmp_error);
20.943 +
20.944 + if (razor_error_matches(tmp_error, RAZOR_GENERAL_ERROR,
20.945 + RAZOR_GENERAL_ERROR_UNSUPPORTED_URI))
20.946 + razor_error_free(tmp_error);
20.947 + else if (!path) {
20.948 + razor_propagate_error(error, tmp_error, NULL);
20.949 + razor_uri_destroy(&ru);
20.950 + return -1;
20.951 + }
20.952 +
20.953 + if (path) {
20.954 + razor_uri_destroy(&ru);
20.955 + retval = razor_file_is_directory(path, error);
20.956 + free(path);
20.957 + } else {
20.958 + entry = razor_uri_get_vtable_entry(ru.scheme);
20.959 + razor_uri_destroy(&ru);
20.960 + if (!entry || !entry->vtable.is_directory) {
20.961 + retval = -1;
20.962 + razor_set_error(error, RAZOR_GENERAL_ERROR,
20.963 + RAZOR_GENERAL_ERROR_UNSUPPORTED_URI,
20.964 + uri, "No URI handler installed");
20.965 + } else
20.966 + retval = entry->vtable.is_directory(uri, error);
20.967 + }
20.968 +
20.969 + return retval;
20.970 +}
20.971 +
20.972 +char *razor_uri_mkdtemp_near(const char *uri, const char *template,
20.973 + struct razor_error **error)
20.974 +{
20.975 + char *retval, *s;
20.976 + char *path;
20.977 + struct razor_uri ru;
20.978 + struct razor_uri_vtable_entry *entry;
20.979 + struct razor_error *tmp_error = NULL;
20.980 +
20.981 + if (razor_uri_parse(&ru, uri, error))
20.982 + return NULL;
20.983 +
20.984 + path = razor_path_from_parsed_uri(&ru, &tmp_error);
20.985 +
20.986 + if (razor_error_matches(tmp_error, RAZOR_GENERAL_ERROR,
20.987 + RAZOR_GENERAL_ERROR_UNSUPPORTED_URI))
20.988 + razor_error_free(tmp_error);
20.989 + else if (!path) {
20.990 + razor_propagate_error(error, tmp_error, NULL);
20.991 + razor_uri_destroy(&ru);
20.992 + return NULL;
20.993 + }
20.994 +
20.995 + if (path) {
20.996 + razor_uri_destroy(&ru);
20.997 + s = razor_file_mkdtemp_near(path, template, error);
20.998 + retval = razor_path_to_uri(s);
20.999 + free(s);
20.1000 + free(path);
20.1001 + } else {
20.1002 + entry = razor_uri_get_vtable_entry(ru.scheme);
20.1003 + razor_uri_destroy(&ru);
20.1004 + if (!entry || !entry->vtable.mkdtemp_near) {
20.1005 + retval = NULL;
20.1006 + razor_set_error(error, RAZOR_GENERAL_ERROR,
20.1007 + RAZOR_GENERAL_ERROR_UNSUPPORTED_URI,
20.1008 + uri, "No URI handler installed");
20.1009 + } else
20.1010 + retval = entry->vtable.mkdtemp_near(uri, template,
20.1011 + error);
20.1012 + }
20.1013 +
20.1014 + return retval;
20.1015 +}
20.1016 +
20.1017 +void *razor_uri_opendir(const char *uri, struct razor_error **error)
20.1018 +{
20.1019 + void *retval;
20.1020 + char *path;
20.1021 + struct razor_uri ru;
20.1022 + struct razor_uri_vtable_entry *entry;
20.1023 + struct razor_error *tmp_error = NULL;
20.1024 +
20.1025 + if (razor_uri_parse(&ru, uri, error))
20.1026 + return NULL;
20.1027 +
20.1028 + path = razor_path_from_parsed_uri(&ru, &tmp_error);
20.1029 +
20.1030 + if (razor_error_matches(tmp_error, RAZOR_GENERAL_ERROR,
20.1031 + RAZOR_GENERAL_ERROR_UNSUPPORTED_URI))
20.1032 + razor_error_free(tmp_error);
20.1033 + else if (!path) {
20.1034 + razor_propagate_error(error, tmp_error, NULL);
20.1035 + razor_uri_destroy(&ru);
20.1036 + return NULL;
20.1037 + }
20.1038 +
20.1039 + if (path) {
20.1040 + razor_uri_destroy(&ru);
20.1041 + retval = razor_file_opendir(path, error);
20.1042 + free(path);
20.1043 + } else {
20.1044 + entry = razor_uri_get_vtable_entry(ru.scheme);
20.1045 + razor_uri_destroy(&ru);
20.1046 + if (!entry || !entry->vtable.opendir) {
20.1047 + retval = NULL;
20.1048 + razor_set_error(error, RAZOR_GENERAL_ERROR,
20.1049 + RAZOR_GENERAL_ERROR_UNSUPPORTED_URI,
20.1050 + uri, "No URI handler installed");
20.1051 + } else {
20.1052 + retval = entry->vtable.opendir(uri, error);
20.1053 + if (retval)
20.1054 + ptr_array_add(&entry->open_directories, retval);
20.1055 + }
20.1056 + }
20.1057 +
20.1058 + return retval;
20.1059 +}
20.1060 +
20.1061 +char *razor_uri_readdir(void *dir, struct razor_error **error)
20.1062 +{
20.1063 + int od;
20.1064 + char *retval;
20.1065 + struct razor_uri_vtable_entry *entry, *eend;
20.1066 +
20.1067 + retval = razor_file_readdir(dir, error);
20.1068 +
20.1069 + if (retval != (char *)-1)
20.1070 + return retval;
20.1071 +
20.1072 + eend = razor_uri_vtable_entries.data + razor_uri_vtable_entries.size;
20.1073 + for (entry = razor_uri_vtable_entries.data; entry < eend; entry++) {
20.1074 + od = ptr_array_find(&entry->open_directories, dir);
20.1075 + if (od >= 0) {
20.1076 + if (entry->vtable.readdir)
20.1077 + retval = entry->vtable.readdir(dir, error);
20.1078 + break;
20.1079 + }
20.1080 + }
20.1081 +
20.1082 + if (retval == (char *)-1) {
20.1083 + retval = NULL;
20.1084 + razor_set_error(error, RAZOR_GENERAL_ERROR,
20.1085 + RAZOR_GENERAL_ERROR_FAILED, NULL,
20.1086 + "Invalid directory handle");
20.1087 + }
20.1088 +
20.1089 + return retval;
20.1090 +}
20.1091 +
20.1092 +int razor_uri_closedir(void *dir, struct razor_error **error)
20.1093 +{
20.1094 + int od;
20.1095 + int retval;
20.1096 + struct razor_uri_vtable_entry *entry, *eend;
20.1097 +
20.1098 + retval = razor_file_closedir(dir, error);
20.1099 +
20.1100 + if (retval != -2)
20.1101 + return retval;
20.1102 +
20.1103 + eend = razor_uri_vtable_entries.data + razor_uri_vtable_entries.size;
20.1104 + for (entry = razor_uri_vtable_entries.data; entry < eend; entry++) {
20.1105 + od = ptr_array_find(&entry->open_directories, dir);
20.1106 + if (od >= 0) {
20.1107 + if (entry->vtable.closedir)
20.1108 + retval = entry->vtable.closedir(dir, error);
20.1109 + break;
20.1110 + }
20.1111 + }
20.1112 +
20.1113 + if (retval == -2)
20.1114 + razor_set_error(error, RAZOR_GENERAL_ERROR,
20.1115 + RAZOR_GENERAL_ERROR_FAILED, NULL,
20.1116 + "Invalid directory handle");
20.1117 +
20.1118 + return retval;
20.1119 +}
20.1120 +
20.1121 +RAZOR_EXPORT int razor_uri_set_vtable(const char *scheme,
20.1122 + struct razor_uri_vtable *vtable, struct razor_error **error)
20.1123 +{
20.1124 + struct razor_uri_vtable_entry *entry, *eend;
20.1125 +
20.1126 + if (!strcmp0(scheme, "file")) {
20.1127 + /*
20.1128 + * There's no fundamental reason why we couldn't support
20.1129 + * this, but it's a lot of work without any obvious need.
20.1130 + */
20.1131 + razor_set_error(error, RAZOR_GENERAL_ERROR,
20.1132 + RAZOR_GENERAL_ERROR_FAILED, scheme,
20.1133 + "Can't override file scheme handler");
20.1134 + return -1;
20.1135 + }
20.1136 +
20.1137 + if (vtable->structure_size < sizeof(struct razor_uri_vtable)) {
20.1138 + /*
20.1139 + * A future version of the API might add vfuncs to the
20.1140 + * table (which we ignore), but won't remove any.
20.1141 + */
20.1142 + razor_set_error(error, RAZOR_GENERAL_ERROR,
20.1143 + RAZOR_GENERAL_ERROR_FAILED, scheme,
20.1144 + "Invalid vtable structure size");
20.1145 + return -1;
20.1146 + }
20.1147 +
20.1148 + eend = razor_uri_vtable_entries.data + razor_uri_vtable_entries.size;
20.1149 + for (entry = razor_uri_vtable_entries.data; entry < eend; entry++) {
20.1150 + if (!strcmp0(entry->scheme, scheme))
20.1151 + break;
20.1152 + }
20.1153 +
20.1154 + if (entry == eend) {
20.1155 + if (!vtable)
20.1156 + return 0;
20.1157 + entry = array_add(&razor_uri_vtable_entries, sizeof *entry);
20.1158 + entry->scheme = scheme ? strdup(scheme) : NULL;
20.1159 + array_init(&entry->open_files);
20.1160 + array_init(&entry->open_directories);
20.1161 + } else if (entry->open_files.size || entry->open_directories.size) {
20.1162 + razor_set_error(error, RAZOR_GENERAL_ERROR,
20.1163 + RAZOR_GENERAL_ERROR_FAILED, scheme,
20.1164 + "URI handler busy");
20.1165 + return -1;
20.1166 + }
20.1167 +
20.1168 + if (vtable) {
20.1169 + entry->vtable = *vtable;
20.1170 + entry->vtable.structure_size = sizeof(struct razor_uri_vtable);
20.1171 + } else {
20.1172 + free(entry->scheme);
20.1173 + if (entry + 1 < eend)
20.1174 + memmove(entry, entry + 1, eend - (entry + 1));
20.1175 + array_set_size(&razor_uri_vtable_entries,
20.1176 + razor_uri_vtable_entries.size - sizeof *entry);
20.1177 + }
20.1178 +
20.1179 + return 0;
20.1180 +}
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
21.2 +++ b/librazor/uri.c Mon Jul 04 10:48:18 2016 +0100
21.3 @@ -0,0 +1,957 @@
21.4 +/*
21.5 + * Copyright (C) 2016 J. Ali Harlow <ali@juiblex.co.uk>
21.6 + *
21.7 + * This program is free software; you can redistribute it and/or modify
21.8 + * it under the terms of the GNU General Public License as published by
21.9 + * the Free Software Foundation; either version 2 of the License, or
21.10 + * (at your option) any later version.
21.11 + *
21.12 + * This program is distributed in the hope that it will be useful,
21.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
21.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21.15 + * GNU General Public License for more details.
21.16 + *
21.17 + * You should have received a copy of the GNU General Public License along
21.18 + * with this program; if not, write to the Free Software Foundation, Inc.,
21.19 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21.20 + */
21.21 +
21.22 +#include "config.h"
21.23 +
21.24 +#undef DEBUG
21.25 +
21.26 +#include <stdlib.h>
21.27 +#include <string.h>
21.28 +#include "razor.h"
21.29 +#include "types/types.h"
21.30 +#include "razor-internal.h"
21.31 +#include "uri.h"
21.32 +
21.33 +/*
21.34 + * Following RFC 3986 § 3.
21.35 + * Note that we don't validate queries or fragments.
21.36 + */
21.37 +
21.38 +#define strdup0(s) ((s) ? strdup(s) : NULL)
21.39 +
21.40 +#define string_str(str) ((char *)(str)->data)
21.41 +
21.42 +#define string_init(str) do { \
21.43 + char *_p; \
21.44 + array_init(str); \
21.45 + _p = array_add(str, 1); \
21.46 + *_p = '\0'; \
21.47 + } while(0)
21.48 +
21.49 +#define string_append_len(str, s, len) do { \
21.50 + char *_p; \
21.51 + _p = array_add(str, len); \
21.52 + _p--; \
21.53 + strncpy(_p, s, len); \
21.54 + _p[(len)] = '\0'; \
21.55 + } while(0)
21.56 +
21.57 +#define string_append(str, s) string_append_len(str, s, strlen(s))
21.58 +
21.59 +#define string_truncate_at(str, s) do { \
21.60 + int _len; \
21.61 + _len = (s) - \
21.62 + (char *)(str)->data; \
21.63 + *(s) = '\0'; \
21.64 + (str)->size = _len + 1; \
21.65 + } while(0)
21.66 +
21.67 +
21.68 +static const char *skip_uri_scheme(const char *uri)
21.69 +{
21.70 + /*
21.71 + * RFC 3986 defines scheme as:
21.72 + * scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
21.73 + */
21.74 + if (*uri >= 'a' && *uri <= 'z' || *uri >= 'A' && *uri <= 'Z') {
21.75 + do {
21.76 + uri++;
21.77 + } while (is_alnum(*uri) || *uri == '+' || *uri == '-' ||
21.78 + *uri == '.');
21.79 + if (*uri == ':')
21.80 + return uri;
21.81 + }
21.82 + return NULL;
21.83 +}
21.84 +
21.85 +static char *razor_strndup(const char *s, size_t n)
21.86 +{
21.87 + char *result;
21.88 +
21.89 + if (memchr(s, '\0', n))
21.90 + result = strdup(s);
21.91 + else {
21.92 + result = malloc(n + 1);
21.93 + memcpy(result, s, n);
21.94 + result[n] = '\0';
21.95 + }
21.96 +
21.97 + return result;
21.98 +}
21.99 +
21.100 +#if 0
21.101 +/*
21.102 + * Return the (possibly decoded) pchar or 0 on end-of-string or -1 on error
21.103 + */
21.104 +static int pchar_get_char_validated(const char *p)
21.105 +{
21.106 + int c;
21.107 +
21.108 + if (p[0]=='\0')
21.109 + c = 0;
21.110 + else if (p[0]=='%') {
21.111 + if (xdigit_value(p[1]) < 0)
21.112 + return -1;
21.113 + c = xdigit_value(p[1]) * 16;
21.114 + if (xdigit_value(p[2]) < 0)
21.115 + return -1;
21.116 + c += xdigit_value(p[2]);
21.117 + } else if (p[0] >= 'a' && p[0] <= 'z' || p[0] >= 'A' && p[0] <= 'Z' ||
21.118 + p[0] >= '0' && p[0] <= '9' ||
21.119 + strchr("-._~!$&'()*+,;=:@", p[0]))
21.120 + c = p[0];
21.121 + else
21.122 + c = -1;
21.123 +
21.124 + return c;
21.125 +}
21.126 +#endif
21.127 +
21.128 +/*
21.129 + * Verify the percent encoding. All '%' characters must be followed by
21.130 + * exactly two hexadecimal digits.
21.131 + */
21.132 +static int pct_encoding_validate(const char *s)
21.133 +{
21.134 + while (*s) {
21.135 + if (*s == '%') {
21.136 + if (xdigit_value(s[1]) < 0 || xdigit_value(s[2]) < 0)
21.137 + return -1;
21.138 + s += 2;
21.139 + }
21.140 +
21.141 + s++;
21.142 + }
21.143 +
21.144 + return 0;
21.145 +}
21.146 +
21.147 +static char *pct_encoding_normalize(char *s)
21.148 +{
21.149 + char *retval, *p;
21.150 + int c;
21.151 +
21.152 + if (!s)
21.153 + return NULL;
21.154 +
21.155 + p = retval = malloc(strlen(s) + 1);
21.156 +
21.157 + while (*s) {
21.158 + if (*s == '%') {
21.159 + c = pchar_get_char(s);
21.160 + if (is_unreserved(c))
21.161 + *p++ = c;
21.162 + else {
21.163 + *p++ = '%';
21.164 + *p++ = "0123456789ABCDEF"[c/16];
21.165 + *p++ = "0123456789ABCDEF"[c%16];
21.166 + }
21.167 + pchar_next_char(s);
21.168 + } else
21.169 + *p++ = *s++;
21.170 + }
21.171 +
21.172 + *p++ = '\0';
21.173 +
21.174 + return realloc(retval, p - retval);
21.175 +}
21.176 +
21.177 +static int validate_userinfo(const char *userinfo, struct razor_error **error)
21.178 +{
21.179 + const char *s;
21.180 +
21.181 + for (s = userinfo; *s; s++) {
21.182 + if (!is_unreserved(*s) && *s != '%' && !is_sub_delim(*s)
21.183 + && *s != ':') {
21.184 + razor_set_error(error, RAZOR_GENERAL_ERROR,
21.185 + RAZOR_GENERAL_ERROR_BAD_URI, userinfo,
21.186 + "Invalid URI userinfo");
21.187 + return -1;
21.188 + }
21.189 + }
21.190 +
21.191 + return 0;
21.192 +}
21.193 +
21.194 +static int validate_reg_name(const char *reg_name)
21.195 +{
21.196 + const char *s;
21.197 +
21.198 + for (s = reg_name; *s; s++) {
21.199 + if (!is_unreserved(*s) && *s != '%' && !is_sub_delim(*s))
21.200 + return -1;
21.201 + }
21.202 +
21.203 + return 0;
21.204 +}
21.205 +
21.206 +static int validate_ipv4address(const char *s, int length)
21.207 +{
21.208 + int count = 0, digits, octet;
21.209 +
21.210 + for (;;) {
21.211 + if (!length)
21.212 + return -1;
21.213 +
21.214 + if (*s == '0') {
21.215 + digits = 1;
21.216 + octet = 0;
21.217 + } else {
21.218 + if (*s < '1' || *s > '9')
21.219 + return -1;
21.220 +
21.221 + octet = *s - '0';
21.222 +
21.223 + for (digits = 1; digits < length; digits++) {
21.224 + if (s[digits] >= '0' && s[digits] <= '9') {
21.225 + octet *= 10;
21.226 + octet += s[digits] - '0';
21.227 + if (octet > 255)
21.228 + return -1;
21.229 + } else
21.230 + break;
21.231 + }
21.232 + }
21.233 +
21.234 + s += digits;
21.235 + length -= digits;
21.236 +
21.237 + if (++count == 4)
21.238 + break;
21.239 +
21.240 + if (length < 1 || *s != '.')
21.241 + return -1;
21.242 +
21.243 + s++;
21.244 + length--;
21.245 + }
21.246 +
21.247 + return length ? -1 : 0;
21.248 +}
21.249 +
21.250 +static int count_ipv6_pieces(const char **s, int *length)
21.251 +{
21.252 + int count, digits;
21.253 +
21.254 + for (digits = 0; digits < 4 && digits < *length; digits++) {
21.255 + if (!is_xdigit((*s)[digits]))
21.256 + break;
21.257 + }
21.258 +
21.259 + if (!digits)
21.260 + return 0;
21.261 +
21.262 + (*s) += digits;
21.263 + (*length) -= digits;
21.264 + count = 1;
21.265 +
21.266 + if (*length && **s == ':') {
21.267 + (*s)++;
21.268 + (*length)--;
21.269 + count += count_ipv6_pieces(s, length);
21.270 + if (count == 1) {
21.271 + (*s)--;
21.272 + (*length)++;
21.273 + }
21.274 + }
21.275 +
21.276 + return count;
21.277 +}
21.278 +
21.279 +static int validate_ip_literal(const char *ip_literal, int length)
21.280 +{
21.281 + const char *s, *dot;
21.282 + int len, no_pieces, elide;
21.283 +
21.284 + if (length >= 4 && ip_literal[0] == 'v') {
21.285 + /* IPvFuture */
21.286 + dot = strchr(ip_literal + 2, '.');
21.287 + if (!dot || dot >= ip_literal + length)
21.288 + return -1;
21.289 + for (s = ip_literal + 1; s < dot; s++) {
21.290 + if (!is_xdigit(*s))
21.291 + return -1;
21.292 + }
21.293 + for (s = dot + 1; s < ip_literal + length; s++) {
21.294 + if (!is_unreserved(*s) && !is_sub_delim(*s) && *s != ':')
21.295 + return -1;
21.296 + }
21.297 + } else {
21.298 + /* IPv6address */
21.299 + s = ip_literal;
21.300 + len = length;
21.301 + no_pieces = count_ipv6_pieces(&s, &len);
21.302 +
21.303 + if (len > 1 && s[0] == ':' && s[1] == ':') {
21.304 + s += 2;
21.305 + len -= 2;
21.306 + elide = 1;
21.307 + no_pieces += count_ipv6_pieces(&s, &len);
21.308 + } else
21.309 + elide = 0;
21.310 +
21.311 + if (!validate_ipv4address(s, len))
21.312 + no_pieces += 2;
21.313 + else if (len)
21.314 + return -1;
21.315 +
21.316 + if (no_pieces > 8 || no_pieces == 8 && elide || no_pieces < 1)
21.317 + return -1;
21.318 + }
21.319 +
21.320 + return 0;
21.321 +}
21.322 +
21.323 +static int validate_host(const char *host, struct razor_error **error)
21.324 +{
21.325 + int retval;
21.326 +
21.327 + if (host[0] == '[' && host[strlen(host) - 1] == ']')
21.328 + retval = validate_ip_literal(host + 1, strlen(host) - 2);
21.329 + else {
21.330 + retval = validate_ipv4address(host, strlen(host));
21.331 + if (retval < 0)
21.332 + retval = validate_reg_name(host);
21.333 + }
21.334 +
21.335 + if (retval)
21.336 + razor_set_error(error, RAZOR_GENERAL_ERROR,
21.337 + RAZOR_GENERAL_ERROR_BAD_URI, host,
21.338 + "Invalid URI host");
21.339 +
21.340 + return retval;
21.341 +}
21.342 +
21.343 +static char *strdown(char *s)
21.344 +{
21.345 + while (*s) {
21.346 + if (*s >= 'A' && *s <= 'Z') {
21.347 + *s -= 'A';
21.348 + *s += 'a';
21.349 + }
21.350 + s++;
21.351 + }
21.352 +
21.353 + return s;
21.354 +}
21.355 +
21.356 +static int razor_uri_parse_authority(struct razor_uri *ru,
21.357 + const char *authority, int length,
21.358 + struct razor_error **error)
21.359 +{
21.360 + const char *s, *auth = authority;
21.361 + char *userinfo, *port, *host;
21.362 +
21.363 + s = strchr(auth, '@');
21.364 + if (s && s < auth + length) {
21.365 + userinfo = razor_strndup(auth, s - auth);
21.366 + s++;
21.367 + length -= s - auth;
21.368 + auth = s;
21.369 +
21.370 + if (validate_userinfo(userinfo, error)) {
21.371 + free(userinfo);
21.372 + return -1;
21.373 + }
21.374 + } else
21.375 + userinfo = NULL;
21.376 +
21.377 + s = strchr(auth, ':');
21.378 + if (s && s < auth + length) {
21.379 + s++;
21.380 + port = razor_strndup(s, length - (s - auth));
21.381 + s--;
21.382 + length = s - auth;
21.383 +
21.384 + if (strspn(port, "0123456789") != strlen(port)) {
21.385 + razor_set_error(error, RAZOR_GENERAL_ERROR,
21.386 + RAZOR_GENERAL_ERROR_BAD_URI, port,
21.387 + "Invalid URI port");
21.388 + free(userinfo);
21.389 + free(port);
21.390 + return -1;
21.391 + }
21.392 + } else
21.393 + port = NULL;
21.394 +
21.395 + host = razor_strndup(auth, length);
21.396 +
21.397 + if (validate_host(host, error)) {
21.398 + free(userinfo);
21.399 + free(port);
21.400 + free(host);
21.401 + return -1;
21.402 + }
21.403 +
21.404 + ru->userinfo = userinfo;
21.405 + ru->port = port;
21.406 + ru->host = host;
21.407 +
21.408 + return 0;
21.409 +}
21.410 +
21.411 +/*
21.412 + * Parse either a hier-part or a relative-part
21.413 + */
21.414 +static int razor_uri_parse_part(struct razor_uri *ru, const char *part,
21.415 + int relative_part, struct razor_error **error)
21.416 +{
21.417 + const char *s, *hp = part;
21.418 + char *path, *p;
21.419 + int noscheme = 0;
21.420 +
21.421 + if (hp[0] == '/' && hp[1] == '/') {
21.422 + hp += 2;
21.423 + s = strpbrk(hp, "/?#");
21.424 + if (!s)
21.425 + s = hp + strlen(hp);
21.426 + if (razor_uri_parse_authority(ru, hp, s - hp, error) < 0)
21.427 + return -1;
21.428 + hp = s;
21.429 + } else {
21.430 + ru->userinfo = NULL;
21.431 + ru->host = NULL;
21.432 + ru->port = NULL;
21.433 + }
21.434 +
21.435 + if (!*hp) {
21.436 + /* path-empty */
21.437 + ru->path = strdup("");
21.438 + return 0;
21.439 + } else if (*hp == '/') {
21.440 + /* path-absolute */
21.441 + p = path = malloc(strlen(hp) + 1);
21.442 + *p++ = '/';
21.443 + hp++;
21.444 + if (!*hp) {
21.445 + *p++ = '\0';
21.446 + ru->path = realloc(path, p - path);
21.447 + return 0;
21.448 + }
21.449 + } else if (!ru->host) {
21.450 + /* path-rootless or path-noscheme */
21.451 + noscheme = relative_part;
21.452 + p = path = malloc(strlen(hp) + 1);
21.453 + } else {
21.454 + razor_set_error(error, RAZOR_GENERAL_ERROR,
21.455 + RAZOR_GENERAL_ERROR_BAD_URI, part,
21.456 + relative_part ? "Invalid URI relative part" :
21.457 + "Invalid URI hierarchical part");
21.458 + return -1;
21.459 + }
21.460 +
21.461 + if (!is_pchar(*hp) || noscheme && *hp == ':') {
21.462 + free(path);
21.463 + razor_set_error(error, RAZOR_GENERAL_ERROR,
21.464 + RAZOR_GENERAL_ERROR_BAD_URI, part,
21.465 + "Invalid character in URI path");
21.466 + return -1;
21.467 + }
21.468 + *p++ = *hp++;
21.469 +
21.470 + while (*hp) {
21.471 + if (*hp == '/')
21.472 + noscheme = 0;
21.473 + else if (!is_pchar(*hp) || noscheme && *hp == ':') {
21.474 + free(path);
21.475 + razor_set_error(error, RAZOR_GENERAL_ERROR,
21.476 + RAZOR_GENERAL_ERROR_BAD_URI, part,
21.477 + "Invalid character in URI path");
21.478 + return -1;
21.479 + }
21.480 + *p++ = *hp++;
21.481 + }
21.482 +
21.483 + *p++ = '\0';
21.484 +
21.485 + ru->path = realloc(path, p - path);
21.486 +
21.487 + return 0;
21.488 +}
21.489 +
21.490 +void razor_uri_destroy(struct razor_uri *ru)
21.491 +{
21.492 + free(ru->scheme);
21.493 + free(ru->userinfo);
21.494 + free(ru->host);
21.495 + free(ru->port);
21.496 + free(ru->path);
21.497 + free(ru->query);
21.498 + free(ru->fragment);
21.499 +}
21.500 +
21.501 +int razor_uri_parse_uri(struct razor_uri *ru, const char *uri, int absolute,
21.502 + struct razor_error **error)
21.503 +{
21.504 + int r;
21.505 + const char *s;
21.506 + char *hier_part;
21.507 +
21.508 + if (pct_encoding_validate(uri) < 0) {
21.509 + razor_set_error(error, RAZOR_GENERAL_ERROR,
21.510 + RAZOR_GENERAL_ERROR_BAD_URI, uri,
21.511 + "Invalid percent encoding");
21.512 + return -1;
21.513 + }
21.514 +
21.515 + memset(ru, 0, sizeof(*ru));
21.516 +
21.517 + s = skip_uri_scheme(uri);
21.518 + if (!s) {
21.519 + razor_set_error(error, RAZOR_GENERAL_ERROR,
21.520 + RAZOR_GENERAL_ERROR_BAD_URI, uri,
21.521 + "Invalid URI scheme");
21.522 + return -1;
21.523 + }
21.524 + ru->scheme = razor_strndup(uri, s - uri);
21.525 + uri = s + 1;
21.526 +
21.527 + s = strchr(uri, '?');
21.528 + if (!s)
21.529 + s = strchr(uri, '#');
21.530 + if (!s)
21.531 + s = uri + strlen(uri);
21.532 + hier_part = razor_strndup(uri, s - uri);
21.533 + uri = s;
21.534 +
21.535 + r = razor_uri_parse_part(ru, hier_part, 0, error);
21.536 + free(hier_part);
21.537 + if (r) {
21.538 + razor_uri_destroy(ru);
21.539 + return -1;
21.540 + }
21.541 +
21.542 + if (*uri != '?')
21.543 + ru->query = NULL;
21.544 + else {
21.545 + uri++;
21.546 + s = strchr(uri, '#');
21.547 + if (!s)
21.548 + s = uri + strlen(uri);
21.549 + ru->query = razor_strndup(uri, s - uri);
21.550 + uri = s;
21.551 + }
21.552 +
21.553 + if (*uri != '#')
21.554 + ru->fragment = NULL;
21.555 + else if (absolute) {
21.556 + razor_set_error(error, RAZOR_GENERAL_ERROR,
21.557 + RAZOR_GENERAL_ERROR_BAD_URI, uri,
21.558 + "Fragments are not allowed in absolute URIs");
21.559 + razor_uri_destroy(ru);
21.560 + return -1;
21.561 + } else {
21.562 + uri++;
21.563 + ru->fragment = strdup(uri);
21.564 + }
21.565 +
21.566 + return 0;
21.567 +}
21.568 +
21.569 +int razor_uri_parse_relative_ref(struct razor_uri *ru, const char *uri,
21.570 + struct razor_error **error)
21.571 +{
21.572 + int r;
21.573 + const char *s;
21.574 + char *relative_part;
21.575 +
21.576 + if (pct_encoding_validate(uri) < 0) {
21.577 + razor_set_error(error, RAZOR_GENERAL_ERROR,
21.578 + RAZOR_GENERAL_ERROR_BAD_URI, uri,
21.579 + "Invalid percent encoding");
21.580 + return -1;
21.581 + }
21.582 +
21.583 + memset(ru, 0, sizeof(*ru));
21.584 +
21.585 + s = strchr(uri, '?');
21.586 + if (!s)
21.587 + s = strchr(uri, '#');
21.588 + if (!s)
21.589 + s = uri + strlen(uri);
21.590 + relative_part = razor_strndup(uri, s - uri);
21.591 + uri = s;
21.592 +
21.593 + r = razor_uri_parse_part(ru, relative_part, 1, error);
21.594 + free(relative_part);
21.595 + if (r)
21.596 + return -1;
21.597 +
21.598 + if (*uri == '?') {
21.599 + uri++;
21.600 + s = strchr(uri, '#');
21.601 + if (!s)
21.602 + s = uri + strlen(uri);
21.603 + ru->query = razor_strndup(uri, s - uri);
21.604 + uri = s;
21.605 + } else
21.606 + ru->query = NULL;
21.607 +
21.608 + if (*uri == '#') {
21.609 + uri++;
21.610 + ru->fragment = strdup(uri);
21.611 + } else
21.612 + ru->fragment = NULL;
21.613 +
21.614 + return 0;
21.615 +}
21.616 +
21.617 +int razor_uri_parse(struct razor_uri *ru, const char *uri,
21.618 + struct razor_error **error)
21.619 +{
21.620 + struct razor_error *tmp_error = NULL;
21.621 + int r;
21.622 +
21.623 + r = razor_uri_parse_uri(ru, uri, 0, &tmp_error);
21.624 + if (r < 0) {
21.625 + r = razor_uri_parse_relative_ref(ru, uri, NULL);
21.626 + if (r < 0)
21.627 + razor_propagate_error(error, tmp_error, NULL);
21.628 + else
21.629 + razor_error_free(tmp_error);
21.630 + }
21.631 +
21.632 + return r;
21.633 +}
21.634 +
21.635 +/*
21.636 + * Following RFC 3986 § 5.2.4
21.637 + */
21.638 +static char *remove_dot_segments(const char *path)
21.639 +{
21.640 + struct array output;
21.641 + char *input, *in, *s, *t;
21.642 + const char *step;
21.643 +
21.644 +#ifdef DEBUG
21.645 + fprintf(stderr, "STEP OUTPUT BUFFER INPUT BUFFER\n");
21.646 +#endif
21.647 +
21.648 + input = strdup(path);
21.649 + in = input;
21.650 + string_init(&output);
21.651 +
21.652 +#ifdef DEBUG
21.653 + fprintf(stderr, " 1 : %-21s %s\n", string_str(&output), in);
21.654 +#endif
21.655 +
21.656 + while (*in) {
21.657 + if (str_has_prefix(in, "../")) {
21.658 + step = "2A";
21.659 + in += 3;
21.660 + } else if (str_has_prefix(in, "./")) {
21.661 + step = "2A";
21.662 + in += 2;
21.663 + } else if (str_has_prefix(in, "/./")) {
21.664 + step = "2B";
21.665 + in += 2;
21.666 + } else if (!strcmp(in, "/.")) {
21.667 + step = "2B";
21.668 + in++;
21.669 + *in = '/';
21.670 + } else if (str_has_prefix(in, "/../")) {
21.671 + step = "2C";
21.672 + in += 3;
21.673 + s = strrchr(string_str(&output), '/');
21.674 + if (!s)
21.675 + s = string_str(&output);
21.676 + string_truncate_at(&output, s);
21.677 + } else if (!strcmp(in, "/..")) {
21.678 + step = "2C";
21.679 + in += 2;
21.680 + *in = '/';
21.681 + s = strrchr(string_str(&output), '/');
21.682 + if (!s)
21.683 + s = string_str(&output);
21.684 + string_truncate_at(&output, s);
21.685 + } else if (!strcmp(in, ".") || !strcmp(in, "..")) {
21.686 + step = "2D";
21.687 + in += strlen(in);
21.688 + } else {
21.689 + step = "2E";
21.690 + t = strchr(in + 1, '/');
21.691 + if (!t)
21.692 + t = in + strlen(in);
21.693 + string_append_len(&output, in, t - in);
21.694 + in = t;
21.695 + }
21.696 +#ifdef DEBUG
21.697 + fprintf(stderr, " %s: %-21s %s\n", step, string_str(&output),
21.698 + in);
21.699 +#endif
21.700 + }
21.701 +
21.702 + free(input);
21.703 + return string_str(&output);
21.704 +}
21.705 +
21.706 +
21.707 +/*
21.708 + * Following RFC 3986 § 6.2.2
21.709 + */
21.710 +void razor_uri_normalize(struct razor_uri *ru)
21.711 +{
21.712 + char *s;
21.713 +
21.714 + strdown(ru->scheme);
21.715 + if (ru->host)
21.716 + strdown(ru->host);
21.717 +
21.718 + s = pct_encoding_normalize(ru->userinfo);
21.719 + free(ru->userinfo);
21.720 + ru->userinfo = s;
21.721 +
21.722 + s = pct_encoding_normalize(ru->host);
21.723 + free(ru->host);
21.724 + ru->host = s;
21.725 +
21.726 + s = pct_encoding_normalize(ru->path);
21.727 + free(ru->path);
21.728 + ru->path = s;
21.729 +
21.730 + s = pct_encoding_normalize(ru->query);
21.731 + free(ru->query);
21.732 + ru->query = s;
21.733 +
21.734 + s = pct_encoding_normalize(ru->fragment);
21.735 + free(ru->fragment);
21.736 + ru->fragment = s;
21.737 +
21.738 + s = remove_dot_segments(ru->path);
21.739 + free(ru->path);
21.740 + ru->path = s;
21.741 +}
21.742 +
21.743 +char *razor_uri_get_authority(const struct razor_uri *ru)
21.744 +{
21.745 + char *result, *r;
21.746 + int len = 1;
21.747 +
21.748 + if (ru->host) {
21.749 + if (ru->userinfo)
21.750 + len += strlen(ru->userinfo) + 1;
21.751 + len += strlen(ru->host);
21.752 + if (ru->port)
21.753 + len += strlen(ru->port) + 1;
21.754 + } else
21.755 + return NULL;
21.756 +
21.757 + r = result = malloc(len);
21.758 +
21.759 + if (ru->userinfo) {
21.760 + strcpy(r, ru->userinfo);
21.761 + r += strlen(r);
21.762 + *r++ = '@';
21.763 + }
21.764 +
21.765 + strcpy(r, ru->host);
21.766 + r += strlen(r);
21.767 +
21.768 + if (ru->port) {
21.769 + *r++ = ':';
21.770 + strcpy(r, ru->port);
21.771 + }
21.772 +
21.773 + return result;
21.774 +}
21.775 +
21.776 +/*
21.777 + * Following RFC 3986 § 5.3
21.778 + */
21.779 +char *razor_uri_recompose(const struct razor_uri *ru)
21.780 +{
21.781 + char *authority, *result, *r;
21.782 + int len = 1;
21.783 +
21.784 + authority = razor_uri_get_authority(ru);
21.785 +
21.786 + if (ru->scheme)
21.787 + len += strlen(ru->scheme) + 1;
21.788 + if (authority)
21.789 + len += strlen(authority) + 2;
21.790 + len += strlen(ru->path);
21.791 + if (ru->query)
21.792 + len += strlen(ru->query) + 1;
21.793 + if (ru->fragment)
21.794 + len += strlen(ru->fragment) + 1;
21.795 +
21.796 + r = result = malloc(len);
21.797 +
21.798 + if (ru->scheme) {
21.799 + strcpy(r, ru->scheme);
21.800 + r += strlen(r);
21.801 + *r++ = ':';
21.802 + }
21.803 +
21.804 + if (authority) {
21.805 + *r++ = '/';
21.806 + *r++ = '/';
21.807 + strcpy(r, authority);
21.808 + free(authority);
21.809 + r += strlen(r);
21.810 + }
21.811 +
21.812 + strcpy(r, ru->path);
21.813 + r += strlen(r);
21.814 +
21.815 + if (ru->query) {
21.816 + *r++ = '?';
21.817 + strcpy(r, ru->query);
21.818 + r += strlen(r);
21.819 + }
21.820 +
21.821 + if (ru->fragment) {
21.822 + *r++ = '#';
21.823 + strcpy(r, ru->fragment);
21.824 + }
21.825 +
21.826 + return result;
21.827 +}
21.828 +
21.829 +/*
21.830 + * Following RFC 3986 § 5.2.3
21.831 + */
21.832 +static char *merge_paths(const struct razor_uri *base,const struct razor_uri *R)
21.833 +{
21.834 + char *s, *t, *path;
21.835 +
21.836 + if (base->host && !*base->path)
21.837 + path = razor_concat("/", R->path, NULL);
21.838 + else {
21.839 + s = strrchr(base->path, '/');
21.840 + if (s) {
21.841 + t = razor_strndup(base->path, s + 1 - base->path);
21.842 + path = razor_concat(t, R->path, NULL);
21.843 + free(t);
21.844 + } else
21.845 + path = strdup(R->path);
21.846 + }
21.847 +
21.848 + return path;
21.849 +}
21.850 +
21.851 +/*
21.852 + * Following RFC 3986 § 5.2
21.853 + */
21.854 +void razor_uri_resolve(struct razor_uri *T, const struct razor_uri *base,
21.855 + const struct razor_uri *R)
21.856 +{
21.857 + char *s;
21.858 +
21.859 + if (R->scheme) {
21.860 + T->scheme = strdup(R->scheme);
21.861 + T->userinfo = strdup0(R->userinfo);
21.862 + T->host = strdup0(R->host);
21.863 + T->port = strdup0(R->port);
21.864 + T->path = remove_dot_segments(R->path);
21.865 + T->query = strdup0(R->query);
21.866 + } else {
21.867 + if (R->host) {
21.868 + T->userinfo = strdup0(R->userinfo);
21.869 + T->host = strdup0(R->host);
21.870 + T->port = strdup0(R->port);
21.871 + T->path = remove_dot_segments(R->path);
21.872 + T->query = strdup0(R->query);
21.873 + } else {
21.874 + if (!*R->path) {
21.875 + T->path = strdup(base->path);
21.876 + if (R->query)
21.877 + T->query = strdup(R->query);
21.878 + else
21.879 + T->query = strdup0(base->query);
21.880 + } else {
21.881 + if (*R->path == '/')
21.882 + T->path = remove_dot_segments(R->path);
21.883 + else {
21.884 + s = merge_paths(base, R);
21.885 + T->path = remove_dot_segments(s);
21.886 + free(s);
21.887 + }
21.888 + T->query = strdup0(R->query);
21.889 + }
21.890 + T->userinfo = strdup0(base->userinfo);
21.891 + T->host = strdup0(base->host);
21.892 + T->port = strdup0(base->port);
21.893 + }
21.894 + T->scheme = strdup(base->scheme);
21.895 + }
21.896 + T->fragment = strdup0(R->fragment);
21.897 +}
21.898 +
21.899 +/*
21.900 + * This differs from razor_uri_resolve() both in the types of its arguments
21.901 + * and in the fact that it takes a root URI rather than a base URI. The base
21.902 + * URI is determined by appending a slash to the root URI (if it doesn't
21.903 + * already end in a slash). Finally, uri can be explicitly marked as either
21.904 + * relative (ie., a relative-ref) or not (ie., a URI). This is important as
21.905 + * otherwise "c:/xxx" could be interpreted as a URI in the "c" scheme.
21.906 + */
21.907 +char *razor_resolve_uri_root(const char *root_uri, const char *uri,
21.908 + int is_relative, struct razor_error **error)
21.909 +{
21.910 + int r;
21.911 + char *base_uri, *s, *result;
21.912 + struct razor_uri ru, base, file;
21.913 +
21.914 + if (!root_uri || !*root_uri)
21.915 + root_uri = "file:/";
21.916 +
21.917 + if (root_uri[strlen(root_uri) - 1] == '/')
21.918 + base_uri = strdup(root_uri);
21.919 + else
21.920 + base_uri = razor_concat(root_uri, "/", NULL);
21.921 +
21.922 + r = razor_uri_parse_uri(&base, base_uri, 1, error);
21.923 + free(base_uri);
21.924 + if (r)
21.925 + return NULL;
21.926 +
21.927 + if (is_relative > 0) {
21.928 + /*
21.929 + * We can't use razor_uri_parse_relative_ref() to parse
21.930 + * uri in case it starts with a segment that includes a
21.931 + * colon. Thus we use this kludge.
21.932 + */
21.933 + s = razor_concat("scheme:", uri, NULL);
21.934 + r = razor_uri_parse_uri(&file, s, 0, error);
21.935 + free(s);
21.936 + if (!r) {
21.937 + free(file.scheme);
21.938 + file.scheme = NULL;
21.939 + }
21.940 + }
21.941 + else if (!is_relative)
21.942 + r = razor_uri_parse_uri(&file, uri, 0, error);
21.943 + else
21.944 + r = razor_uri_parse(&file, uri, error);
21.945 + if (r) {
21.946 + razor_uri_destroy(&base);
21.947 + return NULL;
21.948 + }
21.949 +
21.950 + razor_uri_resolve(&ru, &base, &file);
21.951 +
21.952 + razor_uri_destroy(&base);
21.953 + razor_uri_destroy(&file);
21.954 +
21.955 + result = razor_uri_recompose(&ru);
21.956 +
21.957 + razor_uri_destroy(&ru);
21.958 +
21.959 + return result;
21.960 +}
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
22.2 +++ b/librazor/uri.h Mon Jul 04 10:48:18 2016 +0100
22.3 @@ -0,0 +1,50 @@
22.4 +/*
22.5 + * Copyright (C) 2016 J. Ali Harlow <ali@juiblex.co.uk>
22.6 + *
22.7 + * This program is free software; you can redistribute it and/or modify
22.8 + * it under the terms of the GNU General Public License as published by
22.9 + * the Free Software Foundation; either version 2 of the License, or
22.10 + * (at your option) any later version.
22.11 + *
22.12 + * This program is distributed in the hope that it will be useful,
22.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
22.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22.15 + * GNU General Public License for more details.
22.16 + *
22.17 + * You should have received a copy of the GNU General Public License along
22.18 + * with this program; if not, write to the Free Software Foundation, Inc.,
22.19 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22.20 + */
22.21 +
22.22 +#define is_alpha(c) ((c) >= 'a' && (c) <= 'z' || (c) >= 'A' && (c) <= 'Z')
22.23 +
22.24 +#define is_alnum(c) (is_alpha(c) || (c) >= '0' && (c) <= '9')
22.25 +
22.26 +#define is_xdigit(c) ((c) >= '0' && (c) <= '9' || \
22.27 + (c) >= 'a' && (c) <= 'f' || \
22.28 + (c) >= 'A' && (c) <= 'F')
22.29 +
22.30 +#define is_unreserved(c) (is_alnum(c) || (c) == '-' || (c) == '.' || \
22.31 + (c) == '_' || (c) == '~')
22.32 +
22.33 +#define is_sub_delim(c) strchr("!$&'()*+,;=", c)
22.34 +
22.35 +#define is_pchar(c) (is_unreserved(c) || (c) == '%' || \
22.36 + is_sub_delim(c) || (c) == ':' || (c) == '@')
22.37 +
22.38 +#define xdigit_value(c) ((c) >= '0' && (c) <= '9' ? (c) - '0' : \
22.39 + (c) >= 'a' && (c) <= 'f' ? (c) - 'a' + 10 : \
22.40 + (c) >= 'A' && (c) <= 'F' ? (c) - 'A' + 10 : -1)
22.41 +
22.42 +#define pchar_get_char(p) ((p)[0] == '%' ? \
22.43 + xdigit_value((p)[1]) * 16 + xdigit_value((p)[2]) : \
22.44 + (p)[0])
22.45 +
22.46 +#define pchar_next_char(p) \
22.47 + do { \
22.48 + if ((p)[0] == '%') \
22.49 + (p) += 3; \
22.50 + else \
22.51 + (p)++; \
22.52 + } while(0)
22.53 +
23.1 --- a/librazor/util.c Sat Jun 11 17:56:48 2016 +0100
23.2 +++ b/librazor/util.c Mon Jul 04 10:48:18 2016 +0100
23.3 @@ -1,7 +1,7 @@
23.4 /*
23.5 * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
23.6 * Copyright (C) 2008 Red Hat, Inc
23.7 - * Copyright (C) 2009, 2011, 2012, 2014 J. Ali Harlow <ali@juiblex.co.uk>
23.8 + * Copyright (C) 2009, 2011, 2012, 2014, 2016 J. Ali Harlow <ali@juiblex.co.uk>
23.9 *
23.10 * This program is free software; you can redistribute it and/or modify
23.11 * it under the terms of the GNU General Public License as published by
23.12 @@ -22,32 +22,20 @@
23.13
23.14 #include <limits.h>
23.15 #include <string.h>
23.16 -#include <sys/types.h>
23.17 -#include <sys/stat.h>
23.18 #include <stdlib.h>
23.19 #include <stdio.h>
23.20 #include <stdint.h>
23.21 #include <errno.h>
23.22 #include <unistd.h>
23.23 -#include <fcntl.h>
23.24 -#ifdef MSWIN_API
23.25 -#include <windows.h>
23.26 -#include <direct.h>
23.27 -#else
23.28 +#ifndef MSWIN_API
23.29 #include <sys/utsname.h>
23.30 #endif
23.31 -#if HAVE_SYS_MMAN_H
23.32 -#include <sys/mman.h>
23.33 -#endif
23.34 #include <assert.h>
23.35
23.36 #include "razor.h"
23.37 +#include "types/types.h"
23.38 #include "razor-internal.h"
23.39
23.40 -#ifndef O_BINARY
23.41 -#define O_BINARY 0
23.42 -#endif
23.43 -
23.44 /* Required by gnulib on non-libc platforms */
23.45 char *program_name = "librazor";
23.46
23.47 @@ -62,130 +50,6 @@
23.48 return p;
23.49 }
23.50
23.51 -#if HAVE_SYS_MMAN_H
23.52 -#define OPEN_FILE_USED (1U<<0)
23.53 -#define OPEN_FILE_MMAPPED (1U<<1)
23.54 -
23.55 -struct open_file {
23.56 - void *addr;
23.57 - size_t length;
23.58 - uint32_t flags;
23.59 -};
23.60 -
23.61 -struct array open_files = { 0, };
23.62 -#endif /* HAVE_SYS_MMAN_H */
23.63 -
23.64 -void *
23.65 -razor_file_get_contents(const char *filename, size_t *length, int private,
23.66 - struct razor_error **error)
23.67 -{
23.68 - int fd;
23.69 - struct stat st;
23.70 - void *addr = NULL;
23.71 - size_t nb;
23.72 - ssize_t res;
23.73 -#if HAVE_SYS_MMAN_H
23.74 - struct open_file *of, *ofend;
23.75 -#endif
23.76 -
23.77 - fd = open(filename, O_RDONLY | O_BINARY);
23.78 - if (fd < 0) {
23.79 - razor_set_error_posix(error, filename);
23.80 - return NULL;
23.81 - }
23.82 -
23.83 - if (fstat(fd, &st) < 0) {
23.84 - razor_set_error_posix(error, filename);
23.85 - close(fd);
23.86 - return NULL;
23.87 - }
23.88 -
23.89 - *length = st.st_size;
23.90 -
23.91 -#if HAVE_SYS_MMAN_H
23.92 - ofend = open_files.data + open_files.size;
23.93 - for (of = open_files.data; of < ofend; of++)
23.94 - if (!(of->flags & OPEN_FILE_USED))
23.95 - break;
23.96 - if (of == ofend) {
23.97 - of = array_add(&open_files, sizeof *of);
23.98 - of->flags = 0;
23.99 - }
23.100 -
23.101 - if (!private) {
23.102 - addr = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
23.103 - if (addr == MAP_FAILED)
23.104 - addr = NULL;
23.105 - else
23.106 - of->flags = OPEN_FILE_USED | OPEN_FILE_MMAPPED;
23.107 - }
23.108 -#endif /* HAVE_SYS_MMAN_H */
23.109 - if (!addr) {
23.110 - addr = malloc(st.st_size);
23.111 - if (addr) {
23.112 -#if HAVE_SYS_MMAN_H
23.113 - of->flags = OPEN_FILE_USED;
23.114 -#endif
23.115 - nb = 0;
23.116 - while(nb < st.st_size) {
23.117 - res = read(fd, addr + nb, st.st_size - nb);
23.118 - if (res <= 0) {
23.119 - razor_set_error_posix(error, filename);
23.120 - free(addr);
23.121 - addr = NULL;
23.122 - break;
23.123 - }
23.124 - nb += res;
23.125 - }
23.126 - } else
23.127 - razor_set_error(error, RAZOR_POSIX_ERROR, ENOMEM, NULL,
23.128 - "Not enough memory");
23.129 - }
23.130 - close(fd);
23.131 -
23.132 -#if HAVE_SYS_MMAN_H
23.133 - of->addr = addr;
23.134 - of->length = st.st_size;
23.135 -#endif
23.136 -
23.137 - return addr;
23.138 -}
23.139 -
23.140 -int razor_file_free_contents(void *addr, size_t length)
23.141 -{
23.142 -#if HAVE_SYS_MMAN_H
23.143 - int retval, mmapped;
23.144 - struct open_file *of, *ofend;
23.145 -
23.146 - ofend = open_files.data + open_files.size;
23.147 - for (of = open_files.data; of < ofend; of++)
23.148 - if ((of->flags & OPEN_FILE_USED) && of->addr == addr)
23.149 - break;
23.150 -
23.151 - if (of == ofend)
23.152 - return 1;
23.153 -
23.154 - length = of->length;
23.155 - mmapped = of->flags & OPEN_FILE_MMAPPED;
23.156 - of->flags &= ~OPEN_FILE_USED;
23.157 -
23.158 - for (of = open_files.data; of < ofend; of++)
23.159 - if (of->flags & OPEN_FILE_USED)
23.160 - break;
23.161 -
23.162 - if (of == ofend) {
23.163 - array_release(&open_files);
23.164 - array_init(&open_files);
23.165 - }
23.166 -
23.167 - if (mmapped)
23.168 - return munmap(addr, length);
23.169 -#endif
23.170 -
23.171 - free(addr);
23.172 - return 0;
23.173 -}
23.174 -
23.175 struct qsort_context {
23.176 size_t size;
23.177 razor_compare_with_data_func_t compare;
24.1 --- a/src/import-rpmdb.c Sat Jun 11 17:56:48 2016 +0100
24.2 +++ b/src/import-rpmdb.c Mon Jul 04 10:48:18 2016 +0100
24.3 @@ -24,6 +24,10 @@
24.4 #include <string.h>
24.5 #include <fcntl.h>
24.6 #include <limits.h>
24.7 +/*
24.8 + * Enable rpm 4.4 compatibility mode, see http://rpm.org/wiki/Releases/4.6.0
24.9 + */
24.10 +#define _RPM_4_4_COMPAT
24.11 #include <rpm/rpmlib.h>
24.12 #include <rpm/rpmdb.h>
24.13
25.1 --- a/src/main.c Sat Jun 11 17:56:48 2016 +0100
25.2 +++ b/src/main.c Mon Jul 04 10:48:18 2016 +0100
25.3 @@ -1,7 +1,7 @@
25.4 /*
25.5 * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
25.6 * Copyright (C) 2008 Red Hat, Inc
25.7 - * Copyright (C) 2009, 2011-2012, 2014 J. Ali Harlow <ali@juiblex.co.uk>
25.8 + * Copyright (C) 2009, 2011-2012, 2014, 2016 J. Ali Harlow <ali@juiblex.co.uk>
25.9 *
25.10 * This program is free software; you can redistribute it and/or modify
25.11 * it under the terms of the GNU General Public License as published by
25.12 @@ -49,7 +49,7 @@
25.13
25.14 static const char system_repo_filename[] = "system.rzdb";
25.15 static const char next_repo_filename[] = "system-next.rzdb";
25.16 -static const char rawhide_repo_filename[] = "rawhide.rzdb";
25.17 +static const char rawhide_repo_uri[] = "file:rawhide.rzdb";
25.18 static const char *install_root = "";
25.19 static const char *repo_filename = system_repo_filename;
25.20 static const char *yum_url;
25.21 @@ -150,7 +150,7 @@
25.22
25.23 opterr = 0;
25.24
25.25 - opt = getopt_long(argc, argv, "+", longopts, NULL);
25.26 + opt = getopt_long(argc, (char **)argv, "+", longopts, NULL);
25.27
25.28 switch (opt)
25.29 {
25.30 @@ -621,13 +621,13 @@
25.31 FILE *wfp, *rfp;
25.32 char buffer[256], *ptr, *local;
25.33 size_t nb, n;
25.34 + struct razor_error *error = NULL;
25.35
25.36 - local = razor_path_from_url(url);
25.37 + local = razor_path_from_uri(url, &error);
25.38
25.39 if (local == NULL) {
25.40 - fprintf(stderr,
25.41 - "%s: download manually (curl not available)\n",
25.42 - file);
25.43 + fprintf(stderr, "%s: %s\n", file, razor_error_get_msg(error));
25.44 + razor_error_free(error);
25.45 return -1;
25.46 } else {
25.47 rfp = fopen(local, "rb");
25.48 @@ -723,24 +723,12 @@
25.49 curl_easy_setopt(curl, CURLOPT_URL, url);
25.50 res = curl_easy_perform(curl);
25.51 fclose(fp);
25.52 + putc('\n', stderr);
25.53 if (res != CURLE_OK) {
25.54 fprintf(stderr, "curl error: %s\n", error);
25.55 unlink(file);
25.56 return -1;
25.57 }
25.58 - res = curl_easy_getinfo(curl,
25.59 - CURLINFO_RESPONSE_CODE, &response);
25.60 - if (res != CURLE_OK) {
25.61 - fprintf(stderr, "curl error: %s\n", error);
25.62 - unlink(file);
25.63 - return -1;
25.64 - }
25.65 - if (response != 200) {
25.66 - fprintf(stderr, " - failed %ld\n", response);
25.67 - unlink(file);
25.68 - return -1;
25.69 - }
25.70 - fprintf(stderr, "\n");
25.71 curl_easy_cleanup(curl);
25.72
25.73 return 0;
25.74 @@ -799,13 +787,13 @@
25.75 if (set == NULL)
25.76 return 1;
25.77 atomic = razor_atomic_open("Yum import repository");
25.78 - razor_set_write(set, atomic, rawhide_repo_filename, RAZOR_SECTION_ALL);
25.79 + razor_set_write(set, atomic, rawhide_repo_uri, RAZOR_SECTION_ALL);
25.80 retval = razor_atomic_commit(atomic);
25.81 razor_set_unref(set);
25.82 if (retval)
25.83 fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
25.84 else
25.85 - printf("wrote %s\n", rawhide_repo_filename);
25.86 + printf("wrote %s\n", rawhide_repo_uri);
25.87 razor_atomic_destroy(atomic);
25.88
25.89 return retval;
25.90 @@ -994,7 +982,7 @@
25.91
25.92 set = razor_root_open_read_only(install_root, &error);
25.93 if (set)
25.94 - updated = razor_set_open(rawhide_repo_filename, 0, &error);
25.95 + updated = razor_set_open(rawhide_repo_uri, 0, &error);
25.96 else
25.97 updated = NULL;
25.98 if (updated == NULL) {
25.99 @@ -1131,7 +1119,9 @@
25.100 RAZOR_DETAIL_LAST);
25.101
25.102 s = rpm_filename(name, version, arch);
25.103 - url = razor_concat(yum_url, "/Packages/", s, NULL);
25.104 + file = razor_concat("Packages/", s, NULL);
25.105 + url = razor_path_relative_to_uri(yum_url, file, NULL);
25.106 + free(file);
25.107 file = razor_concat("rpms/", s, NULL);
25.108 free(s);
25.109 if (download_if_missing(url, file) < 0)
25.110 @@ -1166,7 +1156,7 @@
25.111 const char *preunprog, *preun, *postunprog, *postun;
25.112 const char *install_prefix;
25.113 const char *const *prefixes;
25.114 - char *file, *s;
25.115 + char *file, *s, *uri, *filename;
25.116 uint32_t flags;
25.117
25.118 importer = razor_importer_create();
25.119 @@ -1185,14 +1175,20 @@
25.120 RAZOR_DETAIL_POSTUNPROG, &postunprog,
25.121 RAZOR_DETAIL_POSTUN, &postun,
25.122 RAZOR_DETAIL_LAST)) {
25.123 - s = rpm_filename(name, version, arch);
25.124 - file = razor_concat("rpms/", s, NULL);
25.125 + filename = rpm_filename(name, version, arch);
25.126 + s = razor_concat("Packages/", filename, NULL);
25.127 + uri = razor_path_relative_to_uri(yum_url, s, NULL);
25.128 free(s);
25.129 - rpm = razor_rpm_open(file, &error);
25.130 + file = razor_concat("rpms/", filename, NULL);
25.131 + free(filename);
25.132 + download_if_missing(uri, file);
25.133 + free(uri);
25.134 + uri = razor_path_to_uri(file);
25.135 free(file);
25.136 + rpm = razor_rpm_open(uri, &error);
25.137 + free(uri);
25.138 if (rpm == NULL) {
25.139 razor_atomic_propagate_error(atomic, error, NULL);
25.140 - razor_error_free(error);
25.141 razor_package_iterator_destroy(pkg_iter);
25.142 razor_importer_destroy(importer);
25.143 return NULL;
25.144 @@ -1249,7 +1245,7 @@
25.145 {
25.146 int retval;
25.147 const char *name, *version, *arch;
25.148 - char *file, *s;
25.149 + char *file, *s, *uri;
25.150 struct razor_rpm *rpm;
25.151 struct razor_error *error=NULL;
25.152
25.153 @@ -1265,12 +1261,13 @@
25.154 s = rpm_filename(name, version, arch);
25.155 file = razor_concat("rpms/", s, NULL);
25.156 free(s);
25.157 - rpm = razor_rpm_open(file, &error);
25.158 + uri = razor_path_to_uri(file);
25.159 free(file);
25.160 + rpm = razor_rpm_open(uri, &error);
25.161 + free(uri);
25.162 if (rpm == NULL) {
25.163 razor_atomic_propagate_error(atomic, error, NULL);
25.164 fprintf(stderr, "%s\n", razor_error_get_msg(error));
25.165 - razor_error_free(error);
25.166 return -1;
25.167 }
25.168 if (relocations)
25.169 @@ -1441,7 +1438,7 @@
25.170 }
25.171 } while (opt);
25.172
25.173 - upstream = razor_set_open(rawhide_repo_filename, 0, &error);
25.174 + upstream = razor_set_open(rawhide_repo_uri, 0, &error);
25.175 if (upstream == NULL) {
25.176 fprintf(stderr, "%s\n", razor_error_get_msg(error));
25.177 razor_error_free(error);
25.178 @@ -1513,7 +1510,7 @@
25.179 }
25.180 }
25.181
25.182 - if (razor_atomic_create_dir(atomic, "rpms",
25.183 + if (razor_atomic_create_dir(atomic, "file:rpms",
25.184 S_IRWXU | S_IRWXG | S_IRWXO) ||
25.185 razor_atomic_commit(atomic)) {
25.186 fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
25.187 @@ -1604,7 +1601,7 @@
25.188 struct razor_package_iterator *pi;
25.189 struct razor_package *package;
25.190 const char *pattern, *name, *version, *arch;
25.191 - char url[256], file[256];
25.192 + char *url, *file, *s, filename[256];
25.193 int matches = 0;
25.194
25.195 switch (razor_getopt(argc, argv, 0, NULL, "[pattern]", NULL)) {
25.196 @@ -1621,7 +1618,7 @@
25.197
25.198 pattern = argv[optind];
25.199
25.200 - set = razor_set_open(rawhide_repo_filename, 0, &error);
25.201 + set = razor_set_open(rawhide_repo_uri, 0, &error);
25.202 if (set == NULL) {
25.203 fprintf(stderr, "%s\n", razor_error_get_msg(error));
25.204 razor_error_free(error);
25.205 @@ -1630,7 +1627,7 @@
25.206
25.207 atomic = razor_atomic_open("Download packages");
25.208
25.209 - if (razor_atomic_create_dir(atomic, "rpms",
25.210 + if (razor_atomic_create_dir(atomic, "file:rpms",
25.211 S_IRWXU | S_IRWXG | S_IRWXO)) {
25.212 fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
25.213 razor_atomic_destroy(atomic);
25.214 @@ -1654,12 +1651,15 @@
25.215 continue;
25.216
25.217 matches++;
25.218 - snprintf(url, sizeof url,
25.219 - "%s/Packages/%s-%s.%s.rpm",
25.220 - yum_url, name, version, arch);
25.221 - snprintf(file, sizeof file,
25.222 - "rpms/%s-%s.%s.rpm", name, version, arch);
25.223 + snprintf(filename, sizeof filename,
25.224 + "%s-%s.%s.rpm", name, version, arch);
25.225 + s = razor_concat("Packages/", filename, NULL);
25.226 + url = razor_path_relative_to_uri(yum_url, s, NULL);
25.227 + free(s);
25.228 + file = razor_concat("rpms/", filename, NULL);
25.229 download_if_missing(url, file);
25.230 + free(url);
25.231 + free(file);
25.232 }
25.233 razor_package_iterator_destroy(pi);
25.234 razor_set_unref(set);
25.235 @@ -1804,7 +1804,7 @@
25.236
25.237 snprintf(pattern, sizeof pattern, "*%s*", argv[1]);
25.238
25.239 - set = razor_set_open(rawhide_repo_filename, 0, &error);
25.240 + set = razor_set_open(rawhide_repo_uri, 0, &error);
25.241 if (set == NULL) {
25.242 fprintf(stderr, "%s\n", razor_error_get_msg(error));
25.243 razor_error_free(error);
25.244 @@ -1939,7 +1939,7 @@
25.245 while ((opt = getopt_long(argc, argv, "+", options, NULL)) != -1) {
25.246 switch (opt) {
25.247 case opt_database:
25.248 - razor_set_database_path(optarg);
25.249 + razor_set_database_uri(optarg);
25.250 break;
25.251 case opt_help:
25.252 default:
25.253 @@ -1949,12 +1949,12 @@
25.254 printf(" --help "
25.255 "Show this help message and exit\n");
25.256 printf(" --help-commands List commands\n");
25.257 - printf(" --database=PATH "
25.258 + printf(" --database=URI "
25.259 "Use alternative database\n");
25.260 - printf(" --root=ROOT "
25.261 - "Use ROOT as top level directory\n");
25.262 - printf(" --url=URL "
25.263 - "Use URL as upstream repository\n");
25.264 + printf(" --root=URI "
25.265 + "Use URI as top level directory\n");
25.266 + printf(" --url=URI "
25.267 + "Use URI as upstream repository\n");
25.268 return opt != opt_help;
25.269 case opt_root:
25.270 install_root = optarg;
26.1 --- a/test/Makefile.am Sat Jun 11 17:56:48 2016 +0100
26.2 +++ b/test/Makefile.am Mon Jul 04 10:48:18 2016 +0100
26.3 @@ -4,7 +4,7 @@
26.4 if HAVE_LUA
26.5 check_SCRIPTS += lua mult-install
26.6 endif
26.7 -check_SCRIPTS += order
26.8 +check_SCRIPTS += order non-ascii relative-root
26.9
26.10 relocate: relocate.sh primary.xml.gz
26.11 cp $(srcdir)/relocate.sh relocate
26.12 @@ -24,6 +24,12 @@
26.13 order: order.sh primary.xml.gz
26.14 cp $(srcdir)/order.sh order
26.15
26.16 +non-ascii: non-ascii.sh primary.xml.gz
26.17 + cp $(srcdir)/non-ascii.sh non-ascii
26.18 +
26.19 +relative-root: relative-root.sh primary.xml.gz
26.20 + cp $(srcdir)/relative-root.sh relative-root
26.21 +
26.22 lua: lua.sh primary.xml.gz
26.23 cp $(srcdir)/lua.sh lua
26.24
26.25 @@ -40,25 +46,26 @@
26.26 rpmbuild --define "_topdir `pwd`/rpmbuild" -bb $(srcdir)/zsh.spec
26.27 rpmbuild --define "_topdir `pwd`/rpmbuild" -bb $(srcdir)/zsh2.spec
26.28 rpmbuild --define "_topdir `pwd`/rpmbuild" -bb $(srcdir)/filesystem.spec
26.29 - mkdir -p base/rpms
26.30 - mv rpmbuild/RPMS/noarch/*.rpm base/rpms
26.31 + rpmbuild --define "_topdir `pwd`/rpmbuild" -bb $(srcdir)/aljip.spec
26.32 + mkdir -p base/Packages
26.33 + mv rpmbuild/RPMS/noarch/*.rpm base/Packages
26.34 rm -rf rpmbuild
26.35 - createrepo --simple-md-filenames -o base base/rpms
26.36 + createrepo --simple-md-filenames base
26.37
26.38 updates/repodata/primary.xml.gz: zip.spec Makefile
26.39 rm -rf rpmbuild updates
26.40 mkdir -p rpmbuild/BUILD rpmbuild/RPMS
26.41 rpmbuild --define "_topdir `pwd`/rpmbuild" --define "_version 2" \
26.42 -bb $(srcdir)/zip.spec
26.43 - mkdir -p updates/rpms
26.44 - mv rpmbuild/RPMS/noarch/*.rpm updates/rpms
26.45 + mkdir -p updates/Packages
26.46 + mv rpmbuild/RPMS/noarch/*.rpm updates/Packages
26.47 rm -rf rpmbuild
26.48 - createrepo --simple-md-filenames -o updates updates/rpms
26.49 + createrepo --simple-md-filenames updates
26.50
26.51 primary.xml.gz: base/repodata/primary.xml.gz
26.52 cp base/repodata/primary.xml.gz base/repodata/filelists.xml.gz .
26.53 rm -rf rpms
26.54 - ln -s base/rpms .
26.55 + ln -s base/Packages rpms
26.56
26.57 TESTS = $(check_SCRIPTS)
26.58
26.59 @@ -68,7 +75,10 @@
26.60 zsh.spec \
26.61 zsh2.spec \
26.62 filesystem.spec \
26.63 + aljip.spec \
26.64 order.sh \
26.65 + non-ascii.sh \
26.66 + relative-root.sh \
26.67 mult-install.sh \
26.68 lua.sh \
26.69 remove.sh \
27.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
27.2 +++ b/test/aljip.spec Mon Jul 04 10:48:18 2016 +0100
27.3 @@ -0,0 +1,35 @@
27.4 +%define _source_payload w9.gzdio
27.5 +%define _binary_payload w9.gzdio
27.6 +
27.7 +Name: aljip
27.8 +Summary: Test package
27.9 +Group: Test
27.10 +License: GPL
27.11 +Version: %{_version}
27.12 +Release: 1
27.13 +Source: aljip.tar
27.14 +BuildArch: noarch
27.15 +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
27.16 +Prefix: /usr
27.17 +
27.18 +%description
27.19 +Test package
27.20 +
27.21 +%prep
27.22 +
27.23 +%build
27.24 +
27.25 +%install
27.26 +mkdir -p $RPM_BUILD_ROOT/usr/bin
27.27 +echo %{name}-%{version}-%{release} > "$RPM_BUILD_ROOT/usr/bin/data file.alz"
27.28 +echo %{name}-%{version}-%{release} > "$RPM_BUILD_ROOT/usr/bin/-._~.alz"
27.29 +echo %{name}-%{version}-%{release} > "$RPM_BUILD_ROOT/usr/bin/!$&'()*+,;=.alz"
27.30 +echo %{name}-%{version}-%{release} > "$RPM_BUILD_ROOT/usr/bin/:?#[]@.alz"
27.31 +echo %{name}-%{version}-%{release} > "$RPM_BUILD_ROOT/usr/bin/sébastien.alz"
27.32 +echo %{name}-%{version}-%{release} > "$RPM_BUILD_ROOT/usr/bin/lukáš.alz"
27.33 +echo %{name}-%{version}-%{release} > "$RPM_BUILD_ROOT/usr/bin/알집.sh"
27.34 +
27.35 +%clean
27.36 +
27.37 +%files
27.38 +/usr/bin/*
28.1 --- a/test/details.sh Sat Jun 11 17:56:48 2016 +0100
28.2 +++ b/test/details.sh Mon Jul 04 10:48:18 2016 +0100
28.3 @@ -4,11 +4,12 @@
28.4 else
28.5 razor=../src/razor
28.6 fi
28.7 -export RAZOR_ROOT=`mktemp -dt` || exit 1
28.8 +tmpdir=`mktemp -dt` || exit 1
28.9 +export RAZOR_ROOT="file:$tmpdir"
28.10 $razor init || exit 1
28.11 -export YUM_URL="file://localhost/`pwd`"
28.12 +export YUM_URL="file:`pwd`/base"
28.13 $razor import-yum || exit 1
28.14 $razor install zsh2 || exit 1
28.15 $razor info zsh2 > details.out || exit 1
28.16 diff -u $srcdir/details.ref details.out || exit 1
28.17 -rm -rf "$RAZOR_ROOT"
28.18 +rm -rf "$tmpdir"
29.1 --- a/test/lua.sh Sat Jun 11 17:56:48 2016 +0100
29.2 +++ b/test/lua.sh Mon Jul 04 10:48:18 2016 +0100
29.3 @@ -6,23 +6,24 @@
29.4 fi
29.5 check_filesystem()
29.6 {
29.7 - if [ ! -e "$RAZOR_ROOT$1" ]; then
29.8 + if [ ! -e "$tmpdir$1" ]; then
29.9 echo $1: Not in filesystem >&2
29.10 exit 1
29.11 fi
29.12 }
29.13 check_file()
29.14 {
29.15 - ../src/razor list-files | grep -x "$1" > /dev/null
29.16 + ../src/razor list-files | grep -F -x "$1" > /dev/null
29.17 if [ $? -ne 0 ]; then
29.18 echo $1: Not in database >&2
29.19 exit 1
29.20 fi
29.21 check_filesystem "$1"
29.22 }
29.23 -export RAZOR_ROOT=`mktemp -dt` || exit 1
29.24 +tmpdir=`mktemp -dt` || exit 1
29.25 +export RAZOR_ROOT="file:$tmpdir"
29.26 $razor init || exit 1
29.27 -export YUM_URL="file://localhost/`pwd`"
29.28 +export YUM_URL="file:`pwd`/base"
29.29 $razor import-yum || exit 1
29.30 $razor install filesystem || exit 1
29.31 check_file /etc
29.32 @@ -30,4 +31,4 @@
29.33 check_file /usr/lib
29.34 check_file /usr/include
29.35 check_filesystem /media/cdrom
29.36 -rm -rf "$RAZOR_ROOT"
29.37 +rm -rf "$tmpdir"
30.1 --- a/test/mult-install.sh Sat Jun 11 17:56:48 2016 +0100
30.2 +++ b/test/mult-install.sh Mon Jul 04 10:48:18 2016 +0100
30.3 @@ -6,37 +6,37 @@
30.4 fi
30.5 fs_check_file()
30.6 {
30.7 - if [ ! -e "$RAZOR_ROOT$1" ]; then
30.8 + if [ ! -e "$tmpdir$1" ]; then
30.9 echo $1: Not in filesystem >&2
30.10 - ls -R "$RAZOR_ROOT" >&2
30.11 + ls -R "$tmpdir" >&2
30.12 exit 1
30.13 fi
30.14 }
30.15 fs_check_file_contents()
30.16 {
30.17 fs_check_file "$1"
30.18 - if [ `cat "$RAZOR_ROOT$1"` != "$2" ]; then
30.19 + if [ `cat "$tmpdir$1"` != "$2" ]; then
30.20 echo $1: Unexpected contents >&2
30.21 - cat "$RAZOR_ROOT$1" >&2
30.22 + cat "$tmpdir$1" >&2
30.23 exit 1
30.24 fi
30.25 }
30.26 fs_check_no_file()
30.27 {
30.28 - if [ -e "$RAZOR_ROOT$1" ]; then
30.29 + if [ -e "$tmpdir$1" ]; then
30.30 echo $1: Still in filesystem >&2
30.31 exit 1
30.32 fi
30.33 }
30.34 check_file()
30.35 {
30.36 - $razor list-files | grep -x "$1" > /dev/null
30.37 + $razor list-files | grep -F -x "$1" > /dev/null
30.38 if [ $? -ne 0 ]; then
30.39 echo $1: Not in database >&2
30.40 $razor list-files >&2
30.41 exit 1
30.42 fi
30.43 - $razor list-files "$1" | grep -x "$1" > /dev/null
30.44 + $razor list-files "$1" | grep -F -x "$1" > /dev/null
30.45 if [ $? -ne 0 ]; then
30.46 echo $1: Not seen by patterned list >&2
30.47 $razor list-files "$1" >&2
30.48 @@ -50,7 +50,7 @@
30.49 fi
30.50 for nevra in "$pkgs"; do
30.51 name=`echo $nevra | sed 's/\-.*$//'`
30.52 - $razor list-package-files "$name" | grep -x "$1" > /dev/null
30.53 + $razor list-package-files "$name" | grep -F -x "$1" > /dev/null
30.54 if [ $? -ne 0 ]; then
30.55 echo $1: Not in database for package $name >&2
30.56 $razor list-package-files "$name"
30.57 @@ -61,7 +61,7 @@
30.58 }
30.59 check_no_file()
30.60 {
30.61 - $razor list-files | grep -x "$1" > /dev/null
30.62 + $razor list-files | grep -F -x "$1" > /dev/null
30.63 if [ $? -eq 0 ]; then
30.64 echo $1: Still in database >&2
30.65 exit 1
30.66 @@ -76,9 +76,10 @@
30.67 exit 1
30.68 fi
30.69 }
30.70 -export RAZOR_ROOT=`mktemp -dt` || exit 1
30.71 +tmpdir=`mktemp -dt` || exit 1
30.72 +export RAZOR_ROOT="file:$tmpdir"
30.73 $razor init || exit 1
30.74 -export YUM_URL="file://localhost/`pwd`"
30.75 +export YUM_URL="file:`pwd`/base"
30.76 $razor import-yum || exit 1
30.77 $razor install --relocate /usr=/opt zip || exit 1
30.78 fs_check_file_contents /opt/bin/zip zip-1-1
30.79 @@ -87,4 +88,4 @@
30.80 check_install_count zip 2
30.81 $razor install --relocate /usr=/opt zip || exit 1
30.82 check_install_count zip 3
30.83 -rm -rf "$RAZOR_ROOT"
30.84 +rm -rf "$tmpdir"
31.1 --- a/test/named-root.sh Sat Jun 11 17:56:48 2016 +0100
31.2 +++ b/test/named-root.sh Mon Jul 04 10:48:18 2016 +0100
31.3 @@ -6,19 +6,19 @@
31.4 fi
31.5 check_file()
31.6 {
31.7 - $razor list-files | grep -x "$1" > /dev/null
31.8 + $razor list-files | grep -F -x "$1" > /dev/null
31.9 if [ $? -ne 0 ]; then
31.10 echo $1: Not in database >&2
31.11 $razor list-files >&2
31.12 exit 1
31.13 fi
31.14 - $razor list-files c: | grep -x "$1" > /dev/null
31.15 + $razor list-files c: | grep -F -x "$1" > /dev/null
31.16 if [ $? -ne 0 ]; then
31.17 echo $1: Not seen by named root list >&2
31.18 $razor list-files c: >&2
31.19 exit 1
31.20 fi
31.21 - $razor list-files "$1" | grep -x "$1" > /dev/null
31.22 + $razor list-files "$1" | grep -F -x "$1" > /dev/null
31.23 if [ $? -ne 0 ]; then
31.24 echo $1: Not seen by patterned list >&2
31.25 $razor list-files "$1" >&2
31.26 @@ -32,24 +32,23 @@
31.27 fi
31.28 for nevra in "$pkgs"; do
31.29 name=`echo $nevra | sed 's/\-.*$//'`
31.30 - $razor list-package-files "$name" | grep -x "$1" > /dev/null
31.31 + $razor list-package-files "$name" | grep -F -x "$1" > /dev/null
31.32 if [ $? -ne 0 ]; then
31.33 echo $1: Not in database for package $name >&2
31.34 $razor list-package-files "$name"
31.35 exit 1
31.36 fi
31.37 done
31.38 - if [ ! -e "$RAZOR_ROOT$1" ]; then
31.39 + if [ ! -e "$tmpdir/$1" ]; then
31.40 echo $1: Not in filesystem >&2
31.41 exit 1
31.42 fi
31.43 }
31.44 tmpdir=`mktemp -dt` || exit 1
31.45 -export RAZOR_ROOT="$tmpdir/x-"
31.46 -mkdir -p "$tmpdir/x-/var/lib" "$tmpdir/x-c:"
31.47 +export RAZOR_ROOT="file:$tmpdir"
31.48 export RAZOR_NO_ROOT_NAME_CHECKS=1
31.49 $razor init || exit 1
31.50 -export YUM_URL="file://localhost/`pwd`"
31.51 +export YUM_URL="file:`pwd`/base"
31.52 $razor import-yum || exit 1
31.53 $razor install --relocate /usr=c:/test zap || exit 1
31.54 $razor install --relocate /usr=c:/test zip || exit 1
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
32.2 +++ b/test/non-ascii.sh Mon Jul 04 10:48:18 2016 +0100
32.3 @@ -0,0 +1,34 @@
32.4 +#!/bin/sh
32.5 +if [ $# -gt 0 ]; then
32.6 + razor="$1"
32.7 +else
32.8 + razor=../src/razor
32.9 +fi
32.10 +check_file()
32.11 +{
32.12 + $razor list-files | grep -F -x "$1" > /dev/null
32.13 + if [ $? -ne 0 ]; then
32.14 + echo $1: Not in database >&2
32.15 + $razor list-files >&2
32.16 + exit 1
32.17 + fi
32.18 + if [ ! -e "$tmpdir$1" ]; then
32.19 + echo $1: Not in filesystem >&2
32.20 + ls -R "$tmpdir" >&2
32.21 + exit 1
32.22 + fi
32.23 +}
32.24 +tmpdir=`mktemp -dt` || exit 1
32.25 +export RAZOR_ROOT="file:$tmpdir"
32.26 +$razor init || exit 1
32.27 +export YUM_URL="file:`pwd`/base"
32.28 +$razor import-yum || exit 1
32.29 +$razor install aljip || exit 1
32.30 +check_file "/usr/bin/data file.alz"
32.31 +check_file "/usr/bin/-._~.alz"
32.32 +check_file "/usr/bin/!$&'()*+,;=.alz"
32.33 +check_file "/usr/bin/:?#[]@.alz"
32.34 +check_file "/usr/bin/sébastien.alz"
32.35 +check_file "/usr/bin/lukáš.alz"
32.36 +check_file "/usr/bin/알집.sh"
32.37 +rm -rf "$tmpdir"
33.1 --- a/test/order.sh Sat Jun 11 17:56:48 2016 +0100
33.2 +++ b/test/order.sh Mon Jul 04 10:48:18 2016 +0100
33.3 @@ -6,16 +6,17 @@
33.4 fi
33.5 check_file()
33.6 {
33.7 - if [ ! -e "$RAZOR_ROOT$1" ]; then
33.8 + if [ ! -e "$tmpdir$1" ]; then
33.9 echo $1: Not in filesystem >&2
33.10 exit 1
33.11 fi
33.12 }
33.13 -export RAZOR_ROOT=`mktemp -dt` || exit 1
33.14 +tmpdir=`mktemp -dt` || exit 1
33.15 +export RAZOR_ROOT="file:$tmpdir"
33.16 $razor init || exit 1
33.17 -export YUM_URL="file://localhost/`pwd`"
33.18 +export YUM_URL="file:`pwd`/base"
33.19 $razor import-yum || exit 1
33.20 $razor install zip zsh || exit 1
33.21 check_file /usr/var/lib/zip/data.zap
33.22 check_file /usr/var/lib/zsh/data.zip
33.23 -rm -rf "$RAZOR_ROOT"
33.24 +rm -rf "$tmpdir"
34.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
34.2 +++ b/test/relative-root.sh Mon Jul 04 10:48:18 2016 +0100
34.3 @@ -0,0 +1,32 @@
34.4 +#!/bin/sh
34.5 +if [ $# -gt 0 ]; then
34.6 + razor="$1"
34.7 +else
34.8 + razor=`pwd`/../src/razor
34.9 +fi
34.10 +check_file()
34.11 +{
34.12 + (cd /tmp; $razor list-files) | grep -F -x "$1" > /dev/null
34.13 + if [ $? -ne 0 ]; then
34.14 + echo $1: Not in database >&2
34.15 + (cd /tmp; $razor list-files) >&2
34.16 + exit 1
34.17 + fi
34.18 + if [ ! -e "$tmpdir$1" ]; then
34.19 + echo $1: Not in filesystem >&2
34.20 + ls -R "$tmpdir" >&2
34.21 + exit 1
34.22 + fi
34.23 +}
34.24 +tmpdir=`mktemp --directory --tmpdir=/tmp` || exit 1
34.25 +export RAZOR_ROOT="`echo $tmpdir | sed -e 's&/tmp/&file:&'`"
34.26 +(cd /tmp; $razor init) || exit 1
34.27 +export YUM_URL="file:`pwd`/base"
34.28 +(cd /tmp; $razor import-yum) || exit 1
34.29 +(cd /tmp; $razor install zap) || exit 1
34.30 +(cd /tmp; $razor install --relocate /usr=/opt --relocate /etc=/opt/etc zsh) || exit 1
34.31 +check_file /etc/zsh.conf
34.32 +check_file /usr/bin/zap
34.33 +check_file /opt/bin/zip
34.34 +check_file /opt/bin/zsh
34.35 +rm -rf "$tmpdir"
35.1 --- a/test/relocate.sh Sat Jun 11 17:56:48 2016 +0100
35.2 +++ b/test/relocate.sh Mon Jul 04 10:48:18 2016 +0100
35.3 @@ -1,4 +1,5 @@
35.4 #!/bin/sh
35.5 +set -x
35.6 if [ $# -gt 0 ]; then
35.7 razor="$1"
35.8 else
35.9 @@ -6,19 +7,20 @@
35.10 fi
35.11 check_file()
35.12 {
35.13 - $razor list-files | grep -x "$1" > /dev/null
35.14 + $razor list-files | grep -F -x "$1" > /dev/null
35.15 if [ $? -ne 0 ]; then
35.16 echo $1: Not in database >&2
35.17 exit 1
35.18 fi
35.19 - if [ ! -e "$RAZOR_ROOT$1" ]; then
35.20 + if [ ! -e "$tmpdir$1" ]; then
35.21 echo $1: Not in filesystem >&2
35.22 exit 1
35.23 fi
35.24 }
35.25 -export RAZOR_ROOT=`mktemp -dt` || exit 1
35.26 +tmpdir=`mktemp -dt` || exit 1
35.27 +export RAZOR_ROOT="file:$tmpdir"
35.28 $razor init || exit 1
35.29 -export YUM_URL="file://localhost/`pwd`"
35.30 +export YUM_URL="file:`pwd`/base"
35.31 $razor import-yum || exit 1
35.32 $razor install zap || exit 1
35.33 $razor install --relocate /usr=/opt --relocate /etc=/opt/etc zsh || exit 1
35.34 @@ -26,4 +28,4 @@
35.35 check_file /usr/bin/zap
35.36 check_file /opt/bin/zip
35.37 check_file /opt/bin/zsh
35.38 -rm -rf "$RAZOR_ROOT"
35.39 +rm -rf "$tmpdir"
36.1 --- a/test/remove.sh Sat Jun 11 17:56:48 2016 +0100
36.2 +++ b/test/remove.sh Mon Jul 04 10:48:18 2016 +0100
36.3 @@ -6,28 +6,28 @@
36.4 fi
36.5 fs_check_file()
36.6 {
36.7 - if [ ! -e "$RAZOR_ROOT$1" ]; then
36.8 + if [ ! -e "$tmpdir$1" ]; then
36.9 echo $1: Not in filesystem >&2
36.10 - ls -R "$RAZOR_ROOT" >&2
36.11 + ls -R "$tmpdir" >&2
36.12 exit 1
36.13 fi
36.14 }
36.15 fs_check_no_file()
36.16 {
36.17 - if [ -e "$RAZOR_ROOT$1" ]; then
36.18 + if [ -e "$tmpdir$1" ]; then
36.19 echo $1: Still in filesystem >&2
36.20 exit 1
36.21 fi
36.22 }
36.23 check_file()
36.24 {
36.25 - $razor list-files | grep -x "$1" > /dev/null
36.26 + $razor list-files | grep -F -x "$1" > /dev/null
36.27 if [ $? -ne 0 ]; then
36.28 echo $1: Not in database >&2
36.29 $razor list-files >&2
36.30 exit 1
36.31 fi
36.32 - $razor list-files "$1" | grep -x "$1" > /dev/null
36.33 + $razor list-files "$1" | grep -F -x "$1" > /dev/null
36.34 if [ $? -ne 0 ]; then
36.35 echo $1: Not seen by patterned list >&2
36.36 $razor list-files "$1" >&2
36.37 @@ -41,7 +41,7 @@
36.38 fi
36.39 for nevra in "$pkgs"; do
36.40 name=`echo $nevra | sed 's/\-.*$//'`
36.41 - $razor list-package-files "$name" | grep -x "$1" > /dev/null
36.42 + $razor list-package-files "$name" | grep -F -x "$1" > /dev/null
36.43 if [ $? -ne 0 ]; then
36.44 echo $1: Not in database for package $name >&2
36.45 $razor list-package-files "$name"
36.46 @@ -52,16 +52,17 @@
36.47 }
36.48 check_no_file()
36.49 {
36.50 - $razor list-files | grep -x "$1" > /dev/null
36.51 + $razor list-files | grep -F -x "$1" > /dev/null
36.52 if [ $? -eq 0 ]; then
36.53 echo $1: Still in database >&2
36.54 exit 1
36.55 fi
36.56 fs_check_no_file $1
36.57 }
36.58 -export RAZOR_ROOT=`mktemp -dt` || exit 1
36.59 +tmpdir=`mktemp -dt` || exit 1
36.60 +export RAZOR_ROOT="file:$tmpdir"
36.61 $razor init || exit 1
36.62 -export YUM_URL="file://localhost/`pwd`"
36.63 +export YUM_URL="file:`pwd`/base"
36.64 $razor import-yum || exit 1
36.65 $razor install --relocate /usr=/opt zip || exit 1
36.66 fs_check_file /opt/var/lib/zip/data.zap
36.67 @@ -81,4 +82,4 @@
36.68 fs_check_file /opt/var/lib/zip/data.zap
36.69 $razor remove zsh2 zip || exit 1
36.70 fs_check_no_file /opt/var/lib/zip/data.zap
36.71 -rm -rf "$RAZOR_ROOT"
36.72 +rm -rf "$tmpdir"
37.1 --- a/test/update.sh Sat Jun 11 17:56:48 2016 +0100
37.2 +++ b/test/update.sh Mon Jul 04 10:48:18 2016 +0100
37.3 @@ -6,37 +6,37 @@
37.4 fi
37.5 fs_check_file()
37.6 {
37.7 - if [ ! -e "$RAZOR_ROOT$1" ]; then
37.8 + if [ ! -e "$tmpdir$1" ]; then
37.9 echo $1: Not in filesystem >&2
37.10 - ls -R "$RAZOR_ROOT" >&2
37.11 + ls -R "$tmpdir" >&2
37.12 exit 1
37.13 fi
37.14 }
37.15 fs_check_file_contents()
37.16 {
37.17 fs_check_file "$1"
37.18 - if [ `cat "$RAZOR_ROOT$1"` != "$2" ]; then
37.19 + if [ `cat "$tmpdir$1"` != "$2" ]; then
37.20 echo $1: Unexpected contents >&2
37.21 - cat "$RAZOR_ROOT$1" >&2
37.22 + cat "$tmpdir$1" >&2
37.23 exit 1
37.24 fi
37.25 }
37.26 fs_check_no_file()
37.27 {
37.28 - if [ -e "$RAZOR_ROOT$1" ]; then
37.29 + if [ -e "$tmpdir$1" ]; then
37.30 echo $1: Still in filesystem >&2
37.31 exit 1
37.32 fi
37.33 }
37.34 check_file()
37.35 {
37.36 - $razor list-files | grep -x "$1" > /dev/null
37.37 + $razor list-files | grep -F -x "$1" > /dev/null
37.38 if [ $? -ne 0 ]; then
37.39 echo $1: Not in database >&2
37.40 $razor list-files >&2
37.41 exit 1
37.42 fi
37.43 - $razor list-files "$1" | grep -x "$1" > /dev/null
37.44 + $razor list-files "$1" | grep -F -x "$1" > /dev/null
37.45 if [ $? -ne 0 ]; then
37.46 echo $1: Not seen by patterned list >&2
37.47 $razor list-files "$1" >&2
37.48 @@ -50,7 +50,7 @@
37.49 fi
37.50 for nevra in "$pkgs"; do
37.51 name=`echo $nevra | sed 's/\-.*$//'`
37.52 - $razor list-package-files "$name" | grep -x "$1" > /dev/null
37.53 + $razor list-package-files "$name" | grep -F -x "$1" > /dev/null
37.54 if [ $? -ne 0 ]; then
37.55 echo $1: Not in database for package $name >&2
37.56 $razor list-package-files "$name"
37.57 @@ -61,7 +61,7 @@
37.58 }
37.59 check_no_file()
37.60 {
37.61 - $razor list-files | grep -x "$1" > /dev/null
37.62 + $razor list-files | grep -F -x "$1" > /dev/null
37.63 if [ $? -eq 0 ]; then
37.64 echo $1: Still in database >&2
37.65 exit 1
37.66 @@ -78,13 +78,14 @@
37.67 }
37.68 set_repository()
37.69 {
37.70 + export YUM_URL="file:`pwd`/$1"
37.71 cp $1/repodata/primary.xml.gz $1/repodata/filelists.xml.gz .
37.72 rm -rf rpms
37.73 - ln -s $1/rpms .
37.74 + ln -s $1/Packages rpms
37.75 }
37.76 -export RAZOR_ROOT=`mktemp -dt` || exit 1
37.77 +tmpdir=`mktemp -dt` || exit 1
37.78 +export RAZOR_ROOT="file:$tmpdir"
37.79 $razor init || exit 1
37.80 -export YUM_URL="file://localhost/`pwd`"
37.81 set_repository base
37.82 $razor import-yum || exit 1
37.83 $razor install --relocate /usr=/opt zip || exit 1
37.84 @@ -118,4 +119,4 @@
37.85 $razor install --relocate /usr=/opt zip || exit 1
37.86 $razor update --relocate /usr=/opt zip || exit 1
37.87 check_install_count zip 1
37.88 -rm -rf "$RAZOR_ROOT"
37.89 +rm -rf "$tmpdir"