ali@403: /* ali@416: * Copyright (C) 2011-2012 J. Ali Harlow ali@403: * ali@403: * This program is free software; you can redistribute it and/or modify ali@403: * it under the terms of the GNU General Public License as published by ali@403: * the Free Software Foundation; either version 2 of the License, or ali@403: * (at your option) any later version. ali@403: * ali@403: * This program is distributed in the hope that it will be useful, ali@403: * but WITHOUT ANY WARRANTY; without even the implied warranty of ali@403: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ali@403: * GNU General Public License for more details. ali@403: * ali@403: * You should have received a copy of the GNU General Public License along ali@403: * with this program; if not, write to the Free Software Foundation, Inc., ali@403: * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ali@403: */ ali@403: ali@403: #include "config.h" ali@403: ali@403: #include ali@403: #include ali@403: #include ali@403: #include ali@403: #include ali@416: #include ali@416: #include ali@403: #include ali@403: #include ali@403: #include ali@403: ali@403: #include "razor.h" ali@403: #include "razor-internal.h" ali@403: ali@403: /* ali@403: * Atomic transactions ali@403: */ ali@403: ali@403: static int allow_all_root_names = 0; ali@403: ali@403: /* ali@403: * Primarily intended for testing named roots under UNIX platforms. ali@403: */ ali@403: RAZOR_EXPORT void ali@403: razor_disable_root_name_checks(int disable) ali@403: { ali@403: allow_all_root_names = disable; ali@403: } ali@403: ali@416: int ali@416: razor_allow_all_root_names(void) ali@403: { ali@416: return allow_all_root_names; ali@403: } ali@403: ali@403: RAZOR_EXPORT const char * ali@403: razor_atomic_get_error_msg(struct razor_atomic *atomic) ali@403: { ali@403: if (!atomic->error_msg) { ali@403: if (atomic->error_path) ali@403: atomic->error_msg = razor_concat(atomic->error_path, ali@403: ": ", ali@403: atomic->error_str, ali@403: NULL); ali@403: else ali@403: atomic->error_msg = strdup(atomic->error_str); ali@403: } ali@403: ali@403: return atomic->error_msg; ali@403: } ali@403: ali@403: RAZOR_EXPORT void ali@403: razor_atomic_abort(struct razor_atomic *atomic, const char *error_msg) ali@403: { ali@403: if (!atomic->error_str) ali@403: razor_atomic_set_error_str(atomic, NULL, error_msg); ali@403: } ali@403: ali@403: RAZOR_EXPORT int ali@403: razor_atomic_in_error_state(struct razor_atomic *atomic) ali@403: { ali@416: return atomic->error_str && !atomic->in_undo; ali@403: } ali@416: ali@416: #if !HAVE_WINDOWS_KTM ali@416: ali@416: /* ali@416: * Common code with atomic-none and atomic-emulate ali@416: */ ali@416: ali@416: #define RAZOR_ASCII_ISALPHA(c) \ ali@416: ((c) >= 'A' && (c) <= 'Z' || (c) >= 'a' && (c) <= 'z') ali@416: ali@416: int ali@416: razor_valid_root_name(const char *name) ali@416: { ali@416: if (razor_allow_all_root_names()) { ali@416: #ifdef MSWIN_API ali@416: return !strpbrk(name, "/\\"); ali@416: #else ali@416: return !strchr(name, '/'); ali@416: #endif ali@416: } ali@416: ali@416: #ifdef MSWIN_API ali@416: return RAZOR_ASCII_ISALPHA(name[0]) && name[1] == ':' && ali@416: name[2] == '\0'; ali@416: #else ali@416: return name[0] == '\0'; ali@416: #endif ali@416: } ali@416: ali@416: #ifdef MSWIN_API ali@416: void ali@416: razor_atomic_set_error_mswin(struct razor_atomic *atomic, const wchar_t *path, ali@416: DWORD error) ali@416: { ali@416: wchar_t *buf; ali@416: ali@416: assert(!atomic->error_str); ali@416: ali@416: free(atomic->error_path); ali@416: ali@416: if (path) ali@416: atomic->error_path = razor_utf16_to_utf8(path, -1); ali@416: else ali@416: atomic->error_path = NULL; ali@416: ali@416: FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER| ali@416: FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, ali@416: NULL, error, MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), ali@416: (LPWSTR)&buf, 0, NULL); ali@416: atomic->error_str = razor_utf16_to_utf8(buf, -1); ali@416: LocalFree(buf); ali@416: } ali@416: #endif ali@416: ali@416: void ali@416: razor_atomic_set_error_str(struct razor_atomic *atomic, const char *path, ali@416: const char *str) ali@416: { ali@416: assert(!atomic->error_str); ali@416: ali@416: atomic->error_path = path ? strdup(path) : NULL; ali@416: atomic->error_str = strdup(str); ali@416: } ali@416: ali@416: RAZOR_EXPORT int ali@416: razor_atomic_write(struct razor_atomic *atomic, int fd, const void *data, ali@416: size_t size) ali@416: { ali@416: int written; ali@416: ali@416: if (razor_atomic_in_error_state(atomic)) ali@416: return -1; ali@416: ali@416: while(size) { ali@416: written = write(fd, data, size); ali@416: if (written < 0) { ali@416: razor_atomic_set_error_str(atomic, NULL, ali@416: strerror(errno)); ali@416: ali@416: (void)close(fd); ali@416: ali@416: return -1; ali@416: } ali@416: ali@416: data += written; ali@416: size -= written; ali@416: } ali@416: ali@416: return 0; ali@416: } ali@416: ali@416: RAZOR_EXPORT int ali@416: razor_atomic_sync(struct razor_atomic *atomic, int handle) ali@416: { ali@416: if (razor_atomic_in_error_state(atomic)) ali@416: return -1; ali@416: ali@416: if (fsync(handle) < 0) { ali@416: razor_atomic_set_error_str(atomic, NULL, strerror(errno)); ali@416: return -1; ali@416: } ali@416: ali@416: free(atomic->error_path); ali@416: atomic->error_path = NULL; ali@416: ali@416: return 0; ali@416: } ali@416: ali@416: RAZOR_EXPORT int ali@416: razor_atomic_close(struct razor_atomic *atomic, int fd) ali@416: { ali@416: if (razor_atomic_in_error_state(atomic)) ali@416: return -1; ali@416: ali@416: if (close(fd) < 0) { ali@416: razor_atomic_set_error_str(atomic, NULL, strerror(errno)); ali@416: return -1; ali@416: } ali@416: ali@416: free(atomic->error_path); ali@416: atomic->error_path = NULL; ali@416: ali@416: return 0; ali@416: } ali@416: ali@416: #endif /* !HAVE_WINDOWS_KTM */