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