Drop drive letter from path to razor root when RAZOR_ROOT set.
If the RAZOR_ROOT environment variable was set to eg., /root then on
Microsoft Windows we were trying to use paths such as /rootC:/Programs
which is obviously wrong. Instead we should drop the drive letter
giving paths of the form /root/Programs. Note that the drive letter is
_not_ migrated to C:/root/Programs: If a root of C:/root was desired
then RAZOR_ROOT would have been set to C:/root.
2 * Copyright (C) 2011, 2012, 2014 J. Ali Harlow <ali@juiblex.co.uk>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
37 #include "razor-internal.h"
43 RAZOR_EXPORT struct razor_atomic *
44 razor_atomic_open(const char *description)
46 struct razor_atomic *atomic;
48 atomic = zalloc(sizeof *atomic);
54 razor_atomic_commit(struct razor_atomic *atomic)
56 return razor_atomic_in_error_state(atomic);
60 razor_atomic_destroy(struct razor_atomic *atomic)
63 razor_error_free(atomic->error);
69 razor_atomic_make_dirs(struct razor_atomic *atomic, const char *root,
72 char buffer[PATH_MAX], *p;
73 const char *slash, *next;
76 if (razor_atomic_in_error_state(atomic))
80 p = buffer + strlen(buffer);
81 slash = (p > buffer) ? SKIP_DRIVE_PATH(path) : path;
83 for (slash = path; *slash != '\0'; slash = next) {
85 next = strpbrk(slash + 1, "/\\");
87 next = strchr(slash + 1, '/');
92 memcpy(p, slash, next - slash);
96 if (razor_valid_root_name(buffer))
99 if (stat(buffer, &buf) == 0) {
100 if (!S_ISDIR(buf.st_mode)) {
101 atomic->error = razor_error_new_str(buffer,
105 } else if (mkdir(buffer, 0777) < 0) {
106 atomic->error = razor_error_new_str(buffer,
116 razor_atomic_remove(struct razor_atomic *atomic, const char *path)
123 if (razor_atomic_in_error_state(atomic))
127 buf = razor_utf8_to_utf16(path, -1);
129 if (!DeleteFileW(buf)) {
130 err = GetLastError();
131 if (err != ERROR_FILE_NOT_FOUND &&
132 err != ERROR_PATH_NOT_FOUND &&
133 !(SetFileAttributesW(buf, FILE_ATTRIBUTE_NORMAL) &&
135 !RemoveDirectoryW(buf) &&
136 GetLastError() != ERROR_DIR_NOT_EMPTY)
137 atomic->error = razor_error_new_mswin(buf, err);
143 atomic->error = razor_error_new_str(path, strerror(errno));
146 return razor_atomic_in_error_state(atomic);
150 razor_atomic_rename_file(struct razor_atomic *atomic, const char *oldpath,
154 wchar_t *oldbuf, *newbuf;
155 const DWORD flags = MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING;
158 if (razor_atomic_in_error_state(atomic))
162 newbuf = razor_utf8_to_utf16(newpath, -1);
163 oldbuf = razor_utf8_to_utf16(oldpath, -1);
166 * Passing MOVEFILE_REPLACE_EXISTING to MoveFileEx() will
167 * cover every case we care about _except_ replacing an empty
168 * directory with a file. Calling RemoveDirectory() will deal
169 * with this case while having no effect in all other cases.
171 (void)RemoveDirectoryW(newbuf);
173 if (!MoveFileExW(oldbuf, newbuf, flags))
174 atomic->error = razor_error_new_mswin(newbuf, GetLastError());
179 if (rename(oldpath, newpath))
180 atomic->error = razor_error_new_str(newpath, strerror(errno));
183 return razor_atomic_in_error_state(atomic);
187 razor_atomic_create_dir(struct razor_atomic *atomic, const char *dirname,
190 if (razor_atomic_in_error_state(atomic))
193 if (!mkdir(dirname, mode & (S_IRWXU | S_IRWXG | S_IRWXO)))
196 if (errno != EEXIST) {
197 atomic->error = razor_error_new_str(dirname, strerror(errno));
201 if (chmod(dirname, mode & (S_IRWXU | S_IRWXG | S_IRWXO)) < 0) {
202 atomic->error = razor_error_new_str(dirname, strerror(errno));
210 razor_atomic_create_symlink(struct razor_atomic *atomic, const char *target,
213 if (razor_atomic_in_error_state(atomic))
217 if (symlink(target, path) < 0) {
218 atomic->error = razor_error_new_str(path, strerror(errno));
224 atomic->error = razor_error_new_str(NULL,
225 "Symbolic links not supported "
233 razor_atomic_create_file(struct razor_atomic *atomic, const char *filename,
238 if (razor_atomic_in_error_state(atomic))
241 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
242 mode & (S_IRWXU | S_IRWXG | S_IRWXO));
245 atomic->error = razor_error_new_str(filename, strerror(errno));
250 #endif /* !ENABLE_ATOMIC */