librazor/atomic.c
author J. Ali Harlow <ali@juiblex.co.uk>
Mon Jul 11 13:54:54 2016 +0100 (2016-07-11)
changeset 488 7c6d932f291f
parent 447 0a5e583393e1
permissions -rw-r--r--
Release 0.6.3.104
     1 /*
     2  * Copyright (C) 2011-2012, 2016  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 <string.h>
    27 #include <assert.h>
    28 
    29 #include "razor.h"
    30 #include "razor-internal.h"
    31 
    32 /*
    33  * Atomic transactions
    34  */
    35 
    36 static int allow_all_root_names = 0;
    37 
    38 /*
    39  * Primarily intended for testing named roots under UNIX platforms.
    40  */
    41 RAZOR_EXPORT void
    42 razor_disable_root_name_checks(int disable)
    43 {
    44 	allow_all_root_names = disable;
    45 }
    46 
    47 int
    48 razor_allow_all_root_names(void)
    49 {
    50 	return allow_all_root_names;
    51 }
    52 
    53 RAZOR_EXPORT struct razor_error *
    54 razor_atomic_get_error(struct razor_atomic *atomic)
    55 {
    56 	return atomic->error;
    57 }
    58 
    59 RAZOR_EXPORT const char *
    60 razor_atomic_get_error_msg(struct razor_atomic *atomic)
    61 {
    62 	if (atomic->error)
    63 		return razor_error_get_msg(atomic->error);
    64 	else
    65 		return NULL;
    66 }
    67 
    68 RAZOR_EXPORT void
    69 razor_atomic_abort(struct razor_atomic *atomic, int domain, int code,
    70 		   const char *error_msg)
    71 {
    72 	if (!atomic->error)
    73 		atomic->error = razor_error_new_str(domain, code, NULL,
    74 						    error_msg);
    75 }
    76 
    77 RAZOR_EXPORT void
    78 razor_atomic_propagate_error(struct razor_atomic *atomic,
    79 			     struct razor_error *error, const char *summary)
    80 {
    81 	if (!atomic->error) {
    82 		if (!summary) {
    83 			atomic->error = error;
    84 			return;
    85 		} else
    86 			atomic->error = razor_error_dup(error, summary);
    87 	}
    88 
    89 	razor_error_free(error);
    90 }
    91 
    92 RAZOR_EXPORT int
    93 razor_atomic_in_error_state(struct razor_atomic *atomic)
    94 {
    95 	return atomic->error && !atomic->in_undo;
    96 }
    97 
    98 #if !HAVE_WINDOWS_KTM
    99 
   100 /*
   101  * Common code with atomic-none and atomic-emulate
   102  */
   103 
   104 #define RAZOR_ASCII_ISALPHA(c)	\
   105 			((c) >= 'A' && (c) <= 'Z' || (c) >= 'a' && (c) <= 'z')
   106 
   107 int
   108 razor_valid_root_name(const char *name)
   109 {
   110 	if (razor_allow_all_root_names()) {
   111 #ifdef MSWIN_API
   112 		return !strpbrk(name, "/\\");
   113 #else
   114 		return !strchr(name, '/');
   115 #endif
   116 	}
   117 
   118 #ifdef MSWIN_API
   119 	return RAZOR_ASCII_ISALPHA(name[0]) && name[1] == ':' &&
   120 	       name[2] == '\0';
   121 #else
   122 	return name[0] == '\0';
   123 #endif
   124 }
   125 
   126 RAZOR_EXPORT int
   127 razor_atomic_write(struct razor_atomic *atomic, int fd, const void *data,
   128 		   size_t size)
   129 {
   130 	int written;
   131 
   132 	if (razor_atomic_in_error_state(atomic))
   133 		return -1;
   134 
   135 	while(size) {
   136 		written = write(fd, data, size);
   137 		if (written < 0) {
   138 			atomic->error = razor_error_new_posix(NULL);
   139 
   140 			(void)close(fd);
   141 
   142 			return -1;
   143 		}
   144 
   145 		data += written;
   146 		size -= written;
   147 	}
   148 
   149 	return 0;
   150 }
   151 
   152 RAZOR_EXPORT int
   153 razor_atomic_sync(struct razor_atomic *atomic, int handle)
   154 {
   155 	if (razor_atomic_in_error_state(atomic))
   156 		return -1;
   157 
   158 	if (fsync(handle) < 0) {
   159 		atomic->error = razor_error_new_posix(NULL);
   160 		return -1;
   161 	}
   162 
   163 	return 0;
   164 }
   165 
   166 RAZOR_EXPORT int
   167 razor_atomic_close(struct razor_atomic *atomic, int fd)
   168 {
   169 	if (razor_atomic_in_error_state(atomic))
   170 		return -1;
   171 
   172 	if (close(fd) < 0) {
   173 		atomic->error = razor_error_new_posix(NULL);
   174 		return -1;
   175 	}
   176 
   177 	return 0;
   178 }
   179 
   180 #endif	/* !HAVE_WINDOWS_KTM */