librazor/atomic.c
author J. Ali Harlow <ali@juiblex.co.uk>
Thu Feb 09 20:45:27 2012 +0000 (2012-02-09)
changeset 418 33b825d3128d
parent 403 e63951c1d0f8
child 423 6112bcc5d1cf
permissions -rw-r--r--
Add transaction barriers
These allow packages to be installed and removed which have scripts
that depend on each other when atomic transactions are involved.
Note that yum supports pre, but not other requires flags. post will
need similar support to the post scripts themselves pulling in the
requires flags from the rpms. Likewise preun and postun will need
similar handling to those scrips since the requires flags will need
to be stored in the razor database.
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 */