1.1 --- a/librazor/atomic-ktm.c Mon Jul 04 10:48:18 2016 +0100
1.2 +++ b/librazor/atomic-ktm.c Fri Jul 08 17:12:36 2016 +0100
1.3 @@ -168,24 +168,84 @@
1.4 free(atomic);
1.5 }
1.6
1.7 +/*
1.8 + * If root_uri is empty, then uri can be a URI (but not a relative-ref; ie.,
1.9 + * a scheme must be specified). If root_uri is non-empty, then it must be a
1.10 + * URI (but not a relative-ref) and uri must be a non-empty path.
1.11 + */
1.12 RAZOR_EXPORT int
1.13 -razor_atomic_make_dirs(struct razor_atomic *atomic, const char *root,
1.14 - const char *path)
1.15 +razor_atomic_make_dirs(struct razor_atomic *atomic, const char *root_uri,
1.16 + const char *uri)
1.17 {
1.18 struct razor_wstr *buffer;
1.19 const char *slash, *next;
1.20 WIN32_FILE_ATTRIBUTE_DATA fa;
1.21 DWORD err;
1.22 int r, creating = 0;
1.23 + struct razor_uri ru;
1.24 + struct razor_error *tmp_error = NULL;
1.25 + char *s, *root, *path;
1.26
1.27 if (razor_atomic_in_error_state(atomic))
1.28 return -1;
1.29
1.30 + if (!*root_uri) {
1.31 + if (razor_uri_parse(&ru, uri, &tmp_error)) {
1.32 + razor_atomic_propagate_error(atomic, tmp_error, NULL);
1.33 + return -1;
1.34 + }
1.35 + s = SKIP_DRIVE_LETTER(ru.path);
1.36 + if (*s == '/')
1.37 + s++;
1.38 + *s = '\0';
1.39 + s = razor_uri_recompose(&ru);
1.40 + uri += strlen(s);
1.41 + free(s);
1.42 + root = razor_path_from_parsed_uri(&ru, &tmp_error);
1.43 + razor_uri_destroy(&ru);
1.44 + if (!root) {
1.45 + razor_atomic_propagate_error(atomic, tmp_error, NULL);
1.46 + return -1;
1.47 + }
1.48 + path = razor_path_from_uri(uri, &tmp_error);
1.49 + if (!path) {
1.50 + razor_atomic_propagate_error(atomic, tmp_error, NULL);
1.51 + free(root);
1.52 + return -1;
1.53 + }
1.54 + } else {
1.55 + root = razor_path_from_uri(root_uri, &tmp_error);
1.56 + if (!root) {
1.57 + razor_atomic_propagate_error(atomic, tmp_error, NULL);
1.58 + return -1;
1.59 + }
1.60 + s = razor_concat("file:", uri, NULL);
1.61 + path = razor_path_from_uri(s, &tmp_error);
1.62 + free(s);
1.63 + if (!path) {
1.64 + razor_atomic_propagate_error(atomic, tmp_error, NULL);
1.65 + free(root);
1.66 + return -1;
1.67 + }
1.68 + /*
1.69 + * Arguably, razor_atomic_make_dirs(a, "file:///", "c:/xxx")
1.70 + * is wrong, and we should be called as:
1.71 + * razor_atomic_make_dirs(a, "file:///c:/", "xxx")
1.72 + * but cope with it anyway.
1.73 + */
1.74 + s = SKIP_DRIVE_LETTER(path);
1.75 + if (!strcmp(root, "/") && *s == '/') {
1.76 + free(root);
1.77 + root = strdup("");
1.78 + }
1.79 + }
1.80 +
1.81 buffer = razor_wstr_create(root, -1);
1.82 + free(root);
1.83 slash = buffer->len ? SKIP_DRIVE_LETTER(path) : path;
1.84
1.85 for (; *slash != '\0'; slash = next) {
1.86 - next = strpbrk(slash + 1, "/\\");
1.87 + next = strchr(slash + 1, '/');
1.88 if (next == NULL)
1.89 break;
1.90
1.91 @@ -208,6 +268,7 @@
1.92 razor_set_error_mswin(&atomic->error,
1.93 buffer->str, err);
1.94 razor_wstr_destroy(buffer);
1.95 + free(path);
1.96 return -1;
1.97 }
1.98 } else if (!(fa.dwFileAttributes&
1.99 @@ -217,6 +278,7 @@
1.100 ERROR_DIRECTORY, buffer->str,
1.101 "Not a directory");
1.102 razor_wstr_destroy(buffer);
1.103 + free(path);
1.104 return -1;
1.105 }
1.106 }
1.107 @@ -227,6 +289,7 @@
1.108 buffer->str,
1.109 GetLastError());
1.110 razor_wstr_destroy(buffer);
1.111 + free(path);
1.112 return -1;
1.113 }
1.114
1.115 @@ -236,21 +299,32 @@
1.116 }
1.117
1.118 razor_wstr_destroy(buffer);
1.119 + free(path);
1.120
1.121 return 0;
1.122 }
1.123
1.124 RAZOR_EXPORT int
1.125 -razor_atomic_remove(struct razor_atomic *atomic, const char *path)
1.126 +razor_atomic_remove(struct razor_atomic *atomic, const char *uri)
1.127 {
1.128 + struct razor_error *tmp_error = NULL;
1.129 + char *path;
1.130 wchar_t *buf;
1.131 DWORD err;
1.132
1.133 if (razor_atomic_in_error_state(atomic))
1.134 return -1;
1.135
1.136 + path = razor_path_from_uri(uri, &tmp_error);
1.137 + if (!path) {
1.138 + razor_atomic_propagate_error(atomic, tmp_error, NULL);
1.139 + return -1;
1.140 + }
1.141 +
1.142 buf = razor_utf8_to_utf16(path, -1);
1.143
1.144 + free(path);
1.145 +
1.146 if (DeleteFileTransactedW(buf, atomic->transaction)) {
1.147 free(buf);
1.148 return 0;
1.149 @@ -291,18 +365,36 @@
1.150 }
1.151
1.152 RAZOR_EXPORT int
1.153 -razor_atomic_rename_file(struct razor_atomic *atomic, const char *oldpath,
1.154 - const char *newpath)
1.155 +razor_atomic_rename_file(struct razor_atomic *atomic, const char *old_uri,
1.156 + const char *new_uri)
1.157 {
1.158 + struct razor_error *tmp_error = NULL;
1.159 + char *oldpath, *newpath;
1.160 wchar_t *oldbuf, *newbuf;
1.161 const DWORD flags = MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING;
1.162
1.163 if (razor_atomic_in_error_state(atomic))
1.164 return -1;
1.165
1.166 + newpath = razor_path_from_uri(new_uri, &tmp_error);
1.167 + if (!newpath) {
1.168 + razor_atomic_propagate_error(atomic, tmp_error, NULL);
1.169 + return -1;
1.170 + }
1.171 +
1.172 + oldpath = razor_path_from_uri(old_uri, &tmp_error);
1.173 + if (!oldpath) {
1.174 + razor_atomic_propagate_error(atomic, tmp_error, NULL);
1.175 + free(newpath);
1.176 + return -1;
1.177 + }
1.178 +
1.179 newbuf = razor_utf8_to_utf16(newpath, -1);
1.180 oldbuf = razor_utf8_to_utf16(oldpath, -1);
1.181
1.182 + free(newpath);
1.183 + free(oldpath);
1.184 +
1.185 /*
1.186 * Passing MOVEFILE_REPLACE_EXISTING to MoveFileTransaction() will
1.187 * cover every case we care about _except_ replacing an empty
1.188 @@ -322,9 +414,11 @@
1.189 }
1.190
1.191 RAZOR_EXPORT int
1.192 -razor_atomic_create_dir(struct razor_atomic *atomic, const char *dirname,
1.193 +razor_atomic_create_dir(struct razor_atomic *atomic, const char *uri,
1.194 mode_t mode)
1.195 {
1.196 + struct razor_error *tmp_error = NULL;
1.197 + char *dirname;
1.198 wchar_t *buf;
1.199 DWORD err;
1.200 WIN32_FILE_ATTRIBUTE_DATA fa;
1.201 @@ -332,8 +426,16 @@
1.202 if (razor_atomic_in_error_state(atomic))
1.203 return -1;
1.204
1.205 + dirname = razor_path_from_uri(uri, &tmp_error);
1.206 + if (!dirname) {
1.207 + razor_atomic_propagate_error(atomic, tmp_error, NULL);
1.208 + return -1;
1.209 + }
1.210 +
1.211 buf = razor_utf8_to_utf16(dirname, -1);
1.212
1.213 + free(dirname);
1.214 +
1.215 if (!CreateDirectoryTransactedW(NULL, buf, NULL, atomic->transaction)) {
1.216 err = GetLastError();
1.217 if (err != ERROR_FILE_EXISTS && err != ERROR_ALREADY_EXISTS) {
1.218 @@ -367,7 +469,7 @@
1.219
1.220 RAZOR_EXPORT int
1.221 razor_atomic_create_symlink(struct razor_atomic *atomic, const char *target,
1.222 - const char *path)
1.223 + const char *uri)
1.224 {
1.225 if (razor_atomic_in_error_state(atomic))
1.226 return -1;
1.227 @@ -385,9 +487,11 @@
1.228 }
1.229
1.230 RAZOR_EXPORT int
1.231 -razor_atomic_create_file(struct razor_atomic *atomic, const char *filename,
1.232 +razor_atomic_create_file(struct razor_atomic *atomic, const char *uri,
1.233 mode_t mode)
1.234 {
1.235 + struct razor_error *tmp_error = NULL;
1.236 + char *filename;
1.237 DWORD attribs;
1.238 struct razor_atomic_file *files;
1.239 int i = atomic->n_files;
1.240 @@ -395,11 +499,18 @@
1.241 if (razor_atomic_in_error_state(atomic))
1.242 return -1;
1.243
1.244 + filename = razor_path_from_uri(uri, &tmp_error);
1.245 + if (!filename) {
1.246 + razor_atomic_propagate_error(atomic, tmp_error, NULL);
1.247 + return -1;
1.248 + }
1.249 +
1.250 files = realloc(atomic->files,
1.251 (atomic->n_files+1) * sizeof(struct razor_atomic_file));
1.252 if (!files) {
1.253 razor_set_error(&atomic->error, RAZOR_POSIX_ERROR, ENOMEM, NULL,
1.254 "Not enough memory");
1.255 + free(filename);
1.256 return -1;
1.257 }
1.258 atomic->n_files++;
1.259 @@ -407,6 +518,8 @@
1.260
1.261 files[i].path = razor_utf8_to_utf16(filename, -1);
1.262
1.263 + free(filename);
1.264 +
1.265 /*
1.266 * Passing CREATE_ALWAYS to CreateFileTransacted() will cover
1.267 * every case we care about _except_ replacing an empty directory