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
ali@403
     1
/*
ali@416
     2
 * Copyright (C) 2011-2012  J. Ali Harlow <ali@juiblex.co.uk>
ali@403
     3
 *
ali@403
     4
 * This program is free software; you can redistribute it and/or modify
ali@403
     5
 * it under the terms of the GNU General Public License as published by
ali@403
     6
 * the Free Software Foundation; either version 2 of the License, or
ali@403
     7
 * (at your option) any later version.
ali@403
     8
 *
ali@403
     9
 * This program is distributed in the hope that it will be useful,
ali@403
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
ali@403
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
ali@403
    12
 * GNU General Public License for more details.
ali@403
    13
 *
ali@403
    14
 * You should have received a copy of the GNU General Public License along
ali@403
    15
 * with this program; if not, write to the Free Software Foundation, Inc.,
ali@403
    16
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
ali@403
    17
 */
ali@403
    18
ali@403
    19
#include "config.h"
ali@403
    20
ali@403
    21
#include <stdlib.h>
ali@403
    22
#include <stdio.h>
ali@403
    23
#include <limits.h>
ali@403
    24
#include <errno.h>
ali@403
    25
#include <unistd.h>
ali@416
    26
#include <sys/types.h>
ali@416
    27
#include <sys/stat.h>
ali@403
    28
#include <fcntl.h>
ali@403
    29
#include <string.h>
ali@403
    30
#include <assert.h>
ali@403
    31
ali@403
    32
#include "razor.h"
ali@403
    33
#include "razor-internal.h"
ali@403
    34
ali@403
    35
/*
ali@403
    36
 * Atomic transactions
ali@403
    37
 */
ali@403
    38
ali@403
    39
static int allow_all_root_names = 0;
ali@403
    40
ali@403
    41
/*
ali@403
    42
 * Primarily intended for testing named roots under UNIX platforms.
ali@403
    43
 */
ali@403
    44
RAZOR_EXPORT void
ali@403
    45
razor_disable_root_name_checks(int disable)
ali@403
    46
{
ali@403
    47
	allow_all_root_names = disable;
ali@403
    48
}
ali@403
    49
ali@416
    50
int
ali@416
    51
razor_allow_all_root_names(void)
ali@403
    52
{
ali@416
    53
	return allow_all_root_names;
ali@403
    54
}
ali@403
    55
ali@403
    56
RAZOR_EXPORT const char *
ali@403
    57
razor_atomic_get_error_msg(struct razor_atomic *atomic)
ali@403
    58
{
ali@403
    59
	if (!atomic->error_msg) {
ali@403
    60
		if (atomic->error_path)
ali@403
    61
			atomic->error_msg = razor_concat(atomic->error_path,
ali@403
    62
							 ": ",
ali@403
    63
							 atomic->error_str,
ali@403
    64
							 NULL);
ali@403
    65
		else
ali@403
    66
			atomic->error_msg = strdup(atomic->error_str);
ali@403
    67
	}
ali@403
    68
ali@403
    69
	return atomic->error_msg;
ali@403
    70
}
ali@403
    71
ali@403
    72
RAZOR_EXPORT void
ali@403
    73
razor_atomic_abort(struct razor_atomic *atomic, const char *error_msg)
ali@403
    74
{
ali@403
    75
	if (!atomic->error_str)
ali@403
    76
		razor_atomic_set_error_str(atomic, NULL, error_msg);
ali@403
    77
}
ali@403
    78
ali@403
    79
RAZOR_EXPORT int
ali@403
    80
razor_atomic_in_error_state(struct razor_atomic *atomic)
ali@403
    81
{
ali@416
    82
	return atomic->error_str && !atomic->in_undo;
ali@403
    83
}
ali@416
    84
ali@416
    85
#if !HAVE_WINDOWS_KTM
ali@416
    86
ali@416
    87
/*
ali@416
    88
 * Common code with atomic-none and atomic-emulate
ali@416
    89
 */
ali@416
    90
ali@416
    91
#define RAZOR_ASCII_ISALPHA(c)	\
ali@416
    92
			((c) >= 'A' && (c) <= 'Z' || (c) >= 'a' && (c) <= 'z')
ali@416
    93
ali@416
    94
int
ali@416
    95
razor_valid_root_name(const char *name)
ali@416
    96
{
ali@416
    97
	if (razor_allow_all_root_names()) {
ali@416
    98
#ifdef MSWIN_API
ali@416
    99
		return !strpbrk(name, "/\\");
ali@416
   100
#else
ali@416
   101
		return !strchr(name, '/');
ali@416
   102
#endif
ali@416
   103
	}
ali@416
   104
ali@416
   105
#ifdef MSWIN_API
ali@416
   106
	return RAZOR_ASCII_ISALPHA(name[0]) && name[1] == ':' &&
ali@416
   107
	       name[2] == '\0';
ali@416
   108
#else
ali@416
   109
	return name[0] == '\0';
ali@416
   110
#endif
ali@416
   111
}
ali@416
   112
ali@416
   113
#ifdef MSWIN_API
ali@416
   114
void
ali@416
   115
razor_atomic_set_error_mswin(struct razor_atomic *atomic, const wchar_t *path,
ali@416
   116
			     DWORD error)
ali@416
   117
{
ali@416
   118
	wchar_t *buf;
ali@416
   119
ali@416
   120
	assert(!atomic->error_str);
ali@416
   121
ali@416
   122
	free(atomic->error_path);
ali@416
   123
ali@416
   124
	if (path)
ali@416
   125
		atomic->error_path = razor_utf16_to_utf8(path, -1);
ali@416
   126
	else
ali@416
   127
		atomic->error_path = NULL;
ali@416
   128
ali@416
   129
	FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER|
ali@416
   130
		       FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
ali@416
   131
		       NULL, error, MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
ali@416
   132
		       (LPWSTR)&buf, 0, NULL);
ali@416
   133
	atomic->error_str = razor_utf16_to_utf8(buf, -1);
ali@416
   134
	LocalFree(buf);
ali@416
   135
}
ali@416
   136
#endif
ali@416
   137
ali@416
   138
void
ali@416
   139
razor_atomic_set_error_str(struct razor_atomic *atomic, const char *path,
ali@416
   140
			   const char *str)
ali@416
   141
{
ali@416
   142
	assert(!atomic->error_str);
ali@416
   143
ali@416
   144
	atomic->error_path = path ? strdup(path) : NULL;
ali@416
   145
	atomic->error_str = strdup(str);
ali@416
   146
}
ali@416
   147
ali@416
   148
RAZOR_EXPORT int
ali@416
   149
razor_atomic_write(struct razor_atomic *atomic, int fd, const void *data,
ali@416
   150
		   size_t size)
ali@416
   151
{
ali@416
   152
	int written;
ali@416
   153
ali@416
   154
	if (razor_atomic_in_error_state(atomic))
ali@416
   155
		return -1;
ali@416
   156
ali@416
   157
	while(size) {
ali@416
   158
		written = write(fd, data, size);
ali@416
   159
		if (written < 0) {
ali@416
   160
			razor_atomic_set_error_str(atomic, NULL,
ali@416
   161
						   strerror(errno));
ali@416
   162
ali@416
   163
			(void)close(fd);
ali@416
   164
ali@416
   165
			return -1;
ali@416
   166
		}
ali@416
   167
ali@416
   168
		data += written;
ali@416
   169
		size -= written;
ali@416
   170
	}
ali@416
   171
ali@416
   172
	return 0;
ali@416
   173
}
ali@416
   174
ali@416
   175
RAZOR_EXPORT int
ali@416
   176
razor_atomic_sync(struct razor_atomic *atomic, int handle)
ali@416
   177
{
ali@416
   178
	if (razor_atomic_in_error_state(atomic))
ali@416
   179
		return -1;
ali@416
   180
ali@416
   181
	if (fsync(handle) < 0) {
ali@416
   182
		razor_atomic_set_error_str(atomic, NULL, strerror(errno));
ali@416
   183
		return -1;
ali@416
   184
	}
ali@416
   185
ali@416
   186
	free(atomic->error_path);
ali@416
   187
	atomic->error_path = NULL;
ali@416
   188
ali@416
   189
	return 0;
ali@416
   190
}
ali@416
   191
ali@416
   192
RAZOR_EXPORT int
ali@416
   193
razor_atomic_close(struct razor_atomic *atomic, int fd)
ali@416
   194
{
ali@416
   195
	if (razor_atomic_in_error_state(atomic))
ali@416
   196
		return -1;
ali@416
   197
ali@416
   198
	if (close(fd) < 0) {
ali@416
   199
		razor_atomic_set_error_str(atomic, NULL, strerror(errno));
ali@416
   200
		return -1;
ali@416
   201
	}
ali@416
   202
ali@416
   203
	free(atomic->error_path);
ali@416
   204
	atomic->error_path = NULL;
ali@416
   205
ali@416
   206
	return 0;
ali@416
   207
}
ali@416
   208
ali@416
   209
#endif	/* !HAVE_WINDOWS_KTM */