librazor/atomic-none.c
author J. Ali Harlow <ali@juiblex.co.uk>
Thu Feb 09 20:45:27 2012 +0000 (2012-02-09)
changeset 418 33b825d3128d
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@416
     1
/*
ali@416
     2
 * Copyright (C) 2011-2012  J. Ali Harlow <ali@juiblex.co.uk>
ali@416
     3
 *
ali@416
     4
 * This program is free software; you can redistribute it and/or modify
ali@416
     5
 * it under the terms of the GNU General Public License as published by
ali@416
     6
 * the Free Software Foundation; either version 2 of the License, or
ali@416
     7
 * (at your option) any later version.
ali@416
     8
 *
ali@416
     9
 * This program is distributed in the hope that it will be useful,
ali@416
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
ali@416
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
ali@416
    12
 * GNU General Public License for more details.
ali@416
    13
 *
ali@416
    14
 * You should have received a copy of the GNU General Public License along
ali@416
    15
 * with this program; if not, write to the Free Software Foundation, Inc.,
ali@416
    16
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
ali@416
    17
 */
ali@416
    18
ali@416
    19
#include "config.h"
ali@416
    20
ali@416
    21
#if !ENABLE_ATOMIC
ali@416
    22
ali@416
    23
#include <stdlib.h>
ali@416
    24
#ifdef MSWIN_API
ali@416
    25
#include <windows.h>
ali@416
    26
#endif
ali@416
    27
#include <stdio.h>
ali@416
    28
#include <limits.h>
ali@416
    29
#include <errno.h>
ali@416
    30
#include <unistd.h>
ali@416
    31
#include <fcntl.h>
ali@416
    32
#include <sys/stat.h>
ali@416
    33
#include <string.h>
ali@416
    34
#include <assert.h>
ali@416
    35
ali@416
    36
#include "razor.h"
ali@416
    37
#include "razor-internal.h"
ali@416
    38
ali@416
    39
#ifndef O_BINARY
ali@416
    40
#define O_BINARY	0
ali@416
    41
#endif
ali@416
    42
ali@416
    43
RAZOR_EXPORT struct razor_atomic *
ali@416
    44
razor_atomic_open(const char *description)
ali@416
    45
{
ali@416
    46
	struct razor_atomic *atomic;
ali@416
    47
ali@416
    48
	atomic = zalloc(sizeof *atomic);
ali@416
    49
ali@416
    50
	return atomic;
ali@416
    51
}
ali@416
    52
ali@416
    53
RAZOR_EXPORT int
ali@416
    54
razor_atomic_commit(struct razor_atomic *atomic)
ali@416
    55
{
ali@416
    56
	return razor_atomic_in_error_state(atomic);
ali@416
    57
}
ali@416
    58
ali@416
    59
RAZOR_EXPORT void
ali@416
    60
razor_atomic_destroy(struct razor_atomic *atomic)
ali@416
    61
{
ali@416
    62
	free(atomic->error_path);
ali@416
    63
	free(atomic->error_str);
ali@416
    64
	free(atomic->error_msg);
ali@416
    65
	free(atomic);
ali@416
    66
}
ali@416
    67
ali@416
    68
RAZOR_EXPORT int
ali@416
    69
razor_atomic_make_dirs(struct razor_atomic *atomic, const char *root,
ali@416
    70
		       const char *path)
ali@416
    71
{
ali@416
    72
	char buffer[PATH_MAX], *p;
ali@416
    73
	const char *slash, *next;
ali@416
    74
	struct stat buf;
ali@416
    75
ali@416
    76
	if (razor_atomic_in_error_state(atomic))
ali@416
    77
		return -1;
ali@416
    78
ali@416
    79
	strcpy(buffer, root);
ali@416
    80
	p = buffer + strlen(buffer);
ali@416
    81
	slash = path;
ali@416
    82
	for (slash = path; *slash != '\0'; slash = next) {
ali@416
    83
#ifdef MSWIN_API
ali@416
    84
		next = strpbrk(slash + 1, "/\\");
ali@416
    85
#else
ali@416
    86
		next = strchr(slash + 1, '/');
ali@416
    87
#endif
ali@416
    88
		if (next == NULL)
ali@416
    89
			break;
ali@416
    90
ali@416
    91
		memcpy(p, slash, next - slash);
ali@416
    92
		p += next - slash;
ali@416
    93
		*p = '\0';
ali@416
    94
ali@416
    95
		if (razor_valid_root_name(buffer))
ali@416
    96
			continue;
ali@416
    97
ali@416
    98
		if (stat(buffer, &buf) == 0) {
ali@416
    99
			if (!S_ISDIR(buf.st_mode)) {
ali@416
   100
				razor_atomic_set_error_str(atomic, buffer,
ali@416
   101
							   "Not a directory");
ali@416
   102
				return -1;
ali@416
   103
			}
ali@416
   104
		} else if (mkdir(buffer, 0777) < 0) {
ali@416
   105
			razor_atomic_set_error_str(atomic, buffer,
ali@416
   106
						   strerror(errno));
ali@416
   107
			return -1;
ali@416
   108
		}
ali@416
   109
	}
ali@416
   110
ali@416
   111
	return 0;
ali@416
   112
}
ali@416
   113
ali@416
   114
RAZOR_EXPORT int
ali@416
   115
razor_atomic_remove(struct razor_atomic *atomic, const char *path)
ali@416
   116
{
ali@416
   117
#ifdef MSWIN_API
ali@416
   118
	wchar_t *buf;
ali@416
   119
	DWORD err;
ali@416
   120
#endif
ali@416
   121
ali@416
   122
	if (razor_atomic_in_error_state(atomic))
ali@416
   123
		return -1;
ali@416
   124
ali@416
   125
#ifdef MSWIN_API
ali@416
   126
	buf = razor_utf8_to_utf16(path, -1);
ali@416
   127
ali@416
   128
	if (!DeleteFileW(buf)) {
ali@416
   129
		err = GetLastError();
ali@416
   130
		if (err != ERROR_FILE_NOT_FOUND &&
ali@416
   131
		    err != ERROR_PATH_NOT_FOUND &&
ali@416
   132
		    !(SetFileAttributesW(buf, FILE_ATTRIBUTE_NORMAL) &&
ali@416
   133
		      DeleteFileW(buf)) &&
ali@416
   134
		    !RemoveDirectoryW(buf) &&
ali@416
   135
		    GetLastError() != ERROR_DIR_NOT_EMPTY)
ali@416
   136
			razor_atomic_set_error_mswin(atomic, buf, err);
ali@416
   137
	}
ali@416
   138
ali@416
   139
	free(buf);
ali@416
   140
#else
ali@416
   141
	if (remove(path))
ali@416
   142
		razor_atomic_set_error_str(atomic, path, strerror(errno));
ali@416
   143
#endif
ali@416
   144
ali@416
   145
	return !!atomic->error_str;
ali@416
   146
}
ali@416
   147
ali@416
   148
RAZOR_EXPORT int
ali@416
   149
razor_atomic_rename_file(struct razor_atomic *atomic, const char *oldpath,
ali@416
   150
			 const char *newpath)
ali@416
   151
{
ali@416
   152
#ifdef MSWIN_API
ali@416
   153
	wchar_t *oldbuf, *newbuf;
ali@416
   154
	const DWORD flags = MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING;
ali@416
   155
#endif
ali@416
   156
ali@416
   157
	if (razor_atomic_in_error_state(atomic))
ali@416
   158
		return -1;
ali@416
   159
ali@416
   160
#ifdef MSWIN_API
ali@416
   161
	newbuf = razor_utf8_to_utf16(newpath, -1);
ali@416
   162
	oldbuf = razor_utf8_to_utf16(oldpath, -1);
ali@416
   163
ali@416
   164
	/*
ali@416
   165
	 * Passing MOVEFILE_REPLACE_EXISTING to MoveFileEx() will
ali@416
   166
	 * cover every case we care about _except_ replacing an empty
ali@416
   167
	 * directory with a file. Calling RemoveDirectory() will deal
ali@416
   168
	 * with this case while having no effect in all other cases.
ali@416
   169
	 */
ali@416
   170
	(void)RemoveDirectoryW(newbuf);
ali@416
   171
ali@416
   172
	if (!MoveFileExW(oldbuf, newbuf, flags))
ali@416
   173
		razor_atomic_set_error_mswin(atomic, newbuf, GetLastError());
ali@416
   174
ali@416
   175
	free(newbuf);
ali@416
   176
	free(oldbuf);
ali@416
   177
#else
ali@416
   178
	if (rename(oldpath, newpath))
ali@416
   179
		razor_atomic_set_error_str(atomic, newpath, strerror(errno));
ali@416
   180
#endif
ali@416
   181
ali@416
   182
	return !!atomic->error_str;
ali@416
   183
}
ali@416
   184
ali@416
   185
RAZOR_EXPORT int
ali@416
   186
razor_atomic_create_dir(struct razor_atomic *atomic, const char *dirname,
ali@416
   187
			mode_t mode)
ali@416
   188
{
ali@416
   189
	if (razor_atomic_in_error_state(atomic))
ali@416
   190
		return -1;
ali@416
   191
ali@416
   192
	if (!mkdir(dirname, mode & (S_IRWXU | S_IRWXG | S_IRWXO)))
ali@416
   193
		return 0;
ali@416
   194
ali@416
   195
	if (errno != EEXIST) {
ali@416
   196
		razor_atomic_set_error_str(atomic, dirname, strerror(errno));
ali@416
   197
		return -1;
ali@416
   198
	}
ali@416
   199
ali@416
   200
	if (chmod(dirname, mode & (S_IRWXU | S_IRWXG | S_IRWXO)) < 0) {
ali@416
   201
		razor_atomic_set_error_str(atomic, dirname, strerror(errno));
ali@416
   202
		return -1;
ali@416
   203
	}
ali@416
   204
ali@416
   205
	return 0;
ali@416
   206
}
ali@416
   207
ali@416
   208
RAZOR_EXPORT int
ali@416
   209
razor_atomic_create_symlink(struct razor_atomic *atomic, const char *target,
ali@416
   210
			    const char *path)
ali@416
   211
{
ali@416
   212
	if (razor_atomic_in_error_state(atomic))
ali@416
   213
		return -1;
ali@416
   214
ali@416
   215
#if HAVE_SYMLINK
ali@416
   216
	if (symlink(target, path) < 0) {
ali@416
   217
		razor_atomic_set_error_str(atomic, NULL, strerror(errno));
ali@416
   218
		return -1;
ali@416
   219
	}
ali@416
   220
ali@416
   221
	return 0;
ali@416
   222
#else
ali@416
   223
	razor_atomic_set_error_str(atomic, NULL, "Symbolic links not supported "
ali@416
   224
						 "on this platform");
ali@416
   225
ali@416
   226
	return -1;
ali@416
   227
#endif
ali@416
   228
}
ali@416
   229
ali@416
   230
RAZOR_EXPORT int
ali@416
   231
razor_atomic_create_file(struct razor_atomic *atomic, const char *filename,
ali@416
   232
			 mode_t mode)
ali@416
   233
{
ali@416
   234
	int fd;
ali@416
   235
ali@416
   236
	if (razor_atomic_in_error_state(atomic))
ali@416
   237
		return -1;
ali@416
   238
ali@416
   239
	atomic->error_path = strdup(filename);
ali@416
   240
	fd = open(atomic->error_path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
ali@416
   241
		  mode & (S_IRWXU | S_IRWXG | S_IRWXO));
ali@416
   242
ali@416
   243
	if (fd == -1)
ali@416
   244
		razor_atomic_set_error_str(atomic, NULL, strerror(errno));
ali@416
   245
ali@416
   246
	return fd;
ali@416
   247
}
ali@416
   248
ali@416
   249
#endif	/* !ENABLE_ATOMIC */