diff -r 008c75a5e08d -r 8087224f30c4 librazor/atomic-ktm.c --- a/librazor/atomic-ktm.c Mon Jul 04 10:48:18 2016 +0100 +++ b/librazor/atomic-ktm.c Fri Jul 08 17:12:16 2016 +0100 @@ -168,24 +168,84 @@ free(atomic); } +/* + * If root_uri is empty, then uri can be a URI (but not a relative-ref; ie., + * a scheme must be specified). If root_uri is non-empty, then it must be a + * URI (but not a relative-ref) and uri must be a non-empty path. + */ RAZOR_EXPORT int -razor_atomic_make_dirs(struct razor_atomic *atomic, const char *root, - const char *path) +razor_atomic_make_dirs(struct razor_atomic *atomic, const char *root_uri, + const char *uri) { struct razor_wstr *buffer; const char *slash, *next; WIN32_FILE_ATTRIBUTE_DATA fa; DWORD err; int r, creating = 0; + struct razor_uri ru; + struct razor_error *tmp_error = NULL; + char *s, *root, *path; if (razor_atomic_in_error_state(atomic)) return -1; + if (!*root_uri) { + if (razor_uri_parse(&ru, uri, &tmp_error)) { + razor_atomic_propagate_error(atomic, tmp_error, NULL); + return -1; + } + s = SKIP_DRIVE_LETTER(ru.path); + if (*s == '/') + s++; + *s = '\0'; + s = razor_uri_recompose(&ru); + uri += strlen(s); + free(s); + root = razor_path_from_parsed_uri(&ru, &tmp_error); + razor_uri_destroy(&ru); + if (!root) { + razor_atomic_propagate_error(atomic, tmp_error, NULL); + return -1; + } + path = razor_path_from_uri(uri, &tmp_error); + if (!path) { + razor_atomic_propagate_error(atomic, tmp_error, NULL); + free(root); + return -1; + } + } else { + root = razor_path_from_uri(root_uri, &tmp_error); + if (!root) { + razor_atomic_propagate_error(atomic, tmp_error, NULL); + return -1; + } + s = razor_concat("file:", uri, NULL); + path = razor_path_from_uri(s, &tmp_error); + free(s); + if (!path) { + razor_atomic_propagate_error(atomic, tmp_error, NULL); + free(root); + return -1; + } + /* + * Arguably, razor_atomic_make_dirs(a, "file:///", "c:/xxx") + * is wrong, and we should be called as: + * razor_atomic_make_dirs(a, "file:///c:/", "xxx") + * but cope with it anyway. + */ + s = SKIP_DRIVE_LETTER(path); + if (!strcmp(root, "/") && *s == '/') { + free(root); + root = strdup(""); + } + } + buffer = razor_wstr_create(root, -1); + free(root); slash = buffer->len ? SKIP_DRIVE_LETTER(path) : path; for (; *slash != '\0'; slash = next) { - next = strpbrk(slash + 1, "/\\"); + next = strchr(slash + 1, '/'); if (next == NULL) break; @@ -208,6 +268,7 @@ razor_set_error_mswin(&atomic->error, buffer->str, err); razor_wstr_destroy(buffer); + free(path); return -1; } } else if (!(fa.dwFileAttributes& @@ -217,6 +278,7 @@ ERROR_DIRECTORY, buffer->str, "Not a directory"); razor_wstr_destroy(buffer); + free(path); return -1; } } @@ -227,6 +289,7 @@ buffer->str, GetLastError()); razor_wstr_destroy(buffer); + free(path); return -1; } @@ -236,21 +299,32 @@ } razor_wstr_destroy(buffer); + free(path); return 0; } RAZOR_EXPORT int -razor_atomic_remove(struct razor_atomic *atomic, const char *path) +razor_atomic_remove(struct razor_atomic *atomic, const char *uri) { + struct razor_error *tmp_error = NULL; + char *path; wchar_t *buf; DWORD err; if (razor_atomic_in_error_state(atomic)) return -1; + path = razor_path_from_uri(uri, &tmp_error); + if (!path) { + razor_atomic_propagate_error(atomic, tmp_error, NULL); + return -1; + } + buf = razor_utf8_to_utf16(path, -1); + free(path); + if (DeleteFileTransactedW(buf, atomic->transaction)) { free(buf); return 0; @@ -291,18 +365,36 @@ } RAZOR_EXPORT int -razor_atomic_rename_file(struct razor_atomic *atomic, const char *oldpath, - const char *newpath) +razor_atomic_rename_file(struct razor_atomic *atomic, const char *old_uri, + const char *new_uri) { + struct razor_error *tmp_error = NULL; + char *oldpath, *newpath; wchar_t *oldbuf, *newbuf; const DWORD flags = MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING; if (razor_atomic_in_error_state(atomic)) return -1; + newpath = razor_path_from_uri(new_uri, &tmp_error); + if (!newpath) { + razor_atomic_propagate_error(atomic, tmp_error, NULL); + return -1; + } + + oldpath = razor_path_from_uri(old_uri, &tmp_error); + if (!oldpath) { + razor_atomic_propagate_error(atomic, tmp_error, NULL); + free(newpath); + return -1; + } + newbuf = razor_utf8_to_utf16(newpath, -1); oldbuf = razor_utf8_to_utf16(oldpath, -1); + free(newpath); + free(oldpath); + /* * Passing MOVEFILE_REPLACE_EXISTING to MoveFileTransaction() will * cover every case we care about _except_ replacing an empty @@ -322,9 +414,11 @@ } RAZOR_EXPORT int -razor_atomic_create_dir(struct razor_atomic *atomic, const char *dirname, +razor_atomic_create_dir(struct razor_atomic *atomic, const char *uri, mode_t mode) { + struct razor_error *tmp_error = NULL; + char *dirname; wchar_t *buf; DWORD err; WIN32_FILE_ATTRIBUTE_DATA fa; @@ -332,8 +426,16 @@ if (razor_atomic_in_error_state(atomic)) return -1; + dirname = razor_path_from_uri(uri, &tmp_error); + if (!dirname) { + razor_atomic_propagate_error(atomic, tmp_error, NULL); + return -1; + } + buf = razor_utf8_to_utf16(dirname, -1); + free(dirname); + if (!CreateDirectoryTransactedW(NULL, buf, NULL, atomic->transaction)) { err = GetLastError(); if (err != ERROR_FILE_EXISTS && err != ERROR_ALREADY_EXISTS) { @@ -367,7 +469,7 @@ RAZOR_EXPORT int razor_atomic_create_symlink(struct razor_atomic *atomic, const char *target, - const char *path) + const char *uri) { if (razor_atomic_in_error_state(atomic)) return -1; @@ -385,9 +487,11 @@ } RAZOR_EXPORT int -razor_atomic_create_file(struct razor_atomic *atomic, const char *filename, +razor_atomic_create_file(struct razor_atomic *atomic, const char *uri, mode_t mode) { + struct razor_error *tmp_error = NULL; + char *filename; DWORD attribs; struct razor_atomic_file *files; int i = atomic->n_files; @@ -395,11 +499,18 @@ if (razor_atomic_in_error_state(atomic)) return -1; + filename = razor_path_from_uri(uri, &tmp_error); + if (!filename) { + razor_atomic_propagate_error(atomic, tmp_error, NULL); + return -1; + } + files = realloc(atomic->files, (atomic->n_files+1) * sizeof(struct razor_atomic_file)); if (!files) { razor_set_error(&atomic->error, RAZOR_POSIX_ERROR, ENOMEM, NULL, "Not enough memory"); + free(filename); return -1; } atomic->n_files++; @@ -407,6 +518,8 @@ files[i].path = razor_utf8_to_utf16(filename, -1); + free(filename); + /* * Passing CREATE_ALWAYS to CreateFileTransacted() will cover * every case we care about _except_ replacing an empty directory