Use Windows KTM (atomic transactions) where supported.
Increment current header version to 2
1.1 --- a/configure.ac Thu Aug 25 14:22:52 2011 +0100
1.2 +++ b/configure.ac Thu Nov 10 10:35:21 2011 +0000
1.3 @@ -1,7 +1,7 @@
1.4 dnl Process this file with autoconf to produce a configure script.
1.5
1.6 AC_PREREQ(2.59c)
1.7 -AC_INIT([razor], [0.4.1], [ali@juiblex.co.uk])
1.8 +AC_INIT([razor], [0.5], [ali@juiblex.co.uk])
1.9 AM_INIT_AUTOMAKE([])
1.10 AM_CONFIG_HEADER([config.h])
1.11 AM_MAINTAINER_MODE
1.12 @@ -10,8 +10,8 @@
1.13 #
1.14 # See http://sources.redhat.com/autobook/autobook/autobook_91.html#SEC91 for details
1.15 #
1.16 -LT_CURRENT=1
1.17 -LT_REVISION=2
1.18 +LT_CURRENT=2
1.19 +LT_REVISION=0
1.20 LT_AGE=0
1.21 AC_SUBST(LT_CURRENT)
1.22 AC_SUBST(LT_REVISION)
1.23 @@ -45,6 +45,25 @@
1.24 AM_CONDITIONAL(MSWIN_API, test "$mswin_api" = "yes")
1.25 AC_SUBST(EXTRA_LIBS)
1.26
1.27 +if test "$mswin_api" = "yes"; then
1.28 + AC_MSG_CHECKING([for Microsoft Windows Kernel Transaction Manager])
1.29 + save_LIBS="$LIBS"
1.30 + LIBS="-lktmw32 $LIBS"
1.31 + AC_LINK_IFELSE([AC_LANG_PROGRAM([dnl
1.32 +#include <windows.h>
1.33 +#include <ktmw32.h>
1.34 +], [(void)CreateTransaction(NULL,0,0,0,0,0,NULL);])],
1.35 + [have_windows_ktm="yes"; EXTRA_LIBS="-lktmw32 $EXTRA_LIBS"],
1.36 + [have_windows_ktm="no"])
1.37 + LIBS="$save_LIBS"
1.38 + AC_MSG_RESULT([$have_windows_ktm])
1.39 +else
1.40 + have_windows_ktm="no"
1.41 +fi
1.42 +if test "$have_windows_ktm" = "yes"; then
1.43 + AC_DEFINE([HAVE_WINDOWS_KTM],[1],[Define if Windows KTM is available.])
1.44 +fi
1.45 +
1.46 # Taken from dbus
1.47 AC_ARG_ENABLE(ansi, [ --enable-ansi enable -ansi -pedantic gcc flags],enable_ansi=$enableval,enable_ansi=no)
1.48 AC_ARG_ENABLE(verbose-mode, [ --enable-verbose-mode support verbose debug mode],enable_verbose_mode=$enableval,enable_verbose_mode=$USE_MAINTAINER_MODE)
2.1 --- a/librazor/Makefile.am Thu Aug 25 14:22:52 2011 +0100
2.2 +++ b/librazor/Makefile.am Thu Nov 10 10:35:21 2011 +0000
2.3 @@ -33,6 +33,7 @@
2.4 iterator.c \
2.5 importer.c \
2.6 merger.c \
2.7 + atomic.c \
2.8 transaction.c
2.9
2.10 if HAVE_LUA
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/librazor/atomic.c Thu Nov 10 10:35:21 2011 +0000
3.3 @@ -0,0 +1,1002 @@
3.4 +/*
3.5 + * Copyright (C) 2011 J. Ali Harlow <ali@juiblex.co.uk>
3.6 + *
3.7 + * This program is free software; you can redistribute it and/or modify
3.8 + * it under the terms of the GNU General Public License as published by
3.9 + * the Free Software Foundation; either version 2 of the License, or
3.10 + * (at your option) any later version.
3.11 + *
3.12 + * This program is distributed in the hope that it will be useful,
3.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3.15 + * GNU General Public License for more details.
3.16 + *
3.17 + * You should have received a copy of the GNU General Public License along
3.18 + * with this program; if not, write to the Free Software Foundation, Inc.,
3.19 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
3.20 + */
3.21 +
3.22 +#include "config.h"
3.23 +
3.24 +#include <stdlib.h>
3.25 +#ifdef MSWIN_API
3.26 +#include <windows.h>
3.27 +#endif
3.28 +#include <stdio.h>
3.29 +#include <limits.h>
3.30 +#include <errno.h>
3.31 +#include <unistd.h>
3.32 +#include <fcntl.h>
3.33 +#include <sys/stat.h>
3.34 +#include <string.h>
3.35 +#include <assert.h>
3.36 +#if HAVE_WINDOWS_KTM
3.37 +#include <wchar.h>
3.38 +#include <ktmw32.h>
3.39 +#endif
3.40 +
3.41 +#include "razor.h"
3.42 +#include "razor-internal.h"
3.43 +
3.44 +/*
3.45 + * Atomic transactions
3.46 + */
3.47 +
3.48 +#ifndef O_BINARY
3.49 +#define O_BINARY 0
3.50 +#endif
3.51 +
3.52 +#define RAZOR_ASCII_ISALPHA(c) \
3.53 + ((c) >= 'A' && (c) <= 'Z' || (c) >= 'a' && (c) <= 'z')
3.54 +
3.55 +static int allow_all_root_names = 0;
3.56 +
3.57 +/*
3.58 + * Primarily intended for testing named roots under UNIX platforms.
3.59 + */
3.60 +RAZOR_EXPORT void
3.61 +razor_disable_root_name_checks(int disable)
3.62 +{
3.63 + allow_all_root_names = disable;
3.64 +}
3.65 +
3.66 +#ifdef MSWIN_API
3.67 +
3.68 +static char *
3.69 +razor_utf16_to_utf8(const wchar_t *utf16, int len)
3.70 +{
3.71 + int n;
3.72 + char *utf8;
3.73 +
3.74 + n = WideCharToMultiByte(CP_UTF8, 0, utf16, len, NULL, 0, NULL, NULL);
3.75 + if (len >= 0 && utf16[len])
3.76 + n++;
3.77 + utf8 = malloc(n);
3.78 + (void)WideCharToMultiByte(CP_UTF8, 0, utf16, len, utf8, n, NULL, NULL);
3.79 + if (len >= 0 && utf16[len])
3.80 + utf8[n - 1] = 0;
3.81 +
3.82 + return utf8;
3.83 +}
3.84 +
3.85 +static wchar_t *
3.86 +razor_utf8_to_utf16(const char *utf8, int len)
3.87 +{
3.88 + int n;
3.89 + wchar_t *utf16;
3.90 +
3.91 + n = MultiByteToWideChar(CP_UTF8, 0, utf8, len, NULL, 0);
3.92 + if (len >= 0 && utf8[len])
3.93 + n++;
3.94 + utf16 = malloc(n * sizeof(wchar_t));
3.95 + (void)MultiByteToWideChar(CP_UTF8, 0, utf8, len, utf16, n);
3.96 + if (len >= 0 && utf8[len])
3.97 + utf16[n - 1] = 0;
3.98 +
3.99 + return utf16;
3.100 +}
3.101 +
3.102 +#endif /* MSWIN_API */
3.103 +
3.104 +#if HAVE_WINDOWS_KTM
3.105 +
3.106 +static int
3.107 +razor_valid_root_name(const wchar_t *name)
3.108 +{
3.109 + if (allow_all_root_names)
3.110 + return !wcschr(name, '/');
3.111 +
3.112 + return RAZOR_ASCII_ISALPHA(name[0]) && name[1] == ':' &&
3.113 + name[2] == '\0';
3.114 +}
3.115 +
3.116 +struct razor_atomic {
3.117 + HANDLE transaction;
3.118 + int n_files;
3.119 + struct razor_atomic_file {
3.120 + wchar_t *path;
3.121 + HANDLE h;
3.122 + } *files;
3.123 + char *error_path;
3.124 + char *error_str;
3.125 + char *error_msg;
3.126 +};
3.127 +
3.128 +struct razor_wstr {
3.129 + wchar_t *str;
3.130 + int len, allocated;
3.131 +};
3.132 +
3.133 +static struct razor_wstr *
3.134 +razor_wstr_create(const char *init, int len)
3.135 +{
3.136 + int n;
3.137 + struct razor_wstr *wstr;
3.138 +
3.139 + wstr = malloc(sizeof(struct razor_wstr));
3.140 +
3.141 + n = MultiByteToWideChar(CP_UTF8, 0, init, len, NULL, 0);
3.142 + if (len >= 0 && init[len])
3.143 + wstr->len = n++;
3.144 + else
3.145 + wstr->len = n - 1;
3.146 +
3.147 + wstr->allocated = n * 2;
3.148 + wstr->str = malloc(wstr->allocated * sizeof(wchar_t));
3.149 + if (!wstr->str) {
3.150 + free(wstr);
3.151 + return NULL;
3.152 + }
3.153 +
3.154 + (void)MultiByteToWideChar(CP_UTF8, 0, init, len, wstr->str, n);
3.155 + if (len >= 0 && init[len])
3.156 + wstr->str[wstr->len] = 0;
3.157 +
3.158 + return wstr;
3.159 +}
3.160 +
3.161 +static int
3.162 +razor_wstr_append(struct razor_wstr *wstr, const char *s, int len)
3.163 +{
3.164 + int n, allocated;
3.165 + wchar_t *str;
3.166 +
3.167 + n = MultiByteToWideChar(CP_UTF8, 0, s, len, NULL, 0);
3.168 + if (len < 0 || !s[len])
3.169 + n--;
3.170 +
3.171 + if (wstr->allocated <= wstr->len + n) {
3.172 + allocated = (wstr->len + n + 1) * 2;
3.173 + str = realloc(wstr->str, allocated * sizeof(wchar_t));
3.174 + if (!str)
3.175 + return -1;
3.176 + wstr->allocated = allocated;
3.177 + wstr->str = str;
3.178 + }
3.179 +
3.180 + (void)MultiByteToWideChar(CP_UTF8, 0, s, len, wstr->str + wstr->len, n);
3.181 + wstr->len += n;
3.182 + wstr->str[wstr->len] = 0;
3.183 +
3.184 + return 0;
3.185 +}
3.186 +
3.187 +static void
3.188 +razor_wstr_destroy(struct razor_wstr *wstr)
3.189 +{
3.190 + free(wstr->str);
3.191 + free(wstr);
3.192 +}
3.193 +
3.194 +RAZOR_EXPORT struct razor_atomic *
3.195 +razor_atomic_open(const char *description)
3.196 +{
3.197 + wchar_t *buf;
3.198 + struct razor_atomic *atomic;
3.199 +
3.200 + atomic = zalloc(sizeof *atomic);
3.201 + buf = razor_utf8_to_utf16(description, -1);
3.202 + atomic->transaction = CreateTransaction(NULL, 0,
3.203 + TRANSACTION_DO_NOT_PROMOTE,
3.204 + 0, 0, 0, buf);
3.205 + free(buf);
3.206 +
3.207 + return atomic;
3.208 +}
3.209 +
3.210 +static void
3.211 +razor_atomic_set_error_str(struct razor_atomic *atomic, const wchar_t *path,
3.212 + const char *str)
3.213 +{
3.214 + assert(!atomic->error_str);
3.215 +
3.216 + free(atomic->error_path);
3.217 +
3.218 + if (path)
3.219 + atomic->error_path = razor_utf16_to_utf8(path, -1);
3.220 + else
3.221 + atomic->error_path = NULL;
3.222 +
3.223 + atomic->error_str = strdup(str);
3.224 +}
3.225 +
3.226 +static void
3.227 +razor_atomic_set_error(struct razor_atomic *atomic, const wchar_t *path,
3.228 + DWORD error)
3.229 +{
3.230 + wchar_t *buf;
3.231 +
3.232 + assert(!atomic->error_str);
3.233 +
3.234 + free(atomic->error_path);
3.235 +
3.236 + if (path)
3.237 + atomic->error_path = razor_utf16_to_utf8(path, -1);
3.238 + else
3.239 + atomic->error_path = NULL;
3.240 +
3.241 + FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER|
3.242 + FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
3.243 + NULL, error, MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
3.244 + (LPWSTR)&buf, 0, NULL);
3.245 + atomic->error_str = razor_utf16_to_utf8(buf, -1);
3.246 + LocalFree(buf);
3.247 +}
3.248 +
3.249 +RAZOR_EXPORT int
3.250 +razor_atomic_commit(struct razor_atomic *atomic)
3.251 +{
3.252 + int retval;
3.253 +
3.254 + if (atomic->error_str)
3.255 + return -1;
3.256 +
3.257 + retval = !CommitTransaction(atomic->transaction);
3.258 +
3.259 + if (retval) {
3.260 + razor_atomic_set_error(atomic, NULL, GetLastError());
3.261 + RollbackTransaction(atomic->transaction);
3.262 + }
3.263 +
3.264 + CloseHandle(atomic->transaction);
3.265 + atomic->transaction = INVALID_HANDLE_VALUE;
3.266 +
3.267 + return retval;
3.268 +}
3.269 +
3.270 +RAZOR_EXPORT void
3.271 +razor_atomic_destroy(struct razor_atomic *atomic)
3.272 +{
3.273 + int i;
3.274 +
3.275 + for(i = 0; i < atomic->n_files; i++) {
3.276 + if (atomic->files[i].h != INVALID_HANDLE_VALUE) {
3.277 + CloseHandle(atomic->files[i].h);
3.278 + free(atomic->files[i].path);
3.279 + }
3.280 + }
3.281 + free(atomic->files);
3.282 + if (atomic->transaction != INVALID_HANDLE_VALUE) {
3.283 + RollbackTransaction(atomic->transaction);
3.284 + CloseHandle(atomic->transaction);
3.285 + }
3.286 + free(atomic->error_path);
3.287 + free(atomic->error_str);
3.288 + free(atomic->error_msg);
3.289 + free(atomic);
3.290 +}
3.291 +
3.292 +RAZOR_EXPORT int
3.293 +razor_atomic_make_dirs(struct razor_atomic *atomic, const char *root,
3.294 + const char *path)
3.295 +{
3.296 + struct razor_wstr *buffer;
3.297 + const char *slash, *s, *next;
3.298 + WIN32_FILE_ATTRIBUTE_DATA fa;
3.299 + DWORD err;
3.300 + int r, creating = 0;
3.301 +
3.302 + if (atomic->error_str)
3.303 + return -1;
3.304 +
3.305 + buffer = razor_wstr_create(root, -1);
3.306 + slash = path;
3.307 +
3.308 + for (; *slash != '\0'; slash = next) {
3.309 + next = strpbrk(slash + 1, "/\\");
3.310 + if (next == NULL)
3.311 + break;
3.312 +
3.313 + razor_wstr_append(buffer, slash, next - slash);
3.314 +
3.315 + if (!creating) {
3.316 + if (razor_valid_root_name(buffer->str))
3.317 + continue;
3.318 +
3.319 + r = GetFileAttributesTransactedW(buffer->str,
3.320 + GetFileExInfoStandard,
3.321 + &fa,
3.322 + atomic->transaction);
3.323 +
3.324 + if (!r) {
3.325 + err = GetLastError();
3.326 + if (err == ERROR_FILE_NOT_FOUND) {
3.327 + creating = 1;
3.328 + } else {
3.329 + razor_atomic_set_error(atomic,
3.330 + buffer->str,
3.331 + err);
3.332 + razor_wstr_destroy(buffer);
3.333 + return -1;
3.334 + }
3.335 + } else if (!(fa.dwFileAttributes&
3.336 + FILE_ATTRIBUTE_DIRECTORY)) {
3.337 + razor_atomic_set_error_str(atomic, buffer->str,
3.338 + "Not a directory");
3.339 + razor_wstr_destroy(buffer);
3.340 + return -1;
3.341 + }
3.342 + }
3.343 + if (creating) {
3.344 + if (!CreateDirectoryTransactedW(NULL, buffer->str, NULL,
3.345 + atomic->transaction)) {
3.346 + razor_atomic_set_error(atomic, buffer->str,
3.347 + GetLastError());
3.348 + razor_wstr_destroy(buffer);
3.349 + return -1;
3.350 + }
3.351 +
3.352 + /* FIXME: What to do about permissions for dirs we
3.353 + * have to create but are not in the cpio archive? */
3.354 + }
3.355 + }
3.356 +
3.357 + razor_wstr_destroy(buffer);
3.358 +
3.359 + return 0;
3.360 +}
3.361 +
3.362 +RAZOR_EXPORT int
3.363 +razor_atomic_remove(struct razor_atomic *atomic, const char *path)
3.364 +{
3.365 + wchar_t *buf;
3.366 + DWORD err;
3.367 +
3.368 + if (atomic->error_str)
3.369 + return -1;
3.370 +
3.371 + buf = razor_utf8_to_utf16(path, -1);
3.372 +
3.373 + if (DeleteFileTransactedW(buf, atomic->transaction)) {
3.374 + free(buf);
3.375 + return 0;
3.376 + }
3.377 +
3.378 + err = GetLastError();
3.379 + if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND) {
3.380 + free(buf);
3.381 + return 0;
3.382 + }
3.383 +
3.384 + if (SetFileAttributesTransactedW(buf, FILE_ATTRIBUTE_NORMAL,
3.385 + atomic->transaction)) {
3.386 + if (DeleteFileTransactedW(buf, atomic->transaction)) {
3.387 + free(buf);
3.388 + return 0;
3.389 + }
3.390 + err = GetLastError();
3.391 + }
3.392 +
3.393 + if (RemoveDirectoryTransactedW(buf, atomic->transaction) ||
3.394 + GetLastError() == ERROR_DIR_NOT_EMPTY) {
3.395 + free(buf);
3.396 + return 0;
3.397 + }
3.398 +
3.399 + /*
3.400 + * It would be tempting to use:
3.401 + * MoveFileEx(path, NULL, MOVEFILE_DELAY_UNTIL_REBOOT)
3.402 + * but unless we can guarantee that the system will be rebooted
3.403 + * before we (or some other application) write another file with the
3.404 + * same path, this is likely to cause more problems than it solves.
3.405 + */
3.406 +
3.407 + razor_atomic_set_error(atomic, buf, err);
3.408 + free(buf);
3.409 + return -1;
3.410 +}
3.411 +
3.412 +RAZOR_EXPORT int
3.413 +razor_atomic_rename_file(struct razor_atomic *atomic, const char *oldpath,
3.414 + const char *newpath)
3.415 +{
3.416 + wchar_t *oldbuf, *newbuf;
3.417 + const DWORD flags = MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING;
3.418 +
3.419 + if (atomic->error_str)
3.420 + return -1;
3.421 +
3.422 + newbuf = razor_utf8_to_utf16(newpath, -1);
3.423 + oldbuf = razor_utf8_to_utf16(oldpath, -1);
3.424 +
3.425 + /*
3.426 + * Passing MOVEFILE_REPLACE_EXISTING to MoveFileTransaction() will
3.427 + * cover every case we care about _except_ replacing an empty
3.428 + * directory with a file. Calling RemoveDirectoryTransacted() will deal
3.429 + * with this case while having no effect in all other cases.
3.430 + */
3.431 + (void)RemoveDirectoryTransactedW(newbuf, atomic->transaction);
3.432 +
3.433 + if (!MoveFileTransactedW(oldbuf, newbuf, NULL, NULL, flags,
3.434 + atomic->transaction))
3.435 + razor_atomic_set_error(atomic, newbuf, GetLastError());
3.436 +
3.437 + free(newbuf);
3.438 + free(oldbuf);
3.439 +
3.440 + return !!atomic->error_str;
3.441 +}
3.442 +
3.443 +RAZOR_EXPORT int
3.444 +razor_atomic_create_dir(struct razor_atomic *atomic, const char *dirname,
3.445 + mode_t mode)
3.446 +{
3.447 + wchar_t *buf;
3.448 + DWORD err;
3.449 + WIN32_FILE_ATTRIBUTE_DATA fa;
3.450 +
3.451 + if (atomic->error_str)
3.452 + return -1;
3.453 +
3.454 + buf = razor_utf8_to_utf16(dirname, -1);
3.455 +
3.456 + if (!CreateDirectoryTransactedW(NULL, buf, NULL, atomic->transaction)) {
3.457 + err = GetLastError();
3.458 + if (err != ERROR_FILE_EXISTS && err != ERROR_ALREADY_EXISTS) {
3.459 +abort:
3.460 + razor_atomic_set_error(atomic, buf, err);
3.461 + free(buf);
3.462 + return -1;
3.463 + }
3.464 +
3.465 + if (!GetFileAttributesTransactedW(buf, GetFileExInfoStandard,
3.466 + &fa, atomic->transaction))
3.467 + goto abort;
3.468 +
3.469 + if (!(fa.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)) {
3.470 + if (razor_atomic_remove(atomic, dirname)) {
3.471 + free(buf);
3.472 + return -1;
3.473 + }
3.474 + if (!CreateDirectoryTransactedW(NULL, buf, NULL,
3.475 + atomic->transaction)) {
3.476 + err = GetLastError();
3.477 + goto abort;
3.478 + }
3.479 + }
3.480 + }
3.481 +
3.482 + free(buf);
3.483 +
3.484 + return 0;
3.485 +}
3.486 +
3.487 +RAZOR_EXPORT int
3.488 +razor_atomic_create_symlink(struct razor_atomic *atomic, const char *target,
3.489 + const char *path)
3.490 +{
3.491 + if (atomic->error_str)
3.492 + return -1;
3.493 +
3.494 + /*
3.495 + * This isn't true, but symbolic links under Windows 7
3.496 + * need to know whether the target is a directory or not
3.497 + * and we don't always know that at the time when the
3.498 + * link is created, so it's a convienent lie for now.
3.499 + */
3.500 + razor_atomic_set_error_str(atomic, NULL, "Symbolic links not supported "
3.501 + "on this platform");
3.502 +
3.503 + return -1;
3.504 +}
3.505 +
3.506 +RAZOR_EXPORT int
3.507 +razor_atomic_create_file(struct razor_atomic *atomic, const char *filename,
3.508 + mode_t mode)
3.509 +{
3.510 + DWORD attribs;
3.511 + struct razor_atomic_file *files;
3.512 + int i = atomic->n_files;
3.513 +
3.514 + if (atomic->error_str)
3.515 + return -1;
3.516 +
3.517 + files = realloc(atomic->files,
3.518 + (atomic->n_files+1) * sizeof(struct razor_atomic_file));
3.519 + if (!files) {
3.520 + razor_atomic_set_error_str(atomic, NULL, "Not enough memory");
3.521 + return -1;
3.522 + }
3.523 + atomic->n_files++;
3.524 + atomic->files = files;
3.525 +
3.526 + files[i].path = razor_utf8_to_utf16(filename, -1);
3.527 +
3.528 + /*
3.529 + * Passing CREATE_ALWAYS to CreateFileTransacted() will cover
3.530 + * every case we care about _except_ replacing an empty directory
3.531 + * with a file. Calling RemoveDirectoryTransacted() will deal
3.532 + * with this case while having no effect in all other cases.
3.533 + */
3.534 + (void)RemoveDirectoryTransactedW(files[i].path, atomic->transaction);
3.535 +
3.536 + if (mode & S_IWUSR)
3.537 + attribs = FILE_ATTRIBUTE_NORMAL;
3.538 + else
3.539 + attribs = FILE_ATTRIBUTE_READONLY;
3.540 +
3.541 + files[i].h = CreateFileTransactedW(files[i].path, GENERIC_WRITE,
3.542 + 0, NULL, CREATE_ALWAYS, attribs,
3.543 + NULL, atomic->transaction, NULL,
3.544 + NULL);
3.545 +
3.546 + if (files[i].h == INVALID_HANDLE_VALUE) {
3.547 + razor_atomic_set_error(atomic, files[i].path, GetLastError());
3.548 + free(files[i].path);
3.549 + atomic->n_files--;
3.550 + return -1;
3.551 + }
3.552 +
3.553 + return i;
3.554 +}
3.555 +
3.556 +RAZOR_EXPORT int
3.557 +razor_atomic_write(struct razor_atomic *atomic, int handle, const void *data,
3.558 + size_t size)
3.559 +{
3.560 + DWORD written;
3.561 +
3.562 + if (atomic->error_str)
3.563 + return -1;
3.564 +
3.565 + assert(handle < atomic->n_files);
3.566 + assert(atomic->files[handle].h != INVALID_HANDLE_VALUE);
3.567 +
3.568 + while(size) {
3.569 + if (!WriteFile(atomic->files[handle].h, data, size, &written,
3.570 + NULL)) {
3.571 + razor_atomic_set_error(atomic,
3.572 + atomic->files[handle].path,
3.573 + GetLastError());
3.574 +
3.575 + (void)CloseHandle(atomic->files[handle].h);
3.576 + free(atomic->files[handle].path);
3.577 + atomic->files[handle].path = NULL;
3.578 + atomic->files[handle].h = INVALID_HANDLE_VALUE;
3.579 +
3.580 + return -1;
3.581 + }
3.582 +
3.583 + data += written;
3.584 + size -= written;
3.585 + }
3.586 +
3.587 + return 0;
3.588 +}
3.589 +
3.590 +RAZOR_EXPORT int
3.591 +razor_atomic_sync(struct razor_atomic *atomic, int handle)
3.592 +{
3.593 + HANDLE h;
3.594 +
3.595 + if (atomic->error_str)
3.596 + return -1;
3.597 +
3.598 + assert(handle < atomic->n_files);
3.599 + assert(atomic->files[handle].h != INVALID_HANDLE_VALUE);
3.600 +
3.601 + if (!CloseHandle(atomic->files[handle].h)) {
3.602 + razor_atomic_set_error(atomic, atomic->files[handle].path,
3.603 + GetLastError());
3.604 + free(atomic->files[handle].path);
3.605 + atomic->files[handle].path = NULL;
3.606 + atomic->files[handle].h = INVALID_HANDLE_VALUE;
3.607 + return -1;
3.608 + }
3.609 +
3.610 + h = CreateFileTransactedW(atomic->files[handle].path, GENERIC_WRITE, 0,
3.611 + NULL, OPEN_EXISTING, 0, NULL,
3.612 + atomic->transaction, NULL, NULL);
3.613 + atomic->files[handle].h = h;
3.614 +
3.615 + if (atomic->files[handle].h == INVALID_HANDLE_VALUE) {
3.616 + razor_atomic_set_error(atomic, atomic->files[handle].path,
3.617 + GetLastError());
3.618 + free(atomic->files[handle].path);
3.619 + atomic->files[handle].path = NULL;
3.620 + return -1;
3.621 + }
3.622 +
3.623 + return !!atomic->error_str;
3.624 +}
3.625 +
3.626 +RAZOR_EXPORT int
3.627 +razor_atomic_close(struct razor_atomic *atomic, int handle)
3.628 +{
3.629 + if (atomic->error_str)
3.630 + return -1;
3.631 +
3.632 + assert(handle < atomic->n_files);
3.633 + assert(atomic->files[handle].h != INVALID_HANDLE_VALUE);
3.634 +
3.635 + if (!CloseHandle(atomic->files[handle].h))
3.636 + razor_atomic_set_error(atomic, atomic->files[handle].path,
3.637 + GetLastError());
3.638 +
3.639 + free(atomic->files[handle].path);
3.640 + atomic->files[handle].path = NULL;
3.641 + atomic->files[handle].h = INVALID_HANDLE_VALUE;
3.642 +
3.643 + while(atomic->n_files > 0 &&
3.644 + atomic->files[atomic->n_files-1].h == INVALID_HANDLE_VALUE)
3.645 + atomic->n_files--;
3.646 +
3.647 + return !!atomic->error_str;
3.648 +}
3.649 +
3.650 +#else /* HAVE_WINDOWS_KVM */
3.651 +
3.652 +static int
3.653 +razor_valid_root_name(const char *name)
3.654 +{
3.655 + if (allow_all_root_names) {
3.656 +#ifdef MSWIN_API
3.657 + return !strpbrk(name, "/\\");
3.658 +#else
3.659 + return !strchr(name, '/');
3.660 +#endif
3.661 + }
3.662 +
3.663 +#ifdef MSWIN_API
3.664 + return RAZOR_ASCII_ISALPHA(name[0]) && name[1] == ':' &&
3.665 + name[2] == '\0';
3.666 +#else
3.667 + return name[0] == '\0';
3.668 +#endif
3.669 +}
3.670 +
3.671 +struct razor_atomic {
3.672 + char *error_path;
3.673 + char *error_str;
3.674 + char *error_msg;
3.675 +};
3.676 +
3.677 +RAZOR_EXPORT struct razor_atomic *
3.678 +razor_atomic_open(const char *description)
3.679 +{
3.680 + struct razor_atomic *atomic;
3.681 +
3.682 + atomic = zalloc(sizeof *atomic);
3.683 +
3.684 + return atomic;
3.685 +}
3.686 +
3.687 +static void
3.688 +razor_atomic_set_error_str(struct razor_atomic *atomic, const char *path,
3.689 + const char *str)
3.690 +{
3.691 + assert(!atomic->error_str);
3.692 +
3.693 + atomic->error_path = path ? strdup(path) : NULL;
3.694 + atomic->error_str = strdup(str);
3.695 +}
3.696 +
3.697 +#ifdef MSWIN_API
3.698 +static void
3.699 +razor_atomic_set_error_mswin(struct razor_atomic *atomic, const wchar_t *path,
3.700 + DWORD error)
3.701 +{
3.702 + wchar_t *buf;
3.703 +
3.704 + assert(!atomic->error_str);
3.705 +
3.706 + free(atomic->error_path);
3.707 +
3.708 + if (path)
3.709 + atomic->error_path = razor_utf16_to_utf8(path, -1);
3.710 + else
3.711 + atomic->error_path = NULL;
3.712 +
3.713 + FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER|
3.714 + FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
3.715 + NULL, error, MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
3.716 + (LPWSTR)&buf, 0, NULL);
3.717 + atomic->error_str = razor_utf16_to_utf8(buf, -1);
3.718 + LocalFree(buf);
3.719 +}
3.720 +#endif
3.721 +
3.722 +RAZOR_EXPORT int
3.723 +razor_atomic_commit(struct razor_atomic *atomic)
3.724 +{
3.725 + return !!atomic->error_str;
3.726 +}
3.727 +
3.728 +RAZOR_EXPORT void
3.729 +razor_atomic_destroy(struct razor_atomic *atomic)
3.730 +{
3.731 + free(atomic->error_path);
3.732 + free(atomic->error_str);
3.733 + free(atomic->error_msg);
3.734 + free(atomic);
3.735 +}
3.736 +
3.737 +RAZOR_EXPORT int
3.738 +razor_atomic_make_dirs(struct razor_atomic *atomic, const char *root,
3.739 + const char *path)
3.740 +{
3.741 + char buffer[PATH_MAX], *p;
3.742 + const char *slash, *next;
3.743 + struct stat buf;
3.744 +
3.745 + if (atomic->error_str)
3.746 + return -1;
3.747 +
3.748 + strcpy(buffer, root);
3.749 + p = buffer + strlen(buffer);
3.750 + slash = path;
3.751 + for (slash = path; *slash != '\0'; slash = next) {
3.752 +#ifdef MSWIN_API
3.753 + next = strpbrk(slash + 1, "/\\");
3.754 +#else
3.755 + next = strchr(slash + 1, '/');
3.756 +#endif
3.757 + if (next == NULL)
3.758 + break;
3.759 +
3.760 + memcpy(p, slash, next - slash);
3.761 + p += next - slash;
3.762 + *p = '\0';
3.763 +
3.764 + if (razor_valid_root_name(buffer))
3.765 + continue;
3.766 +
3.767 + if (stat(buffer, &buf) == 0) {
3.768 + if (!S_ISDIR(buf.st_mode)) {
3.769 + razor_atomic_set_error_str(atomic, buffer,
3.770 + "Not a directory");
3.771 + return -1;
3.772 + }
3.773 + } else if (mkdir(buffer, 0777) < 0) {
3.774 + razor_atomic_set_error_str(atomic, buffer,
3.775 + strerror(errno));
3.776 + return -1;
3.777 + }
3.778 + }
3.779 +
3.780 + return 0;
3.781 +}
3.782 +
3.783 +RAZOR_EXPORT int
3.784 +razor_atomic_remove(struct razor_atomic *atomic, const char *path)
3.785 +{
3.786 +#ifdef MSWIN_API
3.787 + wchar_t *buf;
3.788 + DWORD err;
3.789 +#endif
3.790 +
3.791 + if (atomic->error_str)
3.792 + return -1;
3.793 +
3.794 +#ifdef MSWIN_API
3.795 + buf = razor_utf8_to_utf16(path, -1);
3.796 +
3.797 + if (!DeleteFileW(buf)) {
3.798 + err = GetLastError();
3.799 + if (err != ERROR_FILE_NOT_FOUND &&
3.800 + err != ERROR_PATH_NOT_FOUND &&
3.801 + !(SetFileAttributesW(buf, FILE_ATTRIBUTE_NORMAL) &&
3.802 + DeleteFileW(buf)) &&
3.803 + !RemoveDirectoryW(buf) &&
3.804 + GetLastError() != ERROR_DIR_NOT_EMPTY)
3.805 + razor_atomic_set_error_mswin(atomic, buf, err);
3.806 + }
3.807 +
3.808 + free(buf);
3.809 +#else
3.810 + if (remove(path))
3.811 + razor_atomic_set_error_str(atomic, path, strerror(errno));
3.812 +#endif
3.813 +
3.814 + return !!atomic->error_str;
3.815 +}
3.816 +
3.817 +RAZOR_EXPORT int
3.818 +razor_atomic_rename_file(struct razor_atomic *atomic, const char *oldpath,
3.819 + const char *newpath)
3.820 +{
3.821 +#ifdef MSWIN_API
3.822 + wchar_t *oldbuf, *newbuf;
3.823 + const DWORD flags = MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING;
3.824 +#endif
3.825 +
3.826 + if (atomic->error_str)
3.827 + return -1;
3.828 +
3.829 +#ifdef MSWIN_API
3.830 + newbuf = razor_utf8_to_utf16(newpath, -1);
3.831 + oldbuf = razor_utf8_to_utf16(oldpath, -1);
3.832 +
3.833 + /*
3.834 + * Passing MOVEFILE_REPLACE_EXISTING to MoveFileEx() will
3.835 + * cover every case we care about _except_ replacing an empty
3.836 + * directory with a file. Calling RemoveDirectory() will deal
3.837 + * with this case while having no effect in all other cases.
3.838 + */
3.839 + (void)RemoveDirectoryW(newbuf);
3.840 +
3.841 + if (!MoveFileExW(oldbuf, newbuf, flags))
3.842 + razor_atomic_set_error_mswin(atomic, newbuf, GetLastError());
3.843 +
3.844 + free(newbuf);
3.845 + free(oldbuf);
3.846 +#else
3.847 + if (rename(oldpath, newpath))
3.848 + razor_atomic_set_error_str(atomic, newpath, strerror(errno));
3.849 +#endif
3.850 +
3.851 + return !!atomic->error_str;
3.852 +}
3.853 +
3.854 +RAZOR_EXPORT int
3.855 +razor_atomic_create_dir(struct razor_atomic *atomic, const char *dirname,
3.856 + mode_t mode)
3.857 +{
3.858 + if (atomic->error_str)
3.859 + return -1;
3.860 +
3.861 + if (!mkdir(dirname, mode & (S_IRWXU | S_IRWXG | S_IRWXO)))
3.862 + return 0;
3.863 +
3.864 + if (errno != EEXIST) {
3.865 + razor_atomic_set_error_str(atomic, dirname, strerror(errno));
3.866 + return -1;
3.867 + }
3.868 +
3.869 + if (chmod(dirname, mode & (S_IRWXU | S_IRWXG | S_IRWXO)) < 0) {
3.870 + razor_atomic_set_error_str(atomic, dirname, strerror(errno));
3.871 + return -1;
3.872 + }
3.873 +
3.874 + return 0;
3.875 +}
3.876 +
3.877 +RAZOR_EXPORT int
3.878 +razor_atomic_create_symlink(struct razor_atomic *atomic, const char *target,
3.879 + const char *path)
3.880 +{
3.881 + if (atomic->error_str)
3.882 + return -1;
3.883 +
3.884 +#if HAVE_SYMLINK
3.885 + if (symlink(target, path) < 0) {
3.886 + razor_atomic_set_error_str(atomic, NULL, strerror(errno));
3.887 + return -1;
3.888 + }
3.889 +#else
3.890 + razor_atomic_set_error_str(atomic, NULL, "Symbolic links not supported "
3.891 + "on this platform");
3.892 +#endif
3.893 +
3.894 + return 0;
3.895 +}
3.896 +
3.897 +RAZOR_EXPORT int
3.898 +razor_atomic_create_file(struct razor_atomic *atomic, const char *filename,
3.899 + mode_t mode)
3.900 +{
3.901 + int fd;
3.902 +
3.903 + if (atomic->error_str)
3.904 + return -1;
3.905 +
3.906 + atomic->error_path = strdup(filename);
3.907 + fd = open(atomic->error_path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
3.908 + mode & (S_IRWXU | S_IRWXG | S_IRWXO));
3.909 +
3.910 + if (fd == -1)
3.911 + razor_atomic_set_error_str(atomic, NULL, strerror(errno));
3.912 +
3.913 + return fd;
3.914 +}
3.915 +
3.916 +RAZOR_EXPORT int
3.917 +razor_atomic_write(struct razor_atomic *atomic, int fd, const void *data,
3.918 + size_t size)
3.919 +{
3.920 + int written;
3.921 +
3.922 + if (atomic->error_str)
3.923 + return -1;
3.924 +
3.925 + while(size) {
3.926 + written = write(fd, data, size);
3.927 + if (written < 0) {
3.928 + razor_atomic_set_error_str(atomic, NULL, strerror(errno));
3.929 +
3.930 + (void)close(fd);
3.931 +
3.932 + return -1;
3.933 + }
3.934 +
3.935 + data += written;
3.936 + size -= written;
3.937 + }
3.938 +
3.939 + return 0;
3.940 +}
3.941 +
3.942 +RAZOR_EXPORT int
3.943 +razor_atomic_sync(struct razor_atomic *atomic, int handle)
3.944 +{
3.945 + if (atomic->error_str)
3.946 + return -1;
3.947 +
3.948 + if (fsync(handle) < 0) {
3.949 + razor_atomic_set_error_str(atomic, NULL, strerror(errno));
3.950 + return -1;
3.951 + }
3.952 +
3.953 + free(atomic->error_path);
3.954 + atomic->error_path = NULL;
3.955 +
3.956 + return 0;
3.957 +}
3.958 +
3.959 +RAZOR_EXPORT int
3.960 +razor_atomic_close(struct razor_atomic *atomic, int fd)
3.961 +{
3.962 + if (atomic->error_str)
3.963 + return -1;
3.964 +
3.965 + if (close(fd) < 0) {
3.966 + razor_atomic_set_error_str(atomic, NULL, strerror(errno));
3.967 + return -1;
3.968 + }
3.969 +
3.970 + free(atomic->error_path);
3.971 + atomic->error_path = NULL;
3.972 +
3.973 + return 0;
3.974 +}
3.975 +
3.976 +#endif /* HAVE_WINDOWS_KVM */
3.977 +
3.978 +RAZOR_EXPORT const char *
3.979 +razor_atomic_get_error_msg(struct razor_atomic *atomic)
3.980 +{
3.981 + if (!atomic->error_msg) {
3.982 + if (atomic->error_path)
3.983 + atomic->error_msg = razor_concat(atomic->error_path,
3.984 + ": ",
3.985 + atomic->error_str,
3.986 + NULL);
3.987 + else
3.988 + atomic->error_msg = strdup(atomic->error_str);
3.989 + }
3.990 +
3.991 + return atomic->error_msg;
3.992 +}
3.993 +
3.994 +RAZOR_EXPORT void
3.995 +razor_atomic_abort(struct razor_atomic *atomic, const char *error_msg)
3.996 +{
3.997 + if (!atomic->error_str)
3.998 + razor_atomic_set_error_str(atomic, NULL, error_msg);
3.999 +}
3.1000 +
3.1001 +RAZOR_EXPORT int
3.1002 +razor_atomic_in_error_state(struct razor_atomic *atomic)
3.1003 +{
3.1004 + return !!atomic->error_str;
3.1005 +}
4.1 --- a/librazor/merger.c Thu Aug 25 14:22:52 2011 +0100
4.2 +++ b/librazor/merger.c Thu Nov 10 10:35:21 2011 +0000
4.3 @@ -1,7 +1,7 @@
4.4 /*
4.5 * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
4.6 * Copyright (C) 2008 Red Hat, Inc
4.7 - * Copyright (C) 2009, 2010 J. Ali Harlow <ali@juiblex.co.uk>
4.8 + * Copyright (C) 2009-2011 J. Ali Harlow <ali@juiblex.co.uk>
4.9 *
4.10 * This program is free software; you can redistribute it and/or modify
4.11 * it under the terms of the GNU General Public License as published by
4.12 @@ -47,9 +47,18 @@
4.13 struct razor_merger *merger;
4.14 int count;
4.15 size_t size;
4.16 + uint32_t header_version;
4.17
4.18 merger = zalloc(sizeof *merger);
4.19 merger->set = razor_set_create();
4.20 + if (set1->packages.size) {
4.21 + header_version = razor_set_get_header_version(set1);
4.22 + if (set2->packages.size &&
4.23 + razor_set_get_header_version(set2) > header_version)
4.24 + header_version = razor_set_get_header_version(set2);
4.25 + } else
4.26 + header_version = razor_set_get_header_version(set2);
4.27 + razor_set_set_header_version(merger->set, header_version);
4.28 hashtable_init(&merger->table, &merger->set->string_pool);
4.29 hashtable_init(&merger->file_table, &merger->set->file_string_pool);
4.30 hashtable_init(&merger->details_table,
4.31 @@ -592,16 +601,24 @@
4.32
4.33 switch (script) {
4.34 case RAZOR_PROPERTY_PREUN:
4.35 - assert(pool[package->preun.program] == '\0');
4.36 - assert(pool[package->preun.body] == '\0');
4.37 - package->preun.program = p;
4.38 - package->preun.body = b;
4.39 + if (package->preun.program != p) {
4.40 + assert(pool[package->preun.program] == '\0');
4.41 + package->preun.program = p;
4.42 + }
4.43 + if (package->preun.body != b) {
4.44 + assert(pool[package->preun.body] == '\0');
4.45 + package->preun.body = b;
4.46 + }
4.47 break;
4.48 case RAZOR_PROPERTY_POSTUN:
4.49 - assert(pool[package->postun.program] == '\0');
4.50 - assert(pool[package->postun.body] == '\0');
4.51 - package->postun.program = p;
4.52 - package->postun.body = b;
4.53 + if (package->postun.program != p) {
4.54 + assert(pool[package->postun.program] == '\0');
4.55 + package->postun.program = p;
4.56 + }
4.57 + if (package->postun.body != b) {
4.58 + assert(pool[package->postun.body] == '\0');
4.59 + package->postun.body = b;
4.60 + }
4.61 break;
4.62 default:
4.63 break;
5.1 --- a/librazor/razor-internal.h Thu Aug 25 14:22:52 2011 +0100
5.2 +++ b/librazor/razor-internal.h Thu Nov 10 10:35:21 2011 +0000
5.3 @@ -1,7 +1,7 @@
5.4 /*
5.5 * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
5.6 * Copyright (C) 2008 Red Hat, Inc
5.7 - * Copyright (C) 2009 J. Ali Harlow <ali@juiblex.co.uk>
5.8 + * Copyright (C) 2009, 2011 J. Ali Harlow <ali@juiblex.co.uk>
5.9 *
5.10 * This program is free software; you can redistribute it and/or modify
5.11 * it under the terms of the GNU General Public License as published by
5.12 @@ -29,7 +29,7 @@
5.13 #include "razor.h"
5.14 #include "types/types.h"
5.15
5.16 -/* GCC visibility */
5.17 +/* GCC extensions */
5.18 #if defined(__GNUC__) && __GNUC__ >= 4
5.19 #define RAZOR_EXPORT __attribute__ ((visibility("default")))
5.20 #else
5.21 @@ -54,7 +54,6 @@
5.22 };
5.23
5.24 #define RAZOR_MAGIC 0x525a4442
5.25 -#define RAZOR_VERSION 1
5.26
5.27 #define RAZOR_STRING_POOL "string_pool"
5.28 #define RAZOR_PACKAGES "packages"
5.29 @@ -108,6 +107,7 @@
5.30 #define RAZOR_ENTRY_LAST 0x80
5.31
5.32 struct razor_set {
5.33 + uint32_t header_version;
5.34 struct array string_pool;
5.35 struct array packages;
5.36 struct array properties;
5.37 @@ -119,7 +119,7 @@
5.38 struct array file_string_pool;
5.39 struct array details_string_pool;
5.40 struct razor_mapped_file *mapped_files;
5.41 - int lock_fd;
5.42 + int lock_fd, ref_count;
5.43 };
5.44
5.45 struct import_entry {
6.1 --- a/librazor/razor.c Thu Aug 25 14:22:52 2011 +0100
6.2 +++ b/librazor/razor.c Thu Nov 10 10:35:21 2011 +0000
6.3 @@ -1,7 +1,7 @@
6.4 /*
6.5 * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
6.6 * Copyright (C) 2008 Red Hat, Inc
6.7 - * Copyright (C) 2009, 2010 J. Ali Harlow <ali@juiblex.co.uk>
6.8 + * Copyright (C) 2009-2011 J. Ali Harlow <ali@juiblex.co.uk>
6.9 *
6.10 * This program is free software; you can redistribute it and/or modify
6.11 * it under the terms of the GNU General Public License as published by
6.12 @@ -93,10 +93,16 @@
6.13
6.14 set = zalloc(sizeof *set);
6.15
6.16 - empty = array_add(&set->string_pool, 1);
6.17 - *empty = '\0';
6.18 + if (set) {
6.19 + empty = array_add(&set->string_pool, 1);
6.20 + *empty = '\0';
6.21
6.22 - set->lock_fd = -1;
6.23 + set->lock_fd = -1;
6.24 +
6.25 + set->ref_count = 1;
6.26 +
6.27 + set->header_version = RAZOR_HEADER_VERSION;
6.28 + }
6.29
6.30 return set;
6.31 }
6.32 @@ -118,6 +124,24 @@
6.33 return set;
6.34 }
6.35
6.36 +RAZOR_EXPORT uint32_t
6.37 +razor_set_get_header_version(struct razor_set *set)
6.38 +{
6.39 + return set->header_version;
6.40 +}
6.41 +
6.42 +RAZOR_EXPORT int
6.43 +razor_set_set_header_version(struct razor_set *set, uint32_t header_version)
6.44 +{
6.45 + if (header_version<RAZOR_HEADER_VERSION_MIN ||
6.46 + header_version>RAZOR_HEADER_VERSION)
6.47 + return -1;
6.48 + else {
6.49 + set->header_version = header_version;
6.50 + return 0;
6.51 + }
6.52 +}
6.53 +
6.54 struct razor_mapped_file {
6.55 struct razor_set_header *header;
6.56 size_t size;
6.57 @@ -125,32 +149,52 @@
6.58 };
6.59
6.60 RAZOR_EXPORT int
6.61 -razor_set_bind_sections(struct razor_set *set, const char *filename)
6.62 +razor_set_bind_sections(struct razor_set *set, struct razor_atomic *atomic,
6.63 + const char *filename)
6.64 {
6.65 struct razor_set_section *s, *sections;
6.66 struct razor_mapped_file *file;
6.67 - const char *pool;
6.68 + const char *pool, *reason;
6.69 + char *msg;
6.70 struct array *array;
6.71 int i, j;
6.72
6.73 file = zalloc(sizeof *file);
6.74 - if (file == NULL)
6.75 + if (file == NULL) {
6.76 + razor_atomic_abort(atomic, "Not enough memory");
6.77 return -1;
6.78 + }
6.79
6.80 file->header = razor_file_get_contents(filename, &file->size);
6.81 if (!file->header) {
6.82 + msg = razor_concat(filename, ": ", strerror(errno), NULL);
6.83 + razor_atomic_abort(atomic, msg);
6.84 + free(msg);
6.85 free(file);
6.86 return -1;
6.87 }
6.88
6.89 - if (file->size < sizeof *file->header ||
6.90 - file->header->magic != RAZOR_MAGIC ||
6.91 - file->header->version != RAZOR_VERSION) {
6.92 + if (file->size < sizeof *file->header)
6.93 + reason = "Premature EOF";
6.94 + else if (file->header->magic != RAZOR_MAGIC)
6.95 + reason = "Bad magic number";
6.96 + else if (file->header->version < RAZOR_HEADER_VERSION_MIN ||
6.97 + file->header->version > RAZOR_HEADER_VERSION)
6.98 + reason = "Incompatible file version";
6.99 + else
6.100 + reason = NULL;
6.101 +
6.102 + if (reason) {
6.103 + msg = razor_concat(filename, ": ", reason, NULL);
6.104 + razor_atomic_abort(atomic, msg);
6.105 + free(msg);
6.106 razor_file_free_contents(file->header, file->size);
6.107 free(file);
6.108 return -1;
6.109 }
6.110
6.111 + set->header_version = file->header->version;
6.112 +
6.113 if (set->mapped_files == NULL) {
6.114 for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
6.115 array = (void *) set + razor_sections[i].offset;
6.116 @@ -182,13 +226,18 @@
6.117 }
6.118
6.119 RAZOR_EXPORT struct razor_set *
6.120 -razor_set_open(const char *filename)
6.121 +razor_set_open(const char *filename, struct razor_atomic *atomic)
6.122 {
6.123 struct razor_set *set;
6.124
6.125 set = zalloc(sizeof *set);
6.126 + if (!set) {
6.127 + razor_atomic_abort(atomic, "Not enough memory");
6.128 + return NULL;
6.129 + }
6.130 +
6.131 set->lock_fd = -1;
6.132 - if (razor_set_bind_sections(set, filename)){
6.133 + if (razor_set_bind_sections(set, atomic, filename)) {
6.134 free(set);
6.135 return NULL;
6.136 }
6.137 @@ -215,12 +264,14 @@
6.138
6.139 if (exclusive)
6.140 flags |= LOCKFILE_EXCLUSIVE_LOCK;
6.141 - if (fd >= 0 && !LockFileEx(_get_osfhandle(fd), flags, 0, 1, 0, &lock)) {
6.142 + if (fd >= 0 && !LockFileEx((HANDLE)_get_osfhandle(fd), flags, 0, 1, 0,
6.143 + &lock)) {
6.144 close(fd);
6.145 return -1;
6.146 }
6.147 if (set->lock_fd >= 0)
6.148 - (void)UnlockFile(_get_osfhandle(set->lock_fd), 0, 0, 1, 0);
6.149 + (void)UnlockFile((HANDLE)_get_osfhandle(set->lock_fd), 0, 0, 1,
6.150 + 0);
6.151 #else
6.152 struct flock lock = {0};
6.153
6.154 @@ -245,7 +296,7 @@
6.155 return 0;
6.156 }
6.157
6.158 -RAZOR_EXPORT void
6.159 +static void
6.160 razor_set_destroy(struct razor_set *set)
6.161 {
6.162 struct razor_mapped_file *file, *next;
6.163 @@ -271,8 +322,24 @@
6.164 free(set);
6.165 }
6.166
6.167 -RAZOR_EXPORT int
6.168 -razor_set_write_to_fd(struct razor_set *set, int fd, uint32_t section_mask)
6.169 +RAZOR_EXPORT void
6.170 +razor_set_unref(struct razor_set *set)
6.171 +{
6.172 + if (set && !--set->ref_count)
6.173 + razor_set_destroy(set);
6.174 +}
6.175 +
6.176 +RAZOR_EXPORT struct razor_set *
6.177 +razor_set_ref(struct razor_set *set)
6.178 +{
6.179 + if (set)
6.180 + set->ref_count++;
6.181 + return set;
6.182 +}
6.183 +
6.184 +RAZOR_EXPORT void
6.185 +razor_set_write_to_handle(struct razor_set *set, struct razor_atomic *atomic,
6.186 + int handle, uint32_t section_mask)
6.187 {
6.188 struct razor_set_header header;
6.189 struct razor_set_section sections[ARRAY_SIZE(razor_sections)];
6.190 @@ -298,7 +365,7 @@
6.191
6.192 count = j;
6.193 header.magic = RAZOR_MAGIC;
6.194 - header.version = RAZOR_VERSION;
6.195 + header.version = set->header_version;
6.196 header.num_sections = count;
6.197 offset = sizeof header + count * sizeof *sections + ALIGN(pool.size, 4);
6.198
6.199 @@ -308,38 +375,36 @@
6.200 offset += ALIGN(arrays[i]->size, 4);
6.201 }
6.202
6.203 - razor_write(fd, &header, sizeof header);
6.204 - razor_write(fd, sections, count * sizeof *sections);
6.205 - razor_write(fd, pool.data, pool.size);
6.206 - razor_write(fd, padding, PADDING(pool.size, 4));
6.207 + razor_atomic_write(atomic, handle, &header, sizeof header);
6.208 + razor_atomic_write(atomic, handle, sections, count * sizeof *sections);
6.209 + razor_atomic_write(atomic, handle, pool.data, pool.size);
6.210 + razor_atomic_write(atomic, handle, padding, PADDING(pool.size, 4));
6.211
6.212 for (i = 0; i < count; i++) {
6.213 - razor_write(fd, arrays[i]->data, arrays[i]->size);
6.214 - razor_write(fd, padding, PADDING(arrays[i]->size, 4));
6.215 + razor_atomic_write(atomic, handle, arrays[i]->data,
6.216 + arrays[i]->size);
6.217 + razor_atomic_write(atomic, handle, padding,
6.218 + PADDING(arrays[i]->size, 4));
6.219 }
6.220
6.221 array_release(&pool);
6.222 hashtable_release(&table);
6.223 -
6.224 - return 0;
6.225 }
6.226
6.227 RAZOR_EXPORT int
6.228 -razor_set_write(struct razor_set *set, const char *filename, uint32_t sections)
6.229 +razor_set_write(struct razor_set *set, struct razor_atomic *atomic,
6.230 + const char *filename, uint32_t sections)
6.231 {
6.232 - int fd, status;
6.233 + int h;
6.234
6.235 - fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC | O_BINARY, 0666);
6.236 - if (fd < 0)
6.237 + h = razor_atomic_create_file(atomic, filename,
6.238 + S_IRWXU | S_IRWXG | S_IRWXO);
6.239 + if (h < 0)
6.240 return -1;
6.241
6.242 - status = razor_set_write_to_fd(set, fd, sections);
6.243 - if (status) {
6.244 - close(fd);
6.245 - return status;
6.246 - }
6.247 + razor_set_write_to_handle(set, atomic, h, sections);
6.248
6.249 - return close(fd);
6.250 + return razor_atomic_close(atomic, h);
6.251 }
6.252
6.253 RAZOR_EXPORT void
6.254 @@ -554,74 +619,86 @@
6.255 * @package: a %razor_package
6.256 * @root: the root into which the package is currently installed
6.257 * @install_count: the value to pass to uninstall scripts
6.258 + * @stage: Limit the removal to just the scripts or the files
6.259 *
6.260 * Removes an installed package.
6.261 **/
6.262 RAZOR_EXPORT int
6.263 razor_package_remove(struct razor_set *prev, struct razor_set *next,
6.264 - struct razor_package *package, const char *root,
6.265 - int install_count)
6.266 + struct razor_atomic *atomic, struct razor_package *package,
6.267 + const char *root, int install_count,
6.268 + enum razor_stage_type stage)
6.269 {
6.270 struct razor_file_iterator *fi;
6.271 struct razor_package_iterator *pi;
6.272 struct razor_package *p;
6.273 - char buffer[PATH_MAX];
6.274 + char *buffer;
6.275 const char *name, *program, *script;
6.276 - int retval = 0, i, count;
6.277 + int i, count;
6.278 struct environment env;
6.279 struct list *link;
6.280 const char *prefix;
6.281
6.282 - environment_init(&env);
6.283 - link = list_first(&package->install_prefixes, &prev->prefix_pool);
6.284 - for (i = 0; link; i++) {
6.285 - prefix = (const char *)prev->string_pool.data + link->data;
6.286 - sprintf(buffer, "RPM_INSTALL_PREFIX%d", i);
6.287 - environment_add_variable(&env, buffer, prefix);
6.288 - link = list_next(link);
6.289 + if (stage & RAZOR_STAGE_SCRIPTS) {
6.290 + environment_init(&env);
6.291 + link = list_first(&package->install_prefixes,
6.292 + &prev->prefix_pool);
6.293 + for (i = 0; link; i++) {
6.294 + prefix = (const char *)prev->string_pool.data +
6.295 + link->data;
6.296 + sprintf(buffer, "RPM_INSTALL_PREFIX%d", i);
6.297 + environment_add_variable(&env, buffer, prefix);
6.298 + link = list_next(link);
6.299 + }
6.300 + environment_set(&env);
6.301 }
6.302 - environment_set(&env);
6.303
6.304 - razor_package_get_details(prev, package,
6.305 - RAZOR_DETAIL_PREUNPROG, &program,
6.306 - RAZOR_DETAIL_PREUN, &script,
6.307 - RAZOR_DETAIL_LAST);
6.308 + if (stage & RAZOR_STAGE_SCRIPTS_PRE) {
6.309 + razor_package_get_details(prev, package,
6.310 + RAZOR_DETAIL_PREUNPROG, &program,
6.311 + RAZOR_DETAIL_PREUN, &script,
6.312 + RAZOR_DETAIL_LAST);
6.313
6.314 - retval = razor_run_script(root, RAZOR_PROPERTY_PREUN, program, script,
6.315 - install_count);
6.316 + razor_run_script(root, RAZOR_PROPERTY_PREUN, program,
6.317 + script, install_count);
6.318 + }
6.319
6.320 - fi = razor_file_iterator_create(prev, package, 1);
6.321 + if (stage & RAZOR_STAGE_FILES) {
6.322 + fi = razor_file_iterator_create(prev, package, 1);
6.323
6.324 - while (razor_file_iterator_next(fi, &name)) {
6.325 - pi = razor_package_iterator_create_for_file(next, name);
6.326 - count = 0;
6.327 - while (razor_package_iterator_next(pi, &p, RAZOR_DETAIL_LAST))
6.328 - count++;
6.329 - razor_package_iterator_destroy(pi);
6.330 - if (count <= 0) {
6.331 - snprintf(buffer, sizeof buffer, "%s%s", root, name);
6.332 - if (razor_remove(buffer) && errno != ENOENT) {
6.333 - perror(name);
6.334 - retval = -1;
6.335 + while (razor_file_iterator_next(fi, &name)) {
6.336 + pi = razor_package_iterator_create_for_file(next, name);
6.337 + count = 0;
6.338 + while (razor_package_iterator_next(pi, &p,
6.339 + RAZOR_DETAIL_LAST))
6.340 + count++;
6.341 + razor_package_iterator_destroy(pi);
6.342 + if (count <= 0) {
6.343 + buffer = razor_concat(root, name, NULL);
6.344 + razor_atomic_remove(atomic, buffer);
6.345 + free(buffer);
6.346 }
6.347 }
6.348 +
6.349 + razor_file_iterator_destroy(fi);
6.350 }
6.351
6.352 - razor_file_iterator_destroy(fi);
6.353 + if (stage & RAZOR_STAGE_SCRIPTS_POST) {
6.354 + razor_package_get_details(prev, package,
6.355 + RAZOR_DETAIL_POSTUNPROG, &program,
6.356 + RAZOR_DETAIL_POSTUN, &script,
6.357 + RAZOR_DETAIL_LAST);
6.358
6.359 - razor_package_get_details(prev, package,
6.360 - RAZOR_DETAIL_POSTUNPROG, &program,
6.361 - RAZOR_DETAIL_POSTUN, &script,
6.362 - RAZOR_DETAIL_LAST);
6.363 + razor_run_script(root, RAZOR_PROPERTY_POSTUN, program, script,
6.364 + install_count);
6.365 + }
6.366
6.367 - if (razor_run_script(root, RAZOR_PROPERTY_POSTUN, program, script,
6.368 - install_count))
6.369 - retval = -1;
6.370 + if (stage & RAZOR_STAGE_SCRIPTS) {
6.371 + environment_unset(&env);
6.372 + environment_release(&env);
6.373 + }
6.374
6.375 - environment_unset(&env);
6.376 - environment_release(&env);
6.377 -
6.378 - return retval;
6.379 + return razor_atomic_in_error_state(atomic);
6.380 }
6.381
6.382 RAZOR_EXPORT const char *
6.383 @@ -887,7 +964,7 @@
6.384 struct razor_set *set;
6.385 struct razor_set *next;
6.386 struct array actions;
6.387 - struct deque *order;
6.388 + struct deque *order, *left;
6.389 };
6.390
6.391 static void
6.392 @@ -989,6 +1066,7 @@
6.393 }
6.394
6.395 ii->order = graph_sort(&follows);
6.396 + ii->left = deque_dup(ii->order);
6.397 graph_release(&follows);
6.398
6.399 return ii;
6.400 @@ -1005,10 +1083,10 @@
6.401 struct razor_package *pkg;
6.402 const char *removing, *name;
6.403
6.404 - if (deque_empty(ii->order))
6.405 + if (deque_empty(ii->left))
6.406 return 0;
6.407
6.408 - a = (struct install_action *)ii->actions.data + deque_pop(ii->order);
6.409 + a = (struct install_action *)ii->actions.data + deque_pop(ii->left);
6.410 *package = a->package;
6.411 *action = a->action;
6.412 *count = 0;
6.413 @@ -1026,15 +1104,24 @@
6.414 (*count)++;
6.415 }
6.416 razor_package_iterator_destroy(pi);
6.417 - }
6.418 + } else
6.419 + *count = 1;
6.420
6.421 return 1;
6.422 }
6.423
6.424 RAZOR_EXPORT void
6.425 +razor_install_iterator_rewind(struct razor_install_iterator *ii)
6.426 +{
6.427 + deque_free(ii->left);
6.428 + ii->left=deque_dup(ii->order);
6.429 +}
6.430 +
6.431 +RAZOR_EXPORT void
6.432 razor_install_iterator_destroy(struct razor_install_iterator *ii)
6.433 {
6.434 array_release(&ii->actions);
6.435 deque_free(ii->order);
6.436 + deque_free(ii->left);
6.437 free(ii);
6.438 }
7.1 --- a/librazor/razor.h Thu Aug 25 14:22:52 2011 +0100
7.2 +++ b/librazor/razor.h Thu Nov 10 10:35:21 2011 +0000
7.3 @@ -1,7 +1,7 @@
7.4 /*
7.5 * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
7.6 * Copyright (C) 2008 Red Hat, Inc
7.7 - * Copyright (C) 2009 J. Ali Harlow <ali@juiblex.co.uk>
7.8 + * Copyright (C) 2009, 2011 J. Ali Harlow <ali@juiblex.co.uk>
7.9 *
7.10 * This program is free software; you can redistribute it and/or modify
7.11 * it under the terms of the GNU General Public License as published by
7.12 @@ -22,6 +22,21 @@
7.13 #define _RAZOR_H_
7.14
7.15 #include <stdint.h>
7.16 +#include <sys/types.h>
7.17 +
7.18 +/* GCC extensions */
7.19 +#if defined(__GNUC__)
7.20 +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)
7.21 +#define RAZOR_MALLOC __attribute__((__malloc__))
7.22 +#else
7.23 +#define RAZOR_MALLOC
7.24 +#endif
7.25 +#if __GNUC__ >= 4
7.26 +#define RAZOR_NULL_TERMINATED __attribute__ ((__sentinel__))
7.27 +#else
7.28 +#define RAZOR_NULL_TERMINATED
7.29 +#endif
7.30 +#endif /* __GNUC__ */
7.31
7.32 enum razor_section_type {
7.33 RAZOR_SECTION_MAIN = 0x01,
7.34 @@ -30,6 +45,14 @@
7.35 RAZOR_SECTION_ALL = 0x07
7.36 };
7.37
7.38 +enum razor_stage_type {
7.39 + RAZOR_STAGE_SCRIPTS_PRE = 0x1,
7.40 + RAZOR_STAGE_FILES = 0x2,
7.41 + RAZOR_STAGE_SCRIPTS_POST = 0x4,
7.42 + RAZOR_STAGE_SCRIPTS = 0x5,
7.43 + RAZOR_STAGE_ALL = 0x7
7.44 +};
7.45 +
7.46 enum razor_detail_type {
7.47 RAZOR_DETAIL_LAST = 0, /* the sentinel */
7.48 RAZOR_DETAIL_NAME,
7.49 @@ -73,6 +96,85 @@
7.50 };
7.51
7.52 /**
7.53 + * SECTION:atomic
7.54 + * @title: Atomic transactions
7.55 + * @short_description: File-based transactions that shouldn't half-succeed
7.56 + *
7.57 + * This is a helper object for issuing a sequence of file-based actions
7.58 + * that should either all succeed or all fail.
7.59 + *
7.60 + * Note that currently only Windows 7 has a native implementation and that
7.61 + * the fallback implementation will not rollback even if an error does occur.
7.62 + * This could (and should) be improved.
7.63 + **/
7.64 +struct razor_atomic;
7.65 +
7.66 +struct razor_atomic *razor_atomic_open(const char *description);
7.67 +int razor_atomic_commit(struct razor_atomic *atomic);
7.68 +const char *razor_atomic_get_error_msg(struct razor_atomic *atomic);
7.69 +void razor_atomic_destroy(struct razor_atomic *atomic);
7.70 +
7.71 +/**
7.72 + * razor_atomic_make_dirs
7.73 + *
7.74 + * Create all sub-directories leading up to path. We know root exists
7.75 + * and is a dir, root does not end in a '/', and path either has a
7.76 + * leading '/' or (on MS-Windows only) root is the empty string
7.77 + * and path starts with drive (eg., "c:/windows").
7.78 + * Note: path itself is not created, only the directory in which it
7.79 + * (would) exist.
7.80 + *
7.81 + * Returns: non-zero on error.
7.82 + **/
7.83 +int razor_atomic_make_dirs(struct razor_atomic *atomic, const char *root,
7.84 + const char *path);
7.85 +int razor_atomic_remove(struct razor_atomic *atomic, const char *path);
7.86 +int razor_atomic_rename_file(struct razor_atomic *atomic, const char *oldpath,
7.87 + const char *newpath);
7.88 +
7.89 +/**
7.90 + * razor_atomic_create_dir
7.91 + *
7.92 + * Create a directory, replacing any existing object at this path except
7.93 + * an existing directory (which is not counted as a error).
7.94 + *
7.95 + * Returns: non-zero on error.
7.96 + */
7.97 +int razor_atomic_create_dir(struct razor_atomic *atomic, const char *dirname,
7.98 + mode_t mode);
7.99 +
7.100 +/**
7.101 + * razor_atomic_create_symlink
7.102 + *
7.103 + * Create a symbolic link, replacing any existing object at this path except
7.104 + * a non-empty directory.
7.105 + *
7.106 + * Note: This function will always fail on platforms that don't support
7.107 + * symbolic links.
7.108 + *
7.109 + * Returns: non-zero on error.
7.110 + */
7.111 +int razor_atomic_create_symlink(struct razor_atomic *atomic, const char *target,
7.112 + const char *path);
7.113 +/**
7.114 + * razor_atomic_create_file
7.115 + *
7.116 + * Create a file, replacing any existing object at this path except
7.117 + * a non-empty directory.
7.118 + *
7.119 + * Returns: A handle to be passed to razor_atomic_write() and
7.120 + * razor_atomic_close() or a negative value on error.
7.121 + */
7.122 +int razor_atomic_create_file(struct razor_atomic *atomic, const char *filename,
7.123 + mode_t mode);
7.124 +int razor_atomic_write(struct razor_atomic *atomic, int handle,
7.125 + const void *data, size_t size);
7.126 +int razor_atomic_close(struct razor_atomic *atomic, int handle);
7.127 +int razor_atomic_sync(struct razor_atomic *atomic, int handle);
7.128 +void razor_atomic_abort(struct razor_atomic *atomic, const char *error_msg);
7.129 +int razor_atomic_in_error_state(struct razor_atomic *atomic);
7.130 +
7.131 +/**
7.132 * SECTION:set
7.133 * @title: Package Set
7.134 * @short_description: Represents a set of packages and their metadata.
7.135 @@ -85,6 +187,9 @@
7.136 struct razor_package;
7.137 struct razor_property;
7.138
7.139 +#define RAZOR_HEADER_VERSION 2 /* Current version */
7.140 +#define RAZOR_HEADER_VERSION_MIN 1 /* Minimum version we support */
7.141 +
7.142 /**
7.143 * razor_set_create:
7.144 *
7.145 @@ -94,13 +199,20 @@
7.146 **/
7.147 struct razor_set *razor_set_create_without_root(void);
7.148 struct razor_set *razor_set_create(void);
7.149 -struct razor_set *razor_set_open(const char *filename);
7.150 -void razor_set_destroy(struct razor_set *set);
7.151 -int razor_set_write_to_fd(struct razor_set *set,
7.152 - int fd, uint32_t section_mask);
7.153 -int razor_set_write(struct razor_set *set,
7.154 +struct razor_set *razor_set_open(const char *filename,
7.155 + struct razor_atomic *atomic);
7.156 +uint32_t razor_set_get_header_version(struct razor_set *set);
7.157 +int razor_set_set_header_version(struct razor_set *set,
7.158 + uint32_t header_version);
7.159 +void razor_set_unref(struct razor_set *set);
7.160 +struct razor_set *razor_set_ref(struct razor_set *set);
7.161 +void razor_set_write_to_handle(struct razor_set *set,
7.162 + struct razor_atomic *atomic, int handle,
7.163 + uint32_t section_mask);
7.164 +int razor_set_write(struct razor_set *set, struct razor_atomic *atomic,
7.165 const char *filename, uint32_t setions);
7.166 -int razor_set_bind_sections(struct razor_set *set, const char *filename);
7.167 +int razor_set_bind_sections(struct razor_set *set, struct razor_atomic *atomic,
7.168 + const char *filename);
7.169
7.170 struct razor_package *
7.171 razor_set_get_package(struct razor_set *set, const char *package);
7.172 @@ -110,8 +222,9 @@
7.173 struct razor_package *package, ...);
7.174 int
7.175 razor_package_remove(struct razor_set *prev, struct razor_set *next,
7.176 - struct razor_package *package, const char *root,
7.177 - int install_count);
7.178 + struct razor_atomic *atomic, struct razor_package *package,
7.179 + const char *root, int install_count,
7.180 + enum razor_stage_type stage);
7.181
7.182 /**
7.183 * SECTION:iterator
7.184 @@ -230,6 +343,7 @@
7.185 enum razor_install_action *action,
7.186 int *count);
7.187
7.188 +void razor_install_iterator_rewind(struct razor_install_iterator *ii);
7.189 void razor_install_iterator_destroy(struct razor_install_iterator *ii);
7.190
7.191 /**
7.192 @@ -286,12 +400,14 @@
7.193 const char *path);
7.194 void razor_relocations_destroy(struct razor_relocations *relocations);
7.195
7.196 -struct razor_rpm *razor_rpm_open(const char *filename);
7.197 +struct razor_rpm *razor_rpm_open(const char *filename,
7.198 + struct razor_atomic *atomic);
7.199 void razor_rpm_get_details(struct razor_rpm *rpm, ...);
7.200 void razor_rpm_set_relocations(struct razor_rpm *rpm,
7.201 struct razor_relocations *relocations);
7.202 -int razor_rpm_install(struct razor_rpm *rpm, const char *root,
7.203 - int install_count);
7.204 +int razor_rpm_install(struct razor_rpm *rpm, struct razor_atomic *atomic,
7.205 + const char *root, int install_count,
7.206 + enum razor_stage_type stage);
7.207 int razor_rpm_close(struct razor_rpm *rpm);
7.208
7.209 /**
7.210 @@ -378,14 +494,15 @@
7.211 struct razor_root;
7.212
7.213 int razor_root_create(const char *root);
7.214 -struct razor_root *razor_root_open(const char *root);
7.215 -struct razor_set *razor_root_open_read_only(const char *root);
7.216 +struct razor_root *
7.217 +razor_root_open(const char *root, struct razor_atomic *atomic);
7.218 +struct razor_set *razor_root_open_read_only(const char *root,
7.219 + struct razor_atomic *atomic);
7.220 struct razor_set *razor_root_get_system_set(struct razor_root *root);
7.221 int razor_root_close(struct razor_root *root);
7.222 void razor_root_update(struct razor_root *root, struct razor_set *next);
7.223 int razor_root_commit(struct razor_root *root);
7.224
7.225 -
7.226 /**
7.227 * SECTION:misc
7.228 * @title: Miscellaneous Functions
7.229 @@ -408,5 +525,8 @@
7.230 void razor_set_lua_loader(const char *modname, void (*loader)());
7.231 void (*razor_get_lua_loader(const char *modname))();
7.232
7.233 +char *razor_concat(const char *s, ...) RAZOR_MALLOC RAZOR_NULL_TERMINATED;
7.234 +
7.235 +const char *razor_system_arch(void);
7.236
7.237 #endif /* _RAZOR_H_ */
8.1 --- a/librazor/root.c Thu Aug 25 14:22:52 2011 +0100
8.2 +++ b/librazor/root.c Thu Nov 10 10:35:21 2011 +0000
8.3 @@ -1,7 +1,7 @@
8.4 /*
8.5 * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
8.6 * Copyright (C) 2008 Red Hat, Inc
8.7 - * Copyright (C) 2009 J. Ali Harlow <ali@juiblex.co.uk>
8.8 + * Copyright (C) 2009, 2011 J. Ali Harlow <ali@juiblex.co.uk>
8.9 *
8.10 * This program is free software; you can redistribute it and/or modify
8.11 * it under the terms of the GNU General Public License as published by
8.12 @@ -60,9 +60,9 @@
8.13 struct razor_root {
8.14 struct razor_set *system;
8.15 struct razor_set *next;
8.16 - int fd;
8.17 - char path[PATH_MAX];
8.18 - char new_path[PATH_MAX];
8.19 + struct razor_atomic *atomic;
8.20 + int handle;
8.21 + char *path, *new_path;
8.22 };
8.23
8.24 static void
8.25 @@ -83,9 +83,11 @@
8.26 RAZOR_EXPORT int
8.27 razor_root_create(const char *root)
8.28 {
8.29 + int retval;
8.30 struct stat buf;
8.31 struct razor_set *set;
8.32 - char path[PATH_MAX];
8.33 + struct razor_atomic *atomic;
8.34 + char *path;
8.35
8.36 assert (root != NULL);
8.37
8.38 @@ -107,77 +109,90 @@
8.39 return -1;
8.40 }
8.41
8.42 - snprintf(path, sizeof path, "%s/%s",
8.43 - razor_root_path, system_repo_filename);
8.44 - if (razor_create_dir(root, path) < 0) {
8.45 - fprintf(stderr, "could not create %s%s\n",
8.46 - root, razor_root_path);
8.47 - return -1;
8.48 + path = razor_concat(root, razor_root_path, "/", system_repo_filename,
8.49 + NULL);
8.50 + retval = !stat(path, &buf);
8.51 + free(path);
8.52 + if (retval) {
8.53 + fprintf(stderr,
8.54 + "a razor install root is already initialized\n");
8.55 + return retval;
8.56 }
8.57
8.58 + atomic = razor_atomic_open("Create initial package set");
8.59 + path = razor_concat(razor_root_path, "/", system_repo_filename, NULL);
8.60 + razor_atomic_make_dirs(atomic, root, path);
8.61 set = razor_set_create();
8.62 - snprintf(path, sizeof path, "%s%s/%s",
8.63 - root, razor_root_path, system_repo_filename);
8.64 - if (stat(path, &buf) == 0) {
8.65 - fprintf(stderr,
8.66 - "a razor install root is already initialized\n");
8.67 - return -1;
8.68 - }
8.69 - if (razor_set_write(set, path, RAZOR_SECTION_ALL) < 0) {
8.70 + razor_set_write(set, atomic, path, RAZOR_SECTION_ALL);
8.71 + free(path);
8.72 + retval = razor_atomic_commit(atomic);
8.73 + if (retval)
8.74 fprintf(stderr, "could not write initial package set\n");
8.75 - return -1;
8.76 - }
8.77 - razor_set_destroy(set);
8.78 + razor_set_unref(set);
8.79 + razor_atomic_destroy(atomic);
8.80
8.81 - return 0;
8.82 + return retval;
8.83 }
8.84
8.85 RAZOR_EXPORT struct razor_root *
8.86 -razor_root_open(const char *root)
8.87 +razor_root_open(const char *root, struct razor_atomic *atomic)
8.88 {
8.89 struct razor_root *image;
8.90 - char lock_path[PATH_MAX];
8.91 + char *lock_path;
8.92 + int r;
8.93
8.94 assert (root != NULL);
8.95
8.96 razor_root_init();
8.97 image = malloc(sizeof *image);
8.98 - if (image == NULL)
8.99 + if (image == NULL) {
8.100 + razor_atomic_abort(atomic, "Not enough memory");
8.101 return NULL;
8.102 + }
8.103 +
8.104 + image->atomic = atomic;
8.105
8.106 image->system = razor_set_create_without_root();
8.107 if (image->system == NULL) {
8.108 free(image);
8.109 + razor_atomic_abort(atomic, "Not enough memory");
8.110 return NULL;
8.111 }
8.112
8.113 - snprintf(lock_path, sizeof lock_path,
8.114 - "%s%s/%s", root, razor_root_path, system_lock_filename);
8.115 + lock_path = razor_concat(root, razor_root_path, "/",
8.116 + system_lock_filename, NULL);
8.117
8.118 - if (razor_set_aquire_lock(image->system, lock_path, 1) < 0) {
8.119 - razor_set_destroy(image->system);
8.120 + r = razor_set_aquire_lock(image->system, lock_path, 1);
8.121 +
8.122 + free(lock_path);
8.123 +
8.124 + if (r < 0) {
8.125 + razor_atomic_abort(atomic,
8.126 + "Failed to aquire exclusive system lock");
8.127 + razor_set_unref(image->system);
8.128 free(image);
8.129 return NULL;
8.130 }
8.131
8.132 - snprintf(image->new_path, sizeof image->new_path,
8.133 - "%s%s/%s", root, razor_root_path, system_tmp_filename);
8.134 - image->fd = open(image->new_path,
8.135 - O_CREAT | O_WRONLY | O_TRUNC | O_BINARY,
8.136 - 0666);
8.137 - if (image->fd < 0) {
8.138 - razor_set_destroy(image->system);
8.139 + image->new_path = razor_concat(root, razor_root_path, "/",
8.140 + system_tmp_filename, NULL);
8.141 + image->handle = razor_atomic_create_file(atomic, image->new_path,
8.142 + S_IRWXU | S_IRWXG | S_IRWXO);
8.143 + if (image->handle < 0) {
8.144 + free(image->new_path);
8.145 + razor_set_unref(image->system);
8.146 free(image);
8.147 return NULL;
8.148 }
8.149
8.150 - snprintf(image->path, sizeof image->path,
8.151 - "%s%s/%s", root, razor_root_path, system_repo_filename);
8.152 + image->path = razor_concat(root, razor_root_path, "/",
8.153 + system_repo_filename, NULL);
8.154
8.155 - if (razor_set_bind_sections(image->system, image->path)) {
8.156 - close(image->fd);
8.157 + if (razor_set_bind_sections(image->system, atomic, image->path)) {
8.158 unlink(image->new_path);
8.159 - razor_set_destroy(image->system);
8.160 + free(image->new_path);
8.161 + free(image->path);
8.162 + razor_set_unref(image->system);
8.163 free(image);
8.164 return NULL;
8.165 }
8.166 @@ -186,33 +201,41 @@
8.167 }
8.168
8.169 RAZOR_EXPORT struct razor_set *
8.170 -razor_root_open_read_only(const char *root)
8.171 +razor_root_open_read_only(const char *root, struct razor_atomic *atomic)
8.172 {
8.173 - char path[PATH_MAX];
8.174 + char *path;
8.175 struct razor_set *set;
8.176
8.177 assert (root != NULL);
8.178
8.179 razor_root_init();
8.180 set = razor_set_create_without_root();
8.181 - if (set == NULL)
8.182 - return NULL;
8.183 -
8.184 - snprintf(path, sizeof path,
8.185 - "%s%s/%s", root, razor_root_path, system_lock_filename);
8.186 - if (razor_set_aquire_lock(set, path, 0) < 0) {
8.187 - razor_set_destroy(set);
8.188 + if (set == NULL) {
8.189 + razor_atomic_abort(atomic, "Not enough memory");
8.190 return NULL;
8.191 }
8.192
8.193 - snprintf(path, sizeof path, "%s%s/%s",
8.194 - root, razor_root_path, system_repo_filename);
8.195 -
8.196 - if (razor_set_bind_sections(set, path)) {
8.197 - razor_set_destroy(set);
8.198 + path = razor_concat(root, razor_root_path, "/", system_lock_filename,
8.199 + NULL);
8.200 + if (razor_set_aquire_lock(set, path, 0) < 0) {
8.201 + razor_atomic_abort(atomic, "Failed to aquire non-exclusive "
8.202 + "system lock");
8.203 + free(path);
8.204 + razor_set_unref(set);
8.205 return NULL;
8.206 }
8.207
8.208 + free(path);
8.209 + path = razor_concat(root, razor_root_path, "/", system_repo_filename,
8.210 + NULL);
8.211 +
8.212 + if (razor_set_bind_sections(set, atomic, path)) {
8.213 + razor_set_unref(set);
8.214 + set = NULL;
8.215 + }
8.216 +
8.217 + free(path);
8.218 +
8.219 return set;
8.220 }
8.221
8.222 @@ -229,9 +252,11 @@
8.223 {
8.224 assert (root != NULL);
8.225
8.226 - razor_set_destroy(root->system);
8.227 - close(root->fd);
8.228 - unlink(root->new_path);
8.229 + razor_set_unref(root->system);
8.230 + razor_atomic_close(root->atomic, root->handle);
8.231 + razor_atomic_remove(root->atomic, root->new_path);
8.232 + free(root->path);
8.233 + free(root->new_path);
8.234 free(root);
8.235
8.236 return 0;
8.237 @@ -244,13 +269,13 @@
8.238 assert (next != NULL);
8.239
8.240 razor_root_init();
8.241 - razor_set_write_to_fd(next, root->fd, RAZOR_SECTION_ALL);
8.242 + razor_set_write_to_handle(next, root->atomic, root->handle,
8.243 + RAZOR_SECTION_ALL);
8.244 root->next = next;
8.245
8.246 /* Sync the new repo file so the new package set is on disk
8.247 * before we start upgrading. */
8.248 - fsync(root->fd);
8.249 - printf("wrote %s\n", root->new_path);
8.250 + razor_atomic_sync(root->atomic, root->handle);
8.251 }
8.252
8.253 RAZOR_EXPORT int
8.254 @@ -259,18 +284,12 @@
8.255 int retval;
8.256 assert (root != NULL);
8.257
8.258 - /* Make it so. */
8.259 - close(root->fd);
8.260 -#ifdef MSWIN_API
8.261 - /* Rename is not atomic under MS-Windows */
8.262 - remove(root->path);
8.263 -#endif
8.264 - retval = rename(root->new_path, root->path);
8.265 - if (retval)
8.266 - perror(root->path);
8.267 - else
8.268 - printf("renamed %s to %s\n", root->new_path, root->path);
8.269 - razor_set_destroy(root->system);
8.270 + razor_atomic_close(root->atomic, root->handle);
8.271 + retval = razor_atomic_rename_file(root->atomic, root->new_path,
8.272 + root->path);
8.273 + razor_set_unref(root->system);
8.274 + free(root->path);
8.275 + free(root->new_path);
8.276 free(root);
8.277
8.278 return retval;
9.1 --- a/librazor/rpm.c Thu Aug 25 14:22:52 2011 +0100
9.2 +++ b/librazor/rpm.c Thu Nov 10 10:35:21 2011 +0000
9.3 @@ -1,7 +1,7 @@
9.4 /*
9.5 * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
9.6 * Copyright (C) 2008 Red Hat, Inc
9.7 - * Copyright (C) 2009 J. Ali Harlow <ali@juiblex.co.uk>
9.8 + * Copyright (C) 2009, 2011 J. Ali Harlow <ali@juiblex.co.uk>
9.9 *
9.10 * This program is free software; you can redistribute it and/or modify
9.11 * it under the terms of the GNU General Public License as published by
9.12 @@ -602,24 +602,29 @@
9.13 }
9.14
9.15 RAZOR_EXPORT struct razor_rpm *
9.16 -razor_rpm_open(const char *filename)
9.17 +razor_rpm_open(const char *filename, struct razor_atomic *atomic)
9.18 {
9.19 struct razor_rpm *rpm;
9.20 struct rpm_header_index *base, *index;
9.21 unsigned int count, i, nindex, hsize;
9.22 const char *name, *prefix;
9.23 + char *s;
9.24
9.25 assert (filename != NULL);
9.26
9.27 - rpm = malloc(sizeof *rpm);
9.28 - if (rpm == NULL)
9.29 + rpm = zalloc(sizeof *rpm);
9.30 + if (rpm == NULL) {
9.31 + razor_atomic_abort(atomic, "Not enough memory");
9.32 return NULL;
9.33 + }
9.34 memset(rpm, 0, sizeof *rpm);
9.35
9.36 rpm->map = razor_file_get_contents(filename, &rpm->size);
9.37 if (!rpm->map) {
9.38 - fprintf(stderr, "couldn't get contents of %s (%s)\n", filename,
9.39 - strerror(errno));
9.40 + s = razor_concat(filename, ": ", strerror(errno), NULL);
9.41 + razor_atomic_abort(atomic, s);
9.42 + free(s);
9.43 + free(rpm);
9.44 return NULL;
9.45 }
9.46
9.47 @@ -648,7 +653,11 @@
9.48 name = razor_rpm_get_indirect(rpm, RPMTAG_OLDFILENAMES,
9.49 &count);
9.50 if (name) {
9.51 - fprintf(stderr, "old filenames not supported\n");
9.52 + razor_rpm_close(rpm);
9.53 + s = razor_concat(filename,
9.54 + ": Old filenames not supported", NULL);
9.55 + razor_atomic_abort(atomic, s);
9.56 + free(s);
9.57 return NULL;
9.58 }
9.59 }
9.60 @@ -666,7 +675,12 @@
9.61 prefix = razor_rpm_get_indirect(rpm, RPMTAG_DEFAULTPREFIX,
9.62 &count);
9.63 if (prefix) {
9.64 - fprintf(stderr, "default prefix not supported\n");
9.65 + razor_rpm_close(rpm);
9.66 + s = razor_concat(filename,
9.67 + ": Default prefix not supported",
9.68 + NULL);
9.69 + razor_atomic_abort(atomic, s);
9.70 + free(s);
9.71 return NULL;
9.72 }
9.73 }
9.74 @@ -711,6 +725,7 @@
9.75 struct installer {
9.76 const char *root;
9.77 struct razor_rpm *rpm;
9.78 + struct razor_atomic *atomic;
9.79 z_stream stream;
9.80 unsigned char buffer[32768];
9.81 size_t rest, length;
9.82 @@ -731,8 +746,7 @@
9.83 installer->stream.avail_out = length;
9.84 err = inflate(&installer->stream, Z_SYNC_FLUSH);
9.85 if (err != Z_OK && err != Z_STREAM_END) {
9.86 - fprintf(stderr, "inflate error: %d (%s)\n", err,
9.87 - strerror(errno));
9.88 + razor_atomic_abort(installer->atomic, "Failed to inflate");
9.89 return -1;
9.90 }
9.91
9.92 @@ -757,8 +771,7 @@
9.93
9.94 err = inflate(&installer->stream, Z_SYNC_FLUSH);
9.95 if (err != Z_OK && err != Z_STREAM_END) {
9.96 - fprintf(stderr, "inflate error: %d (%s)\n", err,
9.97 - strerror(errno));
9.98 + razor_atomic_abort(installer->atomic, "Failed to inflate");
9.99 return -1;
9.100 }
9.101
9.102 @@ -768,80 +781,74 @@
9.103 static int
9.104 create_path(struct installer *installer, const char *path, unsigned int mode)
9.105 {
9.106 - char buffer[PATH_MAX];
9.107 - struct stat buf;
9.108 - int fd, ret;
9.109 + char *s, *buffer;
9.110 + int h, ret;
9.111
9.112 - if (razor_create_dir(installer->root, path) < 0)
9.113 + if (razor_atomic_make_dirs(installer->atomic, installer->root, path))
9.114 return -1;
9.115
9.116 - snprintf(buffer, sizeof buffer, "%s%s", installer->root, path);
9.117 + buffer = razor_concat(installer->root, path, NULL);
9.118
9.119 switch (mode >> 12) {
9.120 case REG:
9.121 /* FIXME: handle the case where a file is already there. */
9.122 - fd = open(buffer, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
9.123 - mode & 0x1ff);
9.124 - if (fd < 0){
9.125 - fprintf(stderr, "failed to create file %s\n", buffer);
9.126 + h = razor_atomic_create_file(installer->atomic, buffer, mode);
9.127 + free(buffer);
9.128 + if (h < 0)
9.129 return -1;
9.130 + while (installer->rest > 0) {
9.131 + if (installer_inflate(installer))
9.132 + return -1;
9.133 + if (razor_atomic_write(installer->atomic, h,
9.134 + installer->buffer,
9.135 + installer->length))
9.136 + return -1;
9.137 }
9.138 - while (installer->rest > 0) {
9.139 - if (installer_inflate(installer)) {
9.140 - fprintf(stderr, "failed to inflate\n");
9.141 - return -1;
9.142 - }
9.143 - if (razor_write(fd, installer->buffer,
9.144 - installer->length)) {
9.145 - fprintf(stderr, "failed to write payload\n");
9.146 - return -1;
9.147 - }
9.148 - }
9.149 - if (close(fd) < 0) {
9.150 - fprintf(stderr, "failed to close %s: %s\n", buffer,
9.151 - strerror(errno));
9.152 - return -1;
9.153 - }
9.154 - return 0;
9.155 + return razor_atomic_close(installer->atomic, h);
9.156 case XDIR:
9.157 - ret = mkdir(buffer, mode & 0x1ff);
9.158 - if (ret == 0 || errno != EEXIST)
9.159 - return ret;
9.160 - if (stat(buffer, &buf) || !S_ISDIR(buf.st_mode)) {
9.161 - /* FIXME: also check that mode match. */
9.162 - fprintf(stderr,
9.163 - "%s exists but is not a directory\n", buffer);
9.164 - return -1;
9.165 - }
9.166 - return 0;
9.167 + ret = razor_atomic_create_dir(installer->atomic, buffer, mode);
9.168 + free(buffer);
9.169 + return ret;
9.170 case LINK:
9.171 #if HAVE_SYMLINK
9.172 - if (installer_inflate(installer)) {
9.173 - fprintf(stderr, "failed to inflate\n");
9.174 + if (installer_inflate(installer))
9.175 return -1;
9.176 - }
9.177 if (installer->length >= sizeof installer->buffer) {
9.178 - fprintf(stderr, "link name too long\n");
9.179 + razor_atomic_abort(installer->atomic,
9.180 + "Link target too long");
9.181 return -1;
9.182 }
9.183 installer->buffer[installer->length] = '\0';
9.184 - if (symlink((const char *) installer->buffer, buffer)) {
9.185 - perror("failed to create symlink");
9.186 - return -1;
9.187 - }
9.188 - return 0;
9.189 + ret = razor_atomic_create_symlink(installer->atomic,
9.190 + (const char *)installer->buffer, buffer);
9.191 + free(buffer);
9.192 + return ret;
9.193 #else
9.194 - /* fall through */
9.195 + s = "Symbolic links";
9.196 + goto unsupported;
9.197 #endif
9.198 case PIPE:
9.199 + s = "Named pipes";
9.200 +unsupported:
9.201 + free(buffer);
9.202 + buffer = razor_concat(s, " are not supported on this platform",
9.203 + NULL);
9.204 + razor_atomic_abort(installer->atomic, buffer);
9.205 + free(buffer);
9.206 + return -1;
9.207 case CDEV:
9.208 + s = "Character devices";
9.209 + goto unsupported;
9.210 case BDEV:
9.211 + s = "Block devices";
9.212 + goto unsupported;
9.213 case SOCK:
9.214 - printf("%s: unhandled file type %d\n", buffer, mode >> 12);
9.215 - return 0;
9.216 + s = "Named sockets";
9.217 + goto unsupported;
9.218 default:
9.219 - printf("%s: unknown file type %d\n", buffer, mode >> 12);
9.220 - return 0;
9.221 + free(buffer);
9.222 + razor_atomic_abort(installer->atomic, "Unknown file type");
9.223 + return -1;
9.224 }
9.225 }
9.226
9.227 @@ -1046,10 +1053,12 @@
9.228 {
9.229 unsigned char *gz_header;
9.230 int method, flags, err;
9.231 + char buffer[32], *s;
9.232
9.233 gz_header = installer->rpm->payload;
9.234 if (gz_header[0] != 0x1f || gz_header[1] != 0x8b) {
9.235 - fprintf(stderr, "payload section doesn't have gz header\n");
9.236 + razor_atomic_abort(installer->atomic,
9.237 + "Payload section doesn't have gz header");
9.238 return -1;
9.239 }
9.240
9.241 @@ -1057,8 +1066,9 @@
9.242 flags = gz_header[3];
9.243
9.244 if (method != Z_DEFLATED || flags != 0) {
9.245 - fprintf(stderr,
9.246 - "unknown payload compression method or flags set\n");
9.247 + razor_atomic_abort(installer->atomic,
9.248 + "Unknown payload compression method or "
9.249 + "flags set");
9.250 return -1;
9.251 }
9.252
9.253 @@ -1075,7 +1085,10 @@
9.254
9.255 err = inflateInit2(&installer->stream, -MAX_WBITS);
9.256 if (err != Z_OK) {
9.257 - fprintf(stderr, "inflateInit error: %d\n", err);
9.258 + sprintf(buffer, "%d", err);
9.259 + s = razor_concat("inflateEnd error: ", s, NULL);
9.260 + razor_atomic_abort(installer->atomic, s);
9.261 + free(s);
9.262 return -1;
9.263 }
9.264
9.265 @@ -1086,15 +1099,18 @@
9.266 installer_finish(struct installer *installer)
9.267 {
9.268 int err;
9.269 + char buffer[32], *s;
9.270
9.271 err = inflateEnd(&installer->stream);
9.272
9.273 if (err != Z_OK) {
9.274 - fprintf(stderr, "inflateEnd error: %d\n", err);
9.275 - return -1;
9.276 + sprintf(buffer, "%d", err);
9.277 + s = razor_concat("inflateEnd error: ", s, NULL);
9.278 + razor_atomic_abort(installer->atomic, s);
9.279 + free(s);
9.280 }
9.281
9.282 - return 0;
9.283 + return razor_atomic_in_error_state(installer->atomic);
9.284 }
9.285
9.286 static unsigned long
9.287 @@ -1114,73 +1130,86 @@
9.288 }
9.289
9.290 RAZOR_EXPORT int
9.291 -razor_rpm_install(struct razor_rpm *rpm, const char *root, int install_count)
9.292 +razor_rpm_install(struct razor_rpm *rpm, struct razor_atomic *atomic,
9.293 + const char *root, int install_count,
9.294 + enum razor_stage_type stage)
9.295 {
9.296 struct installer installer;
9.297 struct cpio_file_header *header;
9.298 struct stat buf;
9.299 unsigned int mode;
9.300 - const char *path;
9.301 + const char *path, *name;
9.302 size_t filesize;
9.303 + char *s;
9.304
9.305 assert (rpm != NULL);
9.306 assert (root != NULL);
9.307
9.308 installer.rpm = rpm;
9.309 installer.root = root;
9.310 + installer.atomic = atomic;
9.311
9.312 /* FIXME: Only do this before a transaction, not per rpm. */
9.313 if (*root && (stat(root, &buf) < 0 || !S_ISDIR(buf.st_mode))) {
9.314 - fprintf(stderr,
9.315 - "root installation directory \"%s\" does not exist\n",
9.316 - root);
9.317 + s = razor_concat(root, ": Directory does not exist", NULL);
9.318 + razor_atomic_abort(stderr, s);
9.319 + free(s);
9.320 return -1;
9.321 }
9.322
9.323 if (rpm->relocations)
9.324 razor_relocations_set_rpm(rpm->relocations, rpm);
9.325
9.326 - if (installer_init(&installer))
9.327 - return -1;
9.328 + if (stage & RAZOR_STAGE_SCRIPTS_PRE)
9.329 + run_script(&installer, RPMTAG_PREINPROG, RPMTAG_PREIN,
9.330 + install_count);
9.331
9.332 - run_script(&installer, RPMTAG_PREINPROG, RPMTAG_PREIN, install_count);
9.333 -
9.334 - while (installer.stream.avail_in > 0) {
9.335 - installer.rest = sizeof *header;
9.336 - if (installer_inflate(&installer))
9.337 + if (stage & RAZOR_STAGE_FILES) {
9.338 + if (installer_init(&installer))
9.339 return -1;
9.340
9.341 - header = (struct cpio_file_header *) installer.buffer;
9.342 - mode = fixed_hex_to_ulong(header->mode, sizeof header->mode);
9.343 - filesize = fixed_hex_to_ulong(header->filesize,
9.344 - sizeof header->filesize);
9.345 + while (installer.stream.avail_in > 0) {
9.346 + installer.rest = sizeof *header;
9.347 + if (installer_inflate(&installer))
9.348 + break;
9.349
9.350 - installer.rest = fixed_hex_to_ulong(header->namesize,
9.351 - sizeof header->namesize);
9.352 + header = (struct cpio_file_header *) installer.buffer;
9.353 + mode = fixed_hex_to_ulong(header->mode,
9.354 + sizeof header->mode);
9.355 + filesize = fixed_hex_to_ulong(header->filesize,
9.356 + sizeof header->filesize);
9.357
9.358 - if (installer_inflate(&installer) ||
9.359 - installer_align(&installer, 4))
9.360 - return -1;
9.361 + installer.rest =
9.362 + fixed_hex_to_ulong(header->namesize,
9.363 + sizeof header->namesize);
9.364
9.365 - path = (const char *) installer.buffer;
9.366 - /* This convention is so lame... */
9.367 - if (strcmp(path, "TRAILER!!!") == 0)
9.368 - break;
9.369 + if (installer_inflate(&installer) ||
9.370 + installer_align(&installer, 4))
9.371 + break;
9.372
9.373 - installer.rest = filesize;
9.374 - path++;
9.375 - if (rpm->relocations)
9.376 - path = razor_relocations_apply(rpm->relocations, path);
9.377 - if (create_path(&installer, path, mode) < 0)
9.378 - return -1;
9.379 - if (installer_align(&installer, 4))
9.380 + path = (const char *) installer.buffer;
9.381 + /* This convention is so lame... */
9.382 + if (strcmp(path, "TRAILER!!!") == 0)
9.383 + break;
9.384 +
9.385 + installer.rest = filesize;
9.386 + path++;
9.387 + if (rpm->relocations)
9.388 + path = razor_relocations_apply(rpm->relocations,
9.389 + path);
9.390 + if (create_path(&installer, path, mode))
9.391 + break;
9.392 + if (installer_align(&installer, 4))
9.393 + break;
9.394 + }
9.395 +
9.396 + if (installer_finish(&installer))
9.397 return -1;
9.398 }
9.399
9.400 - if (installer_finish(&installer))
9.401 - return -1;
9.402 -
9.403 - run_script(&installer, RPMTAG_POSTINPROG, RPMTAG_POSTIN, install_count);
9.404 + if (stage & RAZOR_STAGE_SCRIPTS_POST)
9.405 + run_script(&installer, RPMTAG_POSTINPROG, RPMTAG_POSTIN,
9.406 + install_count);
9.407
9.408 return 0;
9.409 }
10.1 --- a/librazor/transaction.c Thu Aug 25 14:22:52 2011 +0100
10.2 +++ b/librazor/transaction.c Thu Nov 10 10:35:21 2011 +0000
10.3 @@ -1,7 +1,7 @@
10.4 /*
10.5 * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
10.6 * Copyright (C) 2008 Red Hat, Inc
10.7 - * Copyright (C) 2009 J. Ali Harlow <ali@juiblex.co.uk>
10.8 + * Copyright (C) 2009, 2011 J. Ali Harlow <ali@juiblex.co.uk>
10.9 *
10.10 * This program is free software; you can redistribute it and/or modify
10.11 * it under the terms of the GNU General Public License as published by
10.12 @@ -109,7 +109,7 @@
10.13 {
10.14 int count;
10.15
10.16 - ts->set = set;
10.17 + ts->set = razor_set_ref(set);
10.18 count = set->packages.size / sizeof (struct razor_package);
10.19 ts->packages = zalloc(count * sizeof *ts->packages);
10.20 count = set->properties.size / sizeof (struct razor_property);
10.21 @@ -119,6 +119,7 @@
10.22 static void
10.23 transaction_set_release(struct transaction_set *ts)
10.24 {
10.25 + razor_set_unref(ts->set);
10.26 free(ts->packages);
10.27 free(ts->properties);
10.28 }
10.29 @@ -321,7 +322,9 @@
10.30 RAZOR_DETAIL_NAME, &n,
10.31 RAZOR_DETAIL_VERSION, &v,
10.32 RAZOR_DETAIL_LAST)) {
10.33 +#if 0
10.34 fprintf(stderr, "removing %s-%s\n", n, v);
10.35 +#endif
10.36 razor_transaction_remove_package(trans, pkg);
10.37 }
10.38 }
10.39 @@ -369,11 +372,13 @@
10.40 RAZOR_DETAIL_VERSION, &version,
10.41 RAZOR_DETAIL_LAST)) {
10.42
10.43 +#if 0
10.44 fprintf(stderr, "flagging %s-%s for providing %s matching %s %s\n",
10.45 name, version,
10.46 ppi->pool + p->name,
10.47 rpi->pool + r->name,
10.48 rpi->pool + r->version);
10.49 +#endif
10.50 flags[pkg - pkgs] |= flag;
10.51 }
10.52 }
10.53 @@ -542,11 +547,13 @@
10.54 while (razor_package_iterator_next(&pkg_iter, &pkg,
10.55 RAZOR_DETAIL_NAME, &name,
10.56 RAZOR_DETAIL_LAST)) {
10.57 +#if 0
10.58 fprintf(stderr, "updating %s because %s %s %s "
10.59 "isn't satisfied\n",
10.60 name, spi.pool + sp->name,
10.61 razor_property_relation_to_string(sp),
10.62 spi.pool + sp->version);
10.63 +#endif
10.64 trans->system.packages[pkg - spkgs] |=
10.65 TRANS_PACKAGE_UPDATE;
10.66 }
10.67 @@ -595,9 +602,11 @@
10.68 RAZOR_DETAIL_NAME, &name,
10.69 RAZOR_DETAIL_VERSION, &version,
10.70 RAZOR_DETAIL_LAST)) {
10.71 +#if 0
10.72 fprintf(stderr, "updating %s %s because it "
10.73 "conflicts with %s\n",
10.74 name, version, spi.pool + sp->name);
10.75 +#endif
10.76 trans->system.packages[pkg - spkgs] |=
10.77 TRANS_PACKAGE_UPDATE;
10.78 }
10.79 @@ -640,6 +649,7 @@
10.80
10.81 rpi->present[rp - rpi->start] |= TRANS_PROPERTY_SATISFIED;
10.82
10.83 +#if 0
10.84 fprintf(stderr, "pulling in %s-%s.%s which provides %s %s %s "
10.85 "to satisfy %s %s %s\n",
10.86 ppi->pool + pkg->name,
10.87 @@ -651,6 +661,7 @@
10.88 &rpi->pool[rp->name],
10.89 razor_property_relation_to_string(rp),
10.90 &rpi->pool[rp->version]);
10.91 +#endif
10.92
10.93 trans->upstream.packages[pkg - upkgs] |= TRANS_PACKAGE_UPDATE;
10.94 }
10.95 @@ -736,7 +747,9 @@
10.96 RAZOR_PROPERTY_LESS,
10.97 version);
10.98 razor_transaction_install_package(trans, p);
10.99 +#if 0
10.100 fprintf(stderr, "installing %s-%s\n", name, version);
10.101 +#endif
10.102 }
10.103 }
10.104
11.1 --- a/librazor/util.c Thu Aug 25 14:22:52 2011 +0100
11.2 +++ b/librazor/util.c Thu Nov 10 10:35:21 2011 +0000
11.3 @@ -1,7 +1,7 @@
11.4 /*
11.5 * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
11.6 * Copyright (C) 2008 Red Hat, Inc
11.7 - * Copyright (C) 2009 J. Ali Harlow <ali@juiblex.co.uk>
11.8 + * Copyright (C) 2009, 2011 J. Ali Harlow <ali@juiblex.co.uk>
11.9 *
11.10 * This program is free software; you can redistribute it and/or modify
11.11 * it under the terms of the GNU General Public License as published by
11.12 @@ -33,6 +33,8 @@
11.13 #ifdef MSWIN_API
11.14 #include <windows.h>
11.15 #include <direct.h>
11.16 +#else
11.17 +#include <sys/utsname.h>
11.18 #endif
11.19 #if HAVE_SYS_MMAN_H
11.20 #include <sys/mman.h>
11.21 @@ -46,137 +48,9 @@
11.22 #define O_BINARY 0
11.23 #endif
11.24
11.25 -#define RAZOR_ASCII_ISALPHA(c) \
11.26 - ((c) >= 'A' && (c) <= 'Z' || (c) >= 'a' && (c) <= 'z')
11.27 -
11.28 /* Required by gnulib on non-libc platforms */
11.29 char *program_name = "librazor";
11.30
11.31 -static int allow_all_root_names = 0;
11.32 -
11.33 -/*
11.34 - * Primarily intended for testing named roots under UNIX platforms.
11.35 - */
11.36 -RAZOR_EXPORT void razor_disable_root_name_checks(int disable)
11.37 -{
11.38 - allow_all_root_names = disable;
11.39 -}
11.40 -
11.41 -static int razor_valid_root_name(const char *name)
11.42 -{
11.43 - if (allow_all_root_names)
11.44 - return !strchr(name,'/');
11.45 -
11.46 -#ifdef MSWIN_API
11.47 - return RAZOR_ASCII_ISALPHA(name[0]) && name[1] == ':' &&
11.48 - name[2] == '\0';
11.49 -#else
11.50 - return name[0] == '\0';
11.51 -#endif
11.52 -}
11.53 -
11.54 -int
11.55 -razor_create_dir(const char *root, const char *path)
11.56 -{
11.57 - char buffer[PATH_MAX], *p;
11.58 - const char *slash, *next;
11.59 - struct stat buf;
11.60 -
11.61 - /* Create all sub-directories in dir. We know root exists and
11.62 - * is a dir, root does not end in a '/', and path either has a
11.63 - * leading '/' or (on MS-Windows only) root is the empty string
11.64 - * and path starts with drive (eg., "c:/windows"). */
11.65 -
11.66 - strcpy(buffer, root);
11.67 - p = buffer + strlen(buffer);
11.68 - slash = path;
11.69 - for (slash = path; *slash != '\0'; slash = next) {
11.70 - next = strchr(slash + 1, '/');
11.71 - if (next == NULL)
11.72 - break;
11.73 -
11.74 - memcpy(p, slash, next - slash);
11.75 - p += next - slash;
11.76 - *p = '\0';
11.77 -
11.78 - if (razor_valid_root_name(buffer))
11.79 - continue;
11.80 -
11.81 - if (stat(buffer, &buf) == 0) {
11.82 - if (!S_ISDIR(buf.st_mode)) {
11.83 - fprintf(stderr,
11.84 - "%s exists but is not a directory\n",
11.85 - buffer);
11.86 - return -1;
11.87 - }
11.88 - } else if (mkdir(buffer, 0777) < 0) {
11.89 - fprintf(stderr, "failed to make directory %s: %s\n",
11.90 - buffer, strerror(errno));
11.91 - return -1;
11.92 - }
11.93 -
11.94 - /* FIXME: What to do about permissions for dirs we
11.95 - * have to create but are not in the cpio archive? */
11.96 - }
11.97 -
11.98 - return 0;
11.99 -}
11.100 -
11.101 -int
11.102 -razor_remove(const char *path)
11.103 -{
11.104 -#ifdef MSWIN_API
11.105 - DWORD err;
11.106 -
11.107 - if (DeleteFile(path))
11.108 - return 0;
11.109 -
11.110 - err = GetLastError();
11.111 - if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND)
11.112 - return 0;
11.113 -
11.114 - if (SetFileAttributes(path, FILE_ATTRIBUTE_NORMAL) && DeleteFile(path))
11.115 - return 0;
11.116 -
11.117 - if (RemoveDirectory(path) || GetLastError() == ERROR_DIR_NOT_EMPTY)
11.118 - return 0;
11.119 -
11.120 - /*
11.121 - * It would be tempting to use:
11.122 - * MoveFileEx(path, NULL, MOVEFILE_DELAY_UNTIL_REBOOT)
11.123 - * but unless we can guarantee that the system will be rebooted
11.124 - * before we (or some other application) write another file with the
11.125 - * same path, this is likely to cause more problems than it solves.
11.126 - */
11.127 -
11.128 - /* Use remove() as a fallback so that errno is set appropriately */
11.129 -#endif
11.130 -
11.131 - return remove(path);
11.132 -}
11.133 -
11.134 -int
11.135 -razor_write(int fd, const void *data, size_t size)
11.136 -{
11.137 - size_t rest;
11.138 - ssize_t written;
11.139 - const unsigned char *p;
11.140 -
11.141 - rest = size;
11.142 - p = data;
11.143 - while (rest > 0) {
11.144 - written = write(fd, p, rest);
11.145 - if (written < 0) {
11.146 - perror("write error");
11.147 - return -1;
11.148 - }
11.149 - rest -= written;
11.150 - p += written;
11.151 - }
11.152 -
11.153 - return 0;
11.154 -}
11.155 -
11.156 void *
11.157 razor_file_get_contents(const char *filename, size_t *length)
11.158 {
11.159 @@ -225,7 +99,6 @@
11.160 return addr;
11.161 }
11.162
11.163 -int
11.164 razor_file_free_contents(void *addr, size_t length)
11.165 {
11.166 #if HAVE_SYS_MMAN_H
11.167 @@ -396,3 +269,66 @@
11.168 array_release(&env->string_pool);
11.169 array_release(&env->vars);
11.170 }
11.171 +
11.172 +RAZOR_EXPORT char *razor_concat(const char *s, ...)
11.173 +{
11.174 + va_list args;
11.175 + const char *string;
11.176 + char *concat;
11.177 + size_t n, len;
11.178 +
11.179 + va_start(args, s);
11.180 +
11.181 + len = strlen(s);
11.182 + while((string = va_arg(args, const char *)))
11.183 + len += strlen(string);
11.184 +
11.185 + va_end(args);
11.186 +
11.187 + concat = malloc(len + 1);
11.188 +
11.189 + if (!concat)
11.190 + return NULL;
11.191 +
11.192 + va_start(args, s);
11.193 +
11.194 + len = strlen(s);
11.195 + memcpy(concat, s, len);
11.196 + n = len;
11.197 + while((string = va_arg(args, const char *))) {
11.198 + len = strlen(string);
11.199 + memcpy(concat + n, string, len);
11.200 + n += len;
11.201 + }
11.202 +
11.203 + va_end(args);
11.204 +
11.205 + concat[n] = '\0';
11.206 +
11.207 + return concat;
11.208 +}
11.209 +
11.210 +RAZOR_EXPORT const char *razor_system_arch(void)
11.211 +{
11.212 +#ifdef MSWIN_API
11.213 + SYSTEM_INFO si;
11.214 +
11.215 + GetNativeSystemInfo(&si);
11.216 + switch(si.wProcessorArchitecture)
11.217 + {
11.218 + case PROCESSOR_ARCHITECTURE_INTEL:
11.219 + return "i686";
11.220 + case PROCESSOR_ARCHITECTURE_AMD64:
11.221 + return "x86_64";
11.222 + default:
11.223 + return NULL;
11.224 + }
11.225 +#else
11.226 + static struct utsname un;
11.227 +
11.228 + if (uname(&un))
11.229 + return NULL;
11.230 + else
11.231 + return un.machine;
11.232 +#endif
11.233 +}
12.1 --- a/src/main.c Thu Aug 25 14:22:52 2011 +0100
12.2 +++ b/src/main.c Thu Nov 10 10:35:21 2011 +0000
12.3 @@ -1,7 +1,7 @@
12.4 /*
12.5 * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
12.6 * Copyright (C) 2008 Red Hat, Inc
12.7 - * Copyright (C) 2009 J. Ali Harlow <ali@juiblex.co.uk>
12.8 + * Copyright (C) 2009, 2011 J. Ali Harlow <ali@juiblex.co.uk>
12.9 *
12.10 * This program is free software; you can redistribute it and/or modify
12.11 * it under the terms of the GNU General Public License as published by
12.12 @@ -49,8 +49,11 @@
12.13 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
12.14
12.15 static int
12.16 -update_packages(struct razor_transaction *trans, struct razor_set *system,
12.17 - struct razor_set *next, struct razor_relocations *relocations);
12.18 +update_packages(struct razor_transaction *trans,
12.19 + struct razor_install_iterator *ii, struct razor_set *system,
12.20 + struct razor_set *next, struct razor_atomic *atomic,
12.21 + struct razor_relocations *relocations,
12.22 + enum razor_stage_type stage);
12.23
12.24 static struct razor_package_iterator *
12.25 create_iterator_from_argv(struct razor_set *set, int argc, const char *argv[])
12.26 @@ -113,6 +116,7 @@
12.27 command_list(int argc, const char *argv[])
12.28 {
12.29 struct razor_package_iterator *pi;
12.30 + struct razor_atomic *atomic;
12.31 struct razor_set *set;
12.32 uint32_t flags = 0;
12.33 int i = 0;
12.34 @@ -122,14 +126,19 @@
12.35 i++;
12.36 }
12.37
12.38 - set = razor_root_open_read_only(install_root);
12.39 - if (set == NULL)
12.40 + atomic = razor_atomic_open("List installed packages");
12.41 + set = razor_root_open_read_only(install_root, atomic);
12.42 + if (set == NULL) {
12.43 + fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
12.44 + razor_atomic_destroy(atomic);
12.45 return 1;
12.46 + }
12.47
12.48 pi = create_iterator_from_argv(set, argc - i, argv + i);
12.49 list_packages(pi, flags);
12.50 razor_package_iterator_destroy(pi);
12.51 - razor_set_destroy(set);
12.52 + razor_set_unref(set);
12.53 + razor_atomic_destroy(atomic);
12.54
12.55 return 0;
12.56 }
12.57 @@ -175,13 +184,18 @@
12.58 list_properties(int argc, const char *argv[], uint32_t type)
12.59 {
12.60 struct razor_set *set;
12.61 + struct razor_atomic *atomic;
12.62 struct razor_package *package;
12.63 struct razor_package_iterator *pi;
12.64 const char *name, *version, *arch;
12.65
12.66 - set = razor_root_open_read_only(install_root);
12.67 - if (set == NULL)
12.68 + atomic = razor_atomic_open("List package properties");
12.69 + set = razor_root_open_read_only(install_root, atomic);
12.70 + if (set == NULL) {
12.71 + fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
12.72 + razor_atomic_destroy(atomic);
12.73 return 1;
12.74 + }
12.75
12.76 pi = create_iterator_from_argv(set, argc, argv);
12.77 while (razor_package_iterator_next(pi, &package,
12.78 @@ -191,7 +205,8 @@
12.79 RAZOR_DETAIL_LAST))
12.80 list_package_properties(set, package, type);
12.81 razor_package_iterator_destroy(pi);
12.82 - razor_set_destroy(set);
12.83 + razor_set_unref(set);
12.84 + razor_atomic_destroy(atomic);
12.85
12.86 return 0;
12.87 }
12.88 @@ -224,13 +239,18 @@
12.89 command_list_scripts(int argc, const char *argv[])
12.90 {
12.91 struct razor_set *set;
12.92 + struct razor_atomic *atomic;
12.93 struct razor_package *package;
12.94 struct razor_package_iterator *pi;
12.95 const char *preunprog, *preun, *postunprog, *postun;
12.96
12.97 - set = razor_root_open_read_only(install_root);
12.98 - if (set == NULL)
12.99 + atomic = razor_atomic_open("List package scripts");
12.100 + set = razor_root_open_read_only(install_root, atomic);
12.101 + if (set == NULL) {
12.102 + fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
12.103 + razor_atomic_destroy(atomic);
12.104 return 1;
12.105 + }
12.106
12.107 pi = create_iterator_from_argv(set, argc, argv);
12.108 while (razor_package_iterator_next(pi, &package,
12.109 @@ -253,7 +273,8 @@
12.110 }
12.111 }
12.112 razor_package_iterator_destroy(pi);
12.113 - razor_set_destroy(set);
12.114 + razor_set_unref(set);
12.115 + razor_atomic_destroy(atomic);
12.116
12.117 return 0;
12.118 }
12.119 @@ -261,14 +282,20 @@
12.120 static int
12.121 command_list_files(int argc, const char *argv[])
12.122 {
12.123 + struct razor_atomic *atomic;
12.124 struct razor_set *set;
12.125
12.126 - set = razor_root_open_read_only(install_root);
12.127 - if (set == NULL)
12.128 + atomic = razor_atomic_open("List package files");
12.129 + set = razor_root_open_read_only(install_root, atomic);
12.130 + if (set == NULL) {
12.131 + fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
12.132 + razor_atomic_destroy(atomic);
12.133 return 1;
12.134 + }
12.135
12.136 razor_set_list_files(set, argv[0]);
12.137 - razor_set_destroy(set);
12.138 + razor_set_unref(set);
12.139 + razor_atomic_destroy(atomic);
12.140
12.141 return 0;
12.142 }
12.143 @@ -276,18 +303,24 @@
12.144 static int
12.145 command_list_file_packages(int argc, const char *argv[])
12.146 {
12.147 + struct razor_atomic *atomic;
12.148 struct razor_set *set;
12.149 struct razor_package_iterator *pi;
12.150
12.151 - set = razor_root_open_read_only(install_root);
12.152 - if (set == NULL)
12.153 + atomic = razor_atomic_open("List file packages");
12.154 + set = razor_root_open_read_only(install_root, atomic);
12.155 + if (set == NULL) {
12.156 + fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
12.157 + razor_atomic_destroy(atomic);
12.158 return 1;
12.159 + }
12.160
12.161 pi = razor_package_iterator_create_for_file(set, argv[0]);
12.162 list_packages(pi, 0);
12.163 razor_package_iterator_destroy(pi);
12.164
12.165 - razor_set_destroy(set);
12.166 + razor_set_unref(set);
12.167 + razor_atomic_destroy(atomic);
12.168
12.169 return 0;
12.170 }
12.171 @@ -295,14 +328,19 @@
12.172 static int
12.173 command_list_package_files(int argc, const char *argv[])
12.174 {
12.175 + struct razor_atomic *atomic;
12.176 struct razor_set *set;
12.177 struct razor_package_iterator *pi;
12.178 struct razor_package *package;
12.179 const char *name, *version, *arch;
12.180
12.181 - set = razor_root_open_read_only(install_root);
12.182 - if (set == NULL)
12.183 + atomic = razor_atomic_open("List package files");
12.184 + set = razor_root_open_read_only(install_root, atomic);
12.185 + if (set == NULL) {
12.186 + fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
12.187 + razor_atomic_destroy(atomic);
12.188 return 1;
12.189 + }
12.190
12.191 pi = create_iterator_from_argv(set, argc, argv);
12.192 while (razor_package_iterator_next(pi, &package,
12.193 @@ -313,7 +351,8 @@
12.194 razor_set_list_package_files(set, package);
12.195 razor_package_iterator_destroy(pi);
12.196
12.197 - razor_set_destroy(set);
12.198 + razor_set_unref(set);
12.199 + razor_atomic_destroy(atomic);
12.200
12.201 return 0;
12.202 }
12.203 @@ -323,6 +362,7 @@
12.204 const char *ref_version,
12.205 uint32_t type)
12.206 {
12.207 + struct razor_atomic *atomic;
12.208 struct razor_set *set;
12.209 struct razor_property *property;
12.210 struct razor_property_iterator *prop_iter;
12.211 @@ -333,9 +373,13 @@
12.212 if (ref_name == NULL)
12.213 return 0;
12.214
12.215 - set = razor_root_open_read_only(install_root);
12.216 - if (set == NULL)
12.217 + atomic = razor_atomic_open("List package properties");
12.218 + set = razor_root_open_read_only(install_root, atomic);
12.219 + if (set == NULL) {
12.220 + fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
12.221 + razor_atomic_destroy(atomic);
12.222 return 1;
12.223 + }
12.224
12.225 prop_iter = razor_property_iterator_create(set, NULL);
12.226 while (razor_property_iterator_next(prop_iter, &property,
12.227 @@ -357,7 +401,8 @@
12.228 }
12.229 razor_property_iterator_destroy(prop_iter);
12.230
12.231 - razor_set_destroy(set);
12.232 + razor_set_unref(set);
12.233 + razor_atomic_destroy(atomic);
12.234
12.235 return 0;
12.236 }
12.237 @@ -454,7 +499,9 @@
12.238 static int
12.239 command_import_yum(int argc, const char *argv[])
12.240 {
12.241 + int retval;
12.242 struct razor_set *set;
12.243 + struct razor_atomic *atomic;
12.244 char buffer[512];
12.245
12.246 printf("downloading from %s.\n", yum_url);
12.247 @@ -470,14 +517,17 @@
12.248 set = razor_set_create_from_yum();
12.249 if (set == NULL)
12.250 return 1;
12.251 - if (razor_set_write(set, rawhide_repo_filename, RAZOR_SECTION_ALL)) {
12.252 - perror(rawhide_repo_filename);
12.253 - return -1;
12.254 - }
12.255 - razor_set_destroy(set);
12.256 - printf("wrote %s\n", rawhide_repo_filename);
12.257 + atomic = razor_atomic_open("Yum import repository");
12.258 + razor_set_write(set, atomic, rawhide_repo_filename, RAZOR_SECTION_ALL);
12.259 + retval = razor_atomic_commit(atomic);
12.260 + razor_set_unref(set);
12.261 + if (retval)
12.262 + fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
12.263 + else
12.264 + printf("wrote %s\n", rawhide_repo_filename);
12.265 + razor_atomic_destroy(atomic);
12.266
12.267 - return 0;
12.268 + return retval;
12.269 }
12.270
12.271 #if HAVE_RPMLIB
12.272 @@ -486,10 +536,17 @@
12.273 {
12.274 struct razor_set *set;
12.275 struct razor_root *root;
12.276 + struct razor_atomic *atomic;
12.277 + int retval;
12.278
12.279 - root = razor_root_open(install_root);
12.280 - if (root == NULL)
12.281 + atomic = razor_atomic_open("Import RPM database");
12.282 +
12.283 + root = razor_root_open(install_root, atomic);
12.284 + if (root == NULL) {
12.285 + fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
12.286 + razor_atomic_destroy(atomic);
12.287 return 1;
12.288 + }
12.289
12.290 set = razor_set_create_from_rpmdb();
12.291 if (set == NULL)
12.292 @@ -497,7 +554,13 @@
12.293
12.294 razor_root_update(root, set);
12.295
12.296 - return razor_root_commit(root);
12.297 + retval = razor_root_commit(root);
12.298 + if (retval)
12.299 + fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
12.300 +
12.301 + razor_atomic_destroy(atomic);
12.302 +
12.303 + return retval;
12.304 }
12.305 #endif
12.306
12.307 @@ -553,45 +616,69 @@
12.308 struct razor_root *root;
12.309 struct razor_set *system, *upstream, *next;
12.310 struct razor_transaction *trans;
12.311 - int i, errors;
12.312 + struct razor_atomic *atomic;
12.313 + struct razor_install_iterator *ii;
12.314 + int i, retval;
12.315
12.316 - root = razor_root_open(install_root);
12.317 - system = razor_root_get_system_set(root);
12.318 + atomic = razor_atomic_open("Remove packages");
12.319 +
12.320 + root = razor_root_open(install_root, atomic);
12.321 + system = razor_set_ref(razor_root_get_system_set(root));
12.322 if (system == NULL) {
12.323 + fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
12.324 razor_root_close(root);
12.325 + razor_atomic_destroy(atomic);
12.326 return 1;
12.327 }
12.328
12.329 upstream = razor_set_create_without_root();
12.330 trans = razor_transaction_create(system, upstream);
12.331 + razor_set_unref(upstream);
12.332 for (i = 0; i < argc; i++) {
12.333 if (mark_packages_for_removal(trans, system, argv[i]) == 0) {
12.334 fprintf(stderr, "no match for %s\n", argv[i]);
12.335 razor_transaction_destroy(trans);
12.336 - razor_set_destroy(upstream);
12.337 + razor_set_unref(system);
12.338 razor_root_close(root);
12.339 + razor_atomic_destroy(atomic);
12.340 return 1;
12.341 }
12.342 }
12.343
12.344 razor_transaction_resolve(trans);
12.345 - errors = razor_transaction_describe(trans);
12.346 - if (errors) {
12.347 + retval = razor_transaction_describe(trans);
12.348 + if (retval) {
12.349 razor_transaction_destroy(trans);
12.350 - razor_set_destroy(upstream);
12.351 + razor_set_unref(system);
12.352 razor_root_close(root);
12.353 + razor_atomic_destroy(atomic);
12.354 return 1;
12.355 }
12.356
12.357 next = razor_transaction_commit(trans);
12.358 - update_packages(trans, system, next, NULL);
12.359 + ii = razor_set_create_install_iterator(system, next);
12.360 + update_packages(trans, ii, system, next, atomic, NULL,
12.361 + RAZOR_STAGE_SCRIPTS_PRE);
12.362 + update_packages(trans, ii, system, next, atomic, NULL,
12.363 + RAZOR_STAGE_FILES);
12.364 +
12.365 razor_root_update(root, next);
12.366
12.367 + (void)razor_root_commit(root);
12.368 + retval = razor_atomic_commit(atomic);
12.369 + if (retval)
12.370 + fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
12.371 + else
12.372 + update_packages(trans, ii, system, next, atomic, NULL,
12.373 + RAZOR_STAGE_SCRIPTS_POST);
12.374 + razor_install_iterator_destroy(ii);
12.375 +
12.376 razor_transaction_destroy(trans);
12.377 - razor_set_destroy(next);
12.378 - razor_set_destroy(upstream);
12.379 + razor_atomic_destroy(atomic);
12.380 + razor_set_unref(system);
12.381 + razor_set_unref(next);
12.382
12.383 - return razor_root_commit(root);
12.384 + return retval;
12.385 }
12.386
12.387 static void
12.388 @@ -611,17 +698,23 @@
12.389 static int
12.390 command_diff(int argc, const char *argv[])
12.391 {
12.392 + struct razor_atomic *atomic;
12.393 struct razor_set *set, *updated;
12.394
12.395 - set = razor_root_open_read_only(install_root);
12.396 - updated = razor_set_open(rawhide_repo_filename);
12.397 - if (set == NULL || updated == NULL)
12.398 + atomic = razor_atomic_open("Show package differences");
12.399 + set = razor_root_open_read_only(install_root, atomic);
12.400 + updated = razor_set_open(rawhide_repo_filename, atomic);
12.401 + if (set == NULL || updated == NULL) {
12.402 + fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
12.403 + razor_atomic_destroy(atomic);
12.404 return 1;
12.405 + }
12.406
12.407 razor_set_diff(set, updated, print_diff, NULL);
12.408
12.409 - razor_set_destroy(set);
12.410 - razor_set_destroy(updated);
12.411 + razor_set_unref(set);
12.412 + razor_set_unref(updated);
12.413 + razor_atomic_destroy(atomic);
12.414
12.415 return 0;
12.416 }
12.417 @@ -634,9 +727,11 @@
12.418 struct razor_importer *importer;
12.419 struct razor_set *set;
12.420 struct razor_rpm *rpm;
12.421 + struct razor_atomic *atomic;
12.422 int len, imported_count = 0;
12.423 char filename[256];
12.424 const char *dirname = argv[0];
12.425 + int retval;
12.426
12.427 if (dirname == NULL) {
12.428 fprintf(stderr, "usage: razor import-rpms DIR\n");
12.429 @@ -654,15 +749,17 @@
12.430 while (de = readdir(dir), de != NULL) {
12.431 len = strlen(de->d_name);
12.432 if (len < 5 || strcmp(de->d_name + len - 4, ".rpm") != 0)
12.433 - continue;
12.434 + continue;
12.435 snprintf(filename, sizeof filename,
12.436 "%s/%s", dirname, de->d_name);
12.437 - rpm = razor_rpm_open(filename);
12.438 - if (rpm == NULL) {
12.439 - fprintf(stderr,
12.440 - "failed to open rpm \"%s\"\n", filename);
12.441 + atomic = razor_atomic_open("Read RPM");
12.442 + rpm = razor_rpm_open(filename, atomic);
12.443 + if (rpm == NULL)
12.444 + fprintf(stderr, "%s\n",
12.445 + razor_atomic_get_error_msg(atomic));
12.446 + razor_atomic_destroy(atomic);
12.447 + if (rpm == NULL)
12.448 continue;
12.449 - }
12.450 if (razor_importer_add_rpm(importer, rpm)) {
12.451 fprintf(stderr, "couldn't import %s\n", filename);
12.452 break;
12.453 @@ -681,17 +778,22 @@
12.454 printf("\nsaving\n");
12.455 set = razor_importer_finish(importer);
12.456
12.457 - razor_set_write(set, repo_filename, RAZOR_SECTION_ALL);
12.458 - razor_set_destroy(set);
12.459 - printf("wrote %s\n", repo_filename);
12.460 + atomic = razor_atomic_open("Update system database");
12.461 + razor_set_write(set, atomic, repo_filename, RAZOR_SECTION_ALL);
12.462 + razor_set_unref(set);
12.463 + retval = razor_atomic_commit(atomic);
12.464 + if (retval)
12.465 + fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
12.466 + else
12.467 + printf("wrote %s\n", repo_filename);
12.468 + razor_atomic_destroy(atomic);
12.469
12.470 - return 0;
12.471 + return retval;
12.472 }
12.473
12.474 -static const char *
12.475 +static char *
12.476 rpm_filename(const char *name, const char *version, const char *arch)
12.477 {
12.478 - static char file[PATH_MAX];
12.479 const char *v;
12.480
12.481 /* Skip epoch */
12.482 @@ -701,9 +803,7 @@
12.483 else
12.484 v = version;
12.485
12.486 - snprintf(file, sizeof file, "%s-%s.%s.rpm", name, v, arch);
12.487 -
12.488 - return file;
12.489 + return razor_concat(name, "-", v, ".", arch, ".rpm", NULL);
12.490 }
12.491
12.492 static int
12.493 @@ -713,7 +813,7 @@
12.494 struct razor_package *package;
12.495 enum razor_install_action action;
12.496 const char *name, *version, *arch;
12.497 - char file[PATH_MAX], url[256];
12.498 + char *file, *url, *s;
12.499 int errors = 0, count;
12.500
12.501 ii = razor_set_create_install_iterator(system, next);
12.502 @@ -727,13 +827,14 @@
12.503 RAZOR_DETAIL_ARCH, &arch,
12.504 RAZOR_DETAIL_LAST);
12.505
12.506 - snprintf(url, sizeof url,
12.507 - "%s/Packages/%s",
12.508 - yum_url, rpm_filename(name, version, arch));
12.509 - snprintf(file, sizeof file,
12.510 - "rpms/%s", rpm_filename(name, version, arch));
12.511 + s = rpm_filename(name, version, arch);
12.512 + url = razor_concat(yum_url, "/Packages/", s, NULL);
12.513 + file = razor_concat("rpms/", s, NULL);
12.514 + free(s);
12.515 if (download_if_missing(url, file) < 0)
12.516 errors++;
12.517 + free(file);
12.518 + free(url);
12.519 }
12.520 razor_install_iterator_destroy(ii);
12.521
12.522 @@ -746,7 +847,8 @@
12.523 }
12.524
12.525 static struct razor_set *
12.526 -relocate_packages(struct razor_set *set, struct razor_relocations *relocations)
12.527 +relocate_packages(struct razor_set *set, struct razor_atomic *atomic,
12.528 + struct razor_relocations *relocations)
12.529 {
12.530 int i;
12.531 struct razor_importer *importer;
12.532 @@ -760,7 +862,7 @@
12.533 const char *preunprog, *preun, *postunprog, *postun;
12.534 const char *install_prefix;
12.535 const char *const *prefixes;
12.536 - char file[PATH_MAX];
12.537 + char *file, *s;
12.538 uint32_t flags;
12.539
12.540 importer = razor_importer_create();
12.541 @@ -779,11 +881,12 @@
12.542 RAZOR_DETAIL_POSTUNPROG, &postunprog,
12.543 RAZOR_DETAIL_POSTUN, &postun,
12.544 RAZOR_DETAIL_LAST)) {
12.545 - snprintf(file, sizeof file,
12.546 - "rpms/%s", rpm_filename(name, version, arch));
12.547 - rpm = razor_rpm_open(file);
12.548 + s = rpm_filename(name, version, arch);
12.549 + file = razor_concat("rpms/", s, NULL);
12.550 + free(s);
12.551 + rpm = razor_rpm_open(file, atomic);
12.552 + free(file);
12.553 if (rpm == NULL) {
12.554 - fprintf(stderr, "failed to open rpm %s\n", file);
12.555 razor_package_iterator_destroy(pkg_iter);
12.556 razor_importer_destroy(importer);
12.557 return NULL;
12.558 @@ -834,12 +937,13 @@
12.559
12.560 static int
12.561 install_package(struct razor_transaction *trans, struct razor_set *set,
12.562 - struct razor_package *package,
12.563 - struct razor_relocations *relocations)
12.564 + struct razor_atomic *atomic, struct razor_package *package,
12.565 + struct razor_relocations *relocations, int install_count,
12.566 + enum razor_stage_type stage)
12.567 {
12.568 int retval;
12.569 const char *name, *version, *arch;
12.570 - char file[PATH_MAX];
12.571 + char *file, *s;
12.572 struct razor_rpm *rpm;
12.573
12.574 razor_package_get_details(set, package,
12.575 @@ -848,45 +952,57 @@
12.576 RAZOR_DETAIL_ARCH, &arch,
12.577 RAZOR_DETAIL_LAST);
12.578
12.579 - printf("install %s-%s\n", name, version);
12.580 + if (stage & RAZOR_STAGE_SCRIPTS_PRE)
12.581 + printf("install %s-%s\n", name, version);
12.582
12.583 - snprintf(file, sizeof file,
12.584 - "rpms/%s", rpm_filename(name, version, arch));
12.585 - rpm = razor_rpm_open(file);
12.586 + s = rpm_filename(name, version, arch);
12.587 + file = razor_concat("rpms/", s, NULL);
12.588 + free(s);
12.589 + rpm = razor_rpm_open(file, atomic);
12.590 + free(file);
12.591 if (rpm == NULL) {
12.592 - fprintf(stderr, "failed to open rpm %s\n", file);
12.593 + fprintf(stderr, "%s\n",
12.594 + razor_atomic_get_error_msg(atomic));
12.595 return -1;
12.596 }
12.597 if (relocations)
12.598 razor_rpm_set_relocations(rpm, relocations);
12.599 razor_transaction_fixup_package(trans, package, rpm);
12.600 - retval = razor_rpm_install(rpm, install_root, 1);
12.601 - if (retval < 0)
12.602 - fprintf(stderr, "failed to install rpm %s\n", file);
12.603 + retval = razor_rpm_install(rpm, atomic, install_root, install_count,
12.604 + stage);
12.605 + if (retval < 0) {
12.606 + s = rpm_filename(name, version, arch);
12.607 + fprintf(stderr, "%s: %s\n", s,
12.608 + razor_atomic_get_error_msg(atomic));
12.609 + free(s);
12.610 + }
12.611 razor_rpm_close(rpm);
12.612 return retval;
12.613 }
12.614
12.615 static int
12.616 -update_packages(struct razor_transaction *trans, struct razor_set *system,
12.617 - struct razor_set *next, struct razor_relocations *relocations)
12.618 +update_packages(struct razor_transaction *trans,
12.619 + struct razor_install_iterator *ii, struct razor_set *system,
12.620 + struct razor_set *next, struct razor_atomic *atomic,
12.621 + struct razor_relocations *relocations,
12.622 + enum razor_stage_type stage)
12.623 {
12.624 - struct razor_install_iterator *ii;
12.625 struct razor_package *package;
12.626 enum razor_install_action action;
12.627 int retval = 0, count;
12.628
12.629 - ii = razor_set_create_install_iterator(system, next);
12.630 + razor_install_iterator_rewind(ii);
12.631 +
12.632 while (!retval && razor_install_iterator_next(ii, &package,
12.633 &action, &count)) {
12.634 if (action == RAZOR_INSTALL_ACTION_ADD)
12.635 - retval = install_package(trans, next, package,
12.636 - relocations);
12.637 + retval = install_package(trans, next, atomic, package,
12.638 + relocations, count, stage);
12.639 else if (action == RAZOR_INSTALL_ACTION_REMOVE)
12.640 - retval = razor_package_remove(system, next, package,
12.641 - install_root, count);
12.642 + retval = razor_package_remove(system, next, atomic,
12.643 + package, install_root,
12.644 + count, stage);
12.645 }
12.646 - razor_install_iterator_destroy(ii);
12.647
12.648 return retval;
12.649 }
12.650 @@ -898,12 +1014,22 @@
12.651 struct razor_relocations *relocations=NULL;
12.652 struct razor_set *system, *upstream, *next, *set;
12.653 struct razor_transaction *trans;
12.654 - int i, len, dependencies = 1;
12.655 + struct razor_atomic *atomic;
12.656 + struct razor_install_iterator *ii;
12.657 + int i, retval, len, dependencies = 1;
12.658 char *oldpath;
12.659
12.660 - root = razor_root_open(install_root);
12.661 - if (root == NULL)
12.662 + if (do_update)
12.663 + atomic = razor_atomic_open("Update packages");
12.664 + else
12.665 + atomic = razor_atomic_open("Install packages");
12.666 +
12.667 + root = razor_root_open(install_root, atomic);
12.668 + if (root == NULL) {
12.669 + fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
12.670 + razor_atomic_destroy(atomic);
12.671 return 1;
12.672 + }
12.673
12.674 for (i = 0; i < argc; i++) {
12.675 if (strcmp(argv[i], "--no-dependencies") == 0)
12.676 @@ -933,19 +1059,30 @@
12.677 break;
12.678 }
12.679
12.680 - system = razor_root_get_system_set(root);
12.681 - upstream = razor_set_open(rawhide_repo_filename);
12.682 + upstream = razor_set_open(rawhide_repo_filename, atomic);
12.683 if (upstream == NULL) {
12.684 + fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
12.685 razor_root_close(root);
12.686 + razor_atomic_destroy(atomic);
12.687 return 1;
12.688 }
12.689
12.690 if (relocations) {
12.691 - set = relocate_packages(upstream, relocations);
12.692 - razor_set_destroy(upstream);
12.693 + set = relocate_packages(upstream, atomic, relocations);
12.694 + if (set == NULL) {
12.695 + fprintf(stderr, "%s\n",
12.696 + razor_atomic_get_error_msg(atomic));
12.697 + razor_root_close(root);
12.698 + razor_atomic_destroy(atomic);
12.699 + razor_set_unref(upstream);
12.700 + return 1;
12.701 + }
12.702 + razor_set_unref(upstream);
12.703 upstream = set;
12.704 }
12.705
12.706 + system = razor_set_ref(razor_root_get_system_set(root));
12.707 +
12.708 trans = razor_transaction_create(system, upstream);
12.709
12.710 if (i == argc && do_update)
12.711 @@ -957,8 +1094,10 @@
12.712 if (mark_packages_for_update(trans, upstream, argv[i]) == 0) {
12.713 fprintf(stderr, "no package matched %s\n", argv[i]);
12.714 razor_transaction_destroy(trans);
12.715 - razor_set_destroy(upstream);
12.716 + razor_set_unref(upstream);
12.717 + razor_set_unref(system);
12.718 razor_root_close(root);
12.719 + razor_atomic_destroy(atomic);
12.720 return 1;
12.721 }
12.722 }
12.723 @@ -967,41 +1106,67 @@
12.724 razor_transaction_resolve(trans);
12.725 if (razor_transaction_describe(trans) > 0) {
12.726 razor_transaction_destroy(trans);
12.727 - razor_set_destroy(upstream);
12.728 + razor_set_unref(upstream);
12.729 + razor_set_unref(system);
12.730 razor_root_close(root);
12.731 + razor_atomic_destroy(atomic);
12.732 return 1;
12.733 }
12.734 }
12.735
12.736 - if (mkdir("rpms", 0777) && errno != EEXIST) {
12.737 - fprintf(stderr, "failed to create rpms directory.\n");
12.738 + if (razor_atomic_create_dir(atomic, "rpms",
12.739 + S_IRWXU | S_IRWXG | S_IRWXO)) {
12.740 + fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
12.741 razor_transaction_destroy(trans);
12.742 - razor_set_destroy(upstream);
12.743 + razor_set_unref(upstream);
12.744 + razor_set_unref(system);
12.745 razor_root_close(root);
12.746 + razor_atomic_destroy(atomic);
12.747 return 1;
12.748 }
12.749
12.750 next = razor_transaction_commit(trans);
12.751
12.752 if (download_packages(system, next) < 0) {
12.753 - razor_set_destroy(next);
12.754 + razor_set_unref(next);
12.755 razor_transaction_destroy(trans);
12.756 - razor_set_destroy(upstream);
12.757 + razor_set_unref(upstream);
12.758 + razor_set_unref(system);
12.759 razor_root_close(root);
12.760 + razor_atomic_destroy(atomic);
12.761 return 1;
12.762 }
12.763
12.764 - update_packages(trans, system, next, relocations);
12.765 + ii = razor_set_create_install_iterator(system, next);
12.766 +
12.767 + update_packages(trans, ii, system, next, atomic, relocations,
12.768 + RAZOR_STAGE_SCRIPTS_PRE);
12.769 + update_packages(trans, ii, system, next, atomic, relocations,
12.770 + RAZOR_STAGE_FILES);
12.771
12.772 razor_root_update(root, next);
12.773
12.774 + razor_set_unref(upstream);
12.775 +
12.776 + (void)razor_root_commit(root);
12.777 + retval = razor_atomic_commit(atomic);
12.778 + if (retval)
12.779 + fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
12.780 + else
12.781 + update_packages(trans, ii, system, next, atomic, relocations,
12.782 + RAZOR_STAGE_SCRIPTS_POST);
12.783 +
12.784 razor_transaction_destroy(trans);
12.785 if (relocations)
12.786 razor_relocations_destroy(relocations);
12.787 - razor_set_destroy(next);
12.788 - razor_set_destroy(upstream);
12.789 + razor_install_iterator_destroy(ii);
12.790
12.791 - return razor_root_commit(root);
12.792 + razor_atomic_destroy(atomic);
12.793 +
12.794 + razor_set_unref(next);
12.795 + razor_set_unref(system);
12.796 +
12.797 + return retval;
12.798 }
12.799
12.800 static int
12.801 @@ -1025,6 +1190,7 @@
12.802 static int
12.803 command_download(int argc, const char *argv[])
12.804 {
12.805 + struct razor_atomic *atomic;
12.806 struct razor_set *set;
12.807 struct razor_package_iterator *pi;
12.808 struct razor_package *package;
12.809 @@ -1032,12 +1198,24 @@
12.810 char url[256], file[256];
12.811 int matches = 0;
12.812
12.813 - if (mkdir("rpms", 0777) && errno != EEXIST) {
12.814 - fprintf(stderr, "failed to create rpms directory.\n");
12.815 + atomic = razor_atomic_open("Download packages");
12.816 +
12.817 + if (razor_atomic_create_dir(atomic, "rpms",
12.818 + S_IRWXU | S_IRWXG | S_IRWXO)) {
12.819 + fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
12.820 + razor_atomic_destroy(atomic);
12.821 return 1;
12.822 }
12.823
12.824 - set = razor_set_open(rawhide_repo_filename);
12.825 + set = razor_set_open(rawhide_repo_filename, atomic);
12.826 +
12.827 + if (razor_atomic_commit(atomic)) {
12.828 + fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
12.829 + razor_atomic_destroy(atomic);
12.830 + return 1;
12.831 + }
12.832 + razor_atomic_destroy(atomic);
12.833 +
12.834 pi = razor_package_iterator_create(set);
12.835 while (razor_package_iterator_next(pi, &package,
12.836 RAZOR_DETAIL_NAME, &name,
12.837 @@ -1056,7 +1234,7 @@
12.838 download_if_missing(url, file);
12.839 }
12.840 razor_package_iterator_destroy(pi);
12.841 - razor_set_destroy(set);
12.842 + razor_set_unref(set);
12.843
12.844 if (matches == 0)
12.845 fprintf(stderr, "no packages matched \"%s\"\n", pattern);
12.846 @@ -1071,15 +1249,20 @@
12.847 static int
12.848 command_info(int argc, const char *argv[])
12.849 {
12.850 + struct razor_atomic *atomic;
12.851 struct razor_set *set;
12.852 struct razor_package_iterator *pi;
12.853 struct razor_package *package;
12.854 const char *pattern = argv[0], *name, *version, *arch;
12.855 const char *summary, *description, *url, *license;
12.856
12.857 - set = razor_root_open_read_only(install_root);
12.858 - if (set == NULL)
12.859 + atomic = razor_atomic_open("Package info");
12.860 + set = razor_root_open_read_only(install_root, atomic);
12.861 + if (set == NULL) {
12.862 + fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
12.863 + razor_atomic_destroy(atomic);
12.864 return 1;
12.865 + }
12.866
12.867 pi = razor_package_iterator_create(set);
12.868 while (razor_package_iterator_next(pi, &package,
12.869 @@ -1108,7 +1291,8 @@
12.870 printf ("\n");
12.871 }
12.872 razor_package_iterator_destroy(pi);
12.873 - razor_set_destroy(set);
12.874 + razor_set_unref(set);
12.875 + razor_atomic_destroy(atomic);
12.876
12.877 return 0;
12.878 }
12.879 @@ -1118,6 +1302,7 @@
12.880 static int
12.881 command_search(int argc, const char *argv[])
12.882 {
12.883 + struct razor_atomic *atomic;
12.884 struct razor_set *set;
12.885 struct razor_package_iterator *pi;
12.886 struct razor_package *package;
12.887 @@ -1132,9 +1317,14 @@
12.888
12.889 snprintf(pattern, sizeof pattern, "*%s*", argv[0]);
12.890
12.891 - set = razor_set_open(rawhide_repo_filename);
12.892 - if (set == NULL)
12.893 + atomic = razor_atomic_open("Search packages");
12.894 + set = razor_set_open(rawhide_repo_filename, atomic);
12.895 + if (set == NULL || razor_atomic_commit(atomic)) {
12.896 + fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
12.897 + razor_atomic_destroy(atomic);
12.898 return 1;
12.899 + }
12.900 + razor_atomic_destroy(atomic);
12.901
12.902 pi = razor_package_iterator_create(set);
12.903 while (razor_package_iterator_next(pi, &package,
12.904 @@ -1153,7 +1343,7 @@
12.905 printf("%s-%s.%s: %s\n", name, version, arch, summary);
12.906 }
12.907 razor_package_iterator_destroy(pi);
12.908 - razor_set_destroy(set);
12.909 + razor_set_unref(set);
12.910
12.911 return 0;
12.912 }
13.1 --- a/src/rpm.c Thu Aug 25 14:22:52 2011 +0100
13.2 +++ b/src/rpm.c Thu Nov 10 10:35:21 2011 +0000
13.3 @@ -1,7 +1,7 @@
13.4 /*
13.5 * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
13.6 * Copyright (C) 2008 Red Hat, Inc
13.7 - * Copyright (C) 2009 J. Ali Harlow <ali@juiblex.co.uk>
13.8 + * Copyright (C) 2009, 2011 J. Ali Harlow <ali@juiblex.co.uk>
13.9 *
13.10 * This program is free software; you can redistribute it and/or modify
13.11 * it under the terms of the GNU General Public License as published by
13.12 @@ -441,13 +441,16 @@
13.13 create_set_from_command_line(int argc, const char *argv[])
13.14 {
13.15 struct razor_importer *importer;
13.16 + struct razor_atomic *atomic;
13.17 struct razor_rpm *rpm;
13.18 int i;
13.19
13.20 importer = razor_importer_create();
13.21
13.22 for (i = 0; i < argc; i++) {
13.23 - rpm = razor_rpm_open(argv[i]);
13.24 + atomic = razor_atomic_open("Read RPM");
13.25 + rpm = razor_rpm_open(argv[i], atomic);
13.26 + razor_atomic_destroy(atomic);
13.27 if (rpm == NULL)
13.28 continue;
13.29 if (razor_importer_add_rpm(importer, rpm))
13.30 @@ -462,17 +465,25 @@
13.31 static void
13.32 command_query(int argc, const char *argv[])
13.33 {
13.34 + struct razor_atomic *atomic;
13.35 struct razor_set *set;
13.36 struct razor_package_iterator *pi;
13.37 struct razor_package *package;
13.38 const char *name, *version, *arch;
13.39
13.40 + atomic = razor_atomic_open("Query packages");
13.41 if (option_package) {
13.42 set = create_set_from_command_line(argc, argv);
13.43 argc = 0;
13.44 option_all = 1;
13.45 } else {
13.46 - set = razor_root_open_read_only(option_root);
13.47 + set = razor_root_open_read_only(option_root, atomic);
13.48 + if (!set) {
13.49 + fprintf(stderr, "%s\n",
13.50 + razor_atomic_get_error_msg(atomic));
13.51 + razor_atomic_destroy(atomic);
13.52 + return;
13.53 + }
13.54 }
13.55
13.56 pi = get_query_packages(set, argc, argv);
13.57 @@ -509,25 +520,32 @@
13.58
13.59 razor_package_iterator_destroy(pi);
13.60
13.61 - razor_set_destroy(set);
13.62 -
13.63 - return;
13.64 + razor_set_unref(set);
13.65 + razor_atomic_destroy(atomic);
13.66 }
13.67
13.68 static void
13.69 command_verify(int argc, const char *argv[])
13.70 {
13.71 + struct razor_atomic *atomic;
13.72 struct razor_set *set;
13.73 struct razor_package_iterator *pi;
13.74 struct razor_package *package;
13.75 const char *name, *version, *arch;
13.76
13.77 + atomic = razor_atomic_open("Verify packages");
13.78 if (option_package) {
13.79 set = create_set_from_command_line(argc, argv);
13.80 argc = 0;
13.81 option_all = 1;
13.82 } else {
13.83 - set = razor_root_open_read_only(option_root);
13.84 + set = razor_root_open_read_only(option_root, atomic);
13.85 + if (!set) {
13.86 + fprintf(stderr, "%s\n",
13.87 + razor_atomic_get_error_msg(atomic));
13.88 + razor_atomic_destroy(atomic);
13.89 + return;
13.90 + }
13.91 }
13.92
13.93 pi = get_query_packages(set, argc, argv);
13.94 @@ -542,6 +560,7 @@
13.95 }
13.96
13.97 razor_package_iterator_destroy(pi);
13.98 + razor_atomic_destroy(atomic);
13.99 }
13.100
13.101 static void
13.102 @@ -561,6 +580,7 @@
13.103 static void
13.104 command_erase(int argc, const char *argv[])
13.105 {
13.106 + struct razor_atomic *atomic;
13.107 struct razor_set *set, *upstream, *next;
13.108 struct razor_transaction *trans;
13.109 struct razor_package_query *query;
13.110 @@ -572,7 +592,15 @@
13.111 exit(1);
13.112 }
13.113
13.114 - set = razor_set_open(repo_filename);
13.115 + atomic = razor_atomic_open("Erase packages");
13.116 +
13.117 + set = razor_set_open(repo_filename, atomic);
13.118 + if (!set || razor_atomic_commit(atomic)) {
13.119 + fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
13.120 + razor_atomic_destroy(atomic);
13.121 + exit(1);
13.122 + }
13.123 + razor_atomic_destroy(atomic);
13.124 upstream = razor_set_create();
13.125
13.126 trans = razor_transaction_create(set, upstream);
13.127 @@ -602,15 +630,16 @@
13.128 razor_set_diff(set, next, update_package, NULL);
13.129
13.130 razor_transaction_destroy(trans);
13.131 - razor_set_destroy(set);
13.132 - razor_set_destroy(upstream);
13.133 + razor_set_unref(set);
13.134 + razor_set_unref(upstream);
13.135
13.136 - razor_set_destroy(next);
13.137 + razor_set_unref(next);
13.138 }
13.139
13.140 static void
13.141 command_install(int argc, const char *argv[])
13.142 {
13.143 + struct razor_atomic *atomic;
13.144 struct razor_set *set, *upstream, *next;
13.145 struct razor_transaction *trans;
13.146 struct razor_package_iterator *pi;
13.147 @@ -621,7 +650,14 @@
13.148 exit(1);
13.149 }
13.150
13.151 - set = razor_set_open(repo_filename);
13.152 + atomic = razor_atomic_open("Install packages");
13.153 +
13.154 + set = razor_set_open(repo_filename, atomic);
13.155 + if (!set || razor_atomic_commit(atomic)) {
13.156 + fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
13.157 + razor_atomic_destroy(atomic);
13.158 + }
13.159 + razor_atomic_destroy(atomic);
13.160 upstream = create_set_from_command_line(argc, argv);
13.161
13.162 trans = razor_transaction_create(set, upstream);
13.163 @@ -648,15 +684,16 @@
13.164 razor_set_diff(set, next, update_package, NULL);
13.165
13.166 razor_transaction_destroy(trans);
13.167 - razor_set_destroy(set);
13.168 - razor_set_destroy(upstream);
13.169 + razor_set_unref(set);
13.170 + razor_set_unref(upstream);
13.171
13.172 - razor_set_destroy(next);
13.173 + razor_set_unref(next);
13.174 }
13.175
13.176 static void
13.177 command_update(int argc, const char *argv[])
13.178 {
13.179 + struct razor_atomic *atomic;
13.180 struct razor_set *set, *upstream, *next;
13.181 struct razor_transaction *trans;
13.182 struct razor_package_iterator *pi;
13.183 @@ -667,7 +704,14 @@
13.184 exit(1);
13.185 }
13.186
13.187 - set = razor_set_open(repo_filename);
13.188 + atomic = razor_atomic_open("Update packages");
13.189 +
13.190 + set = razor_set_open(repo_filename, atomic);
13.191 + if (!set || razor_atomic_commit(atomic)) {
13.192 + fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
13.193 + razor_atomic_destroy(atomic);
13.194 + }
13.195 + razor_atomic_destroy(atomic);
13.196 upstream = create_set_from_command_line(argc, argv);
13.197
13.198 trans = razor_transaction_create(set, upstream);
13.199 @@ -694,10 +738,10 @@
13.200 razor_set_diff(set, next, update_package, NULL);
13.201
13.202 razor_transaction_destroy(trans);
13.203 - razor_set_destroy(set);
13.204 - razor_set_destroy(upstream);
13.205 + razor_set_unref(set);
13.206 + razor_set_unref(upstream);
13.207
13.208 - razor_set_destroy(next);
13.209 + razor_set_unref(next);
13.210 }
13.211
13.212 static int