librazor/atomic.c
author ali <j.a.harlow@letterboxes.org>
Thu Feb 09 20:45:27 2012 +0000 (2012-02-09)
changeset 419 891991677a7f
parent 403 e63951c1d0f8
child 423 6112bcc5d1cf
permissions -rw-r--r--
Release version 0.5.3
     1 /*
     2  * Copyright (C) 2011-2012  J. Ali Harlow <ali@juiblex.co.uk>
     3  *
     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.
     8  *
     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.
    13  *
    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.
    17  */
    18 
    19 #include "config.h"
    20 
    21 #include <stdlib.h>
    22 #include <stdio.h>
    23 #include <limits.h>
    24 #include <errno.h>
    25 #include <unistd.h>
    26 #include <sys/types.h>
    27 #include <sys/stat.h>
    28 #include <fcntl.h>
    29 #include <string.h>
    30 #include <assert.h>
    31 
    32 #include "razor.h"
    33 #include "razor-internal.h"
    34 
    35 /*
    36  * Atomic transactions
    37  */
    38 
    39 static int allow_all_root_names = 0;
    40 
    41 /*
    42  * Primarily intended for testing named roots under UNIX platforms.
    43  */
    44 RAZOR_EXPORT void
    45 razor_disable_root_name_checks(int disable)
    46 {
    47 	allow_all_root_names = disable;
    48 }
    49 
    50 int
    51 razor_allow_all_root_names(void)
    52 {
    53 	return allow_all_root_names;
    54 }
    55 
    56 RAZOR_EXPORT const char *
    57 razor_atomic_get_error_msg(struct razor_atomic *atomic)
    58 {
    59 	if (!atomic->error_msg) {
    60 		if (atomic->error_path)
    61 			atomic->error_msg = razor_concat(atomic->error_path,
    62 							 ": ",
    63 							 atomic->error_str,
    64 							 NULL);
    65 		else
    66 			atomic->error_msg = strdup(atomic->error_str);
    67 	}
    68 
    69 	return atomic->error_msg;
    70 }
    71 
    72 RAZOR_EXPORT void
    73 razor_atomic_abort(struct razor_atomic *atomic, const char *error_msg)
    74 {
    75 	if (!atomic->error_str)
    76 		razor_atomic_set_error_str(atomic, NULL, error_msg);
    77 }
    78 
    79 RAZOR_EXPORT int
    80 razor_atomic_in_error_state(struct razor_atomic *atomic)
    81 {
    82 	return atomic->error_str && !atomic->in_undo;
    83 }
    84 
    85 #if !HAVE_WINDOWS_KTM
    86 
    87 /*
    88  * Common code with atomic-none and atomic-emulate
    89  */
    90 
    91 #define RAZOR_ASCII_ISALPHA(c)	\
    92 			((c) >= 'A' && (c) <= 'Z' || (c) >= 'a' && (c) <= 'z')
    93 
    94 int
    95 razor_valid_root_name(const char *name)
    96 {
    97 	if (razor_allow_all_root_names()) {
    98 #ifdef MSWIN_API
    99 		return !strpbrk(name, "/\\");
   100 #else
   101 		return !strchr(name, '/');
   102 #endif
   103 	}
   104 
   105 #ifdef MSWIN_API
   106 	return RAZOR_ASCII_ISALPHA(name[0]) && name[1] == ':' &&
   107 	       name[2] == '\0';
   108 #else
   109 	return name[0] == '\0';
   110 #endif
   111 }
   112 
   113 #ifdef MSWIN_API
   114 void
   115 razor_atomic_set_error_mswin(struct razor_atomic *atomic, const wchar_t *path,
   116 			     DWORD error)
   117 {
   118 	wchar_t *buf;
   119 
   120 	assert(!atomic->error_str);
   121 
   122 	free(atomic->error_path);
   123 
   124 	if (path)
   125 		atomic->error_path = razor_utf16_to_utf8(path, -1);
   126 	else
   127 		atomic->error_path = NULL;
   128 
   129 	FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER|
   130 		       FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
   131 		       NULL, error, MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
   132 		       (LPWSTR)&buf, 0, NULL);
   133 	atomic->error_str = razor_utf16_to_utf8(buf, -1);
   134 	LocalFree(buf);
   135 }
   136 #endif
   137 
   138 void
   139 razor_atomic_set_error_str(struct razor_atomic *atomic, const char *path,
   140 			   const char *str)
   141 {
   142 	assert(!atomic->error_str);
   143 
   144 	atomic->error_path = path ? strdup(path) : NULL;
   145 	atomic->error_str = strdup(str);
   146 }
   147 
   148 RAZOR_EXPORT int
   149 razor_atomic_write(struct razor_atomic *atomic, int fd, const void *data,
   150 		   size_t size)
   151 {
   152 	int written;
   153 
   154 	if (razor_atomic_in_error_state(atomic))
   155 		return -1;
   156 
   157 	while(size) {
   158 		written = write(fd, data, size);
   159 		if (written < 0) {
   160 			razor_atomic_set_error_str(atomic, NULL,
   161 						   strerror(errno));
   162 
   163 			(void)close(fd);
   164 
   165 			return -1;
   166 		}
   167 
   168 		data += written;
   169 		size -= written;
   170 	}
   171 
   172 	return 0;
   173 }
   174 
   175 RAZOR_EXPORT int
   176 razor_atomic_sync(struct razor_atomic *atomic, int handle)
   177 {
   178 	if (razor_atomic_in_error_state(atomic))
   179 		return -1;
   180 
   181 	if (fsync(handle) < 0) {
   182 		razor_atomic_set_error_str(atomic, NULL, strerror(errno));
   183 		return -1;
   184 	}
   185 
   186 	free(atomic->error_path);
   187 	atomic->error_path = NULL;
   188 
   189 	return 0;
   190 }
   191 
   192 RAZOR_EXPORT int
   193 razor_atomic_close(struct razor_atomic *atomic, int fd)
   194 {
   195 	if (razor_atomic_in_error_state(atomic))
   196 		return -1;
   197 
   198 	if (close(fd) < 0) {
   199 		razor_atomic_set_error_str(atomic, NULL, strerror(errno));
   200 		return -1;
   201 	}
   202 
   203 	free(atomic->error_path);
   204 	atomic->error_path = NULL;
   205 
   206 	return 0;
   207 }
   208 
   209 #endif	/* !HAVE_WINDOWS_KTM */