if (errno != EEXIST || chmod(action->args.path, mode) < 0) {
if (!atomic->error)
- atomic->error = razor_error_new_str(action->args.path,
- strerror(errno));
+ atomic->error = razor_error_new_posix(action->args.path);
atomic_action_free(action);
return NULL;
}
if (rmdir(action->args.path) < 0) {
if (!atomic->error)
- atomic->error = razor_error_new_str(action->args.path,
- strerror(errno));
+ atomic->error = razor_error_new_posix(action->args.path);
atomic_action_free(action);
return NULL;
} else
r = symlink(action->args.u.create_symlink.target, action->args.path);
if (r < 0) {
if (!atomic->error)
- atomic->error = razor_error_new_str(action->args.path,
- strerror(errno));
+ atomic->error = razor_error_new_posix(action->args.path);
atomic_action_free(action);
return NULL;
}
if (unlink(action->args.path) < 0) {
if (!atomic->error)
- atomic->error = razor_error_new_str(action->args.path,
- strerror(errno));
+ atomic->error = razor_error_new_posix(action->args.path);
atomic_action_free(action);
return NULL;
}
#else
if (rename(path, dest)) {
if (!atomic->error)
- atomic->error = razor_error_new_str(dest,
- strerror(errno));
+ atomic->error = razor_error_new_posix(dest);
return -1;
}
#endif
abspath = absolute_path(path);
if (!abspath) {
- atomic->error = razor_error_new_str(path,
- strerror(errno));
+ atomic->error = razor_error_new_posix(path);
return -1;
}
if (stat(abspath, &buf) < 0) {
- atomic->error = razor_error_new_str(abspath,
- strerror(errno));
+ atomic->error = razor_error_new_posix(abspath);
free(abspath);
return -1;
}
}
if (stat(abspath, &buf) < 0) {
- atomic->error =
- razor_error_new_str(abspath, strerror(errno));
+ atomic->error = razor_error_new_posix(abspath);
free(abspath);
return -1;
}
#ifndef MSWIN_API
if (stat(".", &buf) < 0) {
- atomic->error =
- razor_error_new_str(".", strerror(errno));
+ atomic->error = razor_error_new_posix(".");
free(s);
free(atomic->toplevel);
atomic->toplevel = NULL;
}
#endif
- atomic->error = razor_error_new_str(atomic->toplevel,
+ atomic->error = razor_error_new_str(RAZOR_POSIX_ERROR, err,
+ atomic->toplevel,
strerror(err));
free(atomic->toplevel);
return 0;
#else
- atomic->error = razor_error_new_str(NULL,
+ atomic->error = razor_error_new_str(RAZOR_POSIX_ERROR, ENOSYS, NULL,
"Symbolic links not supported "
"on this platform");
mode & (S_IRWXU | S_IRWXG | S_IRWXO));
if (fd == -1)
- atomic->error = razor_error_new_str(filename, strerror(errno));
+ atomic->error = razor_error_new_posix(filename);
else {
a = atomic_action_new(ACTION_MOVE);
a->args.path = tmpnam;
}
} else if (!(fa.dwFileAttributes&
FILE_ATTRIBUTE_DIRECTORY)) {
- razor_set_error2(&atomic->error, buffer->str,
+ razor_set_error2(&atomic->error,
+ RAZOR_MSWIN_ERROR,
+ ERROR_DIRECTORY, buffer->str,
"Not a directory");
razor_wstr_destroy(buffer);
return -1;
* and we don't always know that at the time when the
* link is created, so it's a convienent lie for now.
*/
- razor_set_error(&atomic->error, NULL,
- "Symbolic links not supported on this platform");
+ razor_set_error(&atomic->error, RAZOR_MSWIN_ERROR, ERROR_NOT_SUPPORTED,
+ NULL, "Symbolic links not supported on this platform");
return -1;
}
files = realloc(atomic->files,
(atomic->n_files+1) * sizeof(struct razor_atomic_file));
if (!files) {
- razor_set_error(&atomic->error, NULL, "Not enough memory");
+ razor_set_error(&atomic->error, RAZOR_POSIX_ERROR, ENOMEM, NULL,
+ "Not enough memory");
return -1;
}
atomic->n_files++;
}
RAZOR_EXPORT void
-razor_atomic_abort(struct razor_atomic *atomic, const char *error_msg)
+razor_atomic_abort(struct razor_atomic *atomic, int domain, int code,
+ const char *error_msg)
{
if (!atomic->error)
- atomic->error = razor_error_new_str(NULL, error_msg);
+ atomic->error = razor_error_new_str(domain, code, NULL,
+ error_msg);
+}
+
+RAZOR_EXPORT void
+razor_atomic_propagate_error(struct razor_atomic *atomic,
+ struct razor_error *error, const char *summary)
+{
+ if (!atomic->error)
+ atomic->error = razor_error_dup(error, summary);
}
RAZOR_EXPORT int
while(size) {
written = write(fd, data, size);
if (written < 0) {
- atomic->error = razor_error_new_str(NULL,
- strerror(errno));
+ atomic->error = razor_error_new_posix(NULL);
(void)close(fd);
return -1;
if (fsync(handle) < 0) {
- atomic->error = razor_error_new_str(NULL, strerror(errno));
+ atomic->error = razor_error_new_posix(NULL);
return -1;
}
return -1;
if (close(fd) < 0) {
- atomic->error = razor_error_new_str(NULL, strerror(errno));
+ atomic->error = razor_error_new_posix(NULL);
return -1;
}
/*
- * Copyright (C) 2011-2012 J. Ali Harlow <ali@juiblex.co.uk>
+ * Copyright (C) 2011-2012, 2014 J. Ali Harlow <ali@juiblex.co.uk>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#include "razor.h"
#include "razor-internal.h"
-static const char *razor_error_get_path_str(struct razor_error *error)
+RAZOR_EXPORT int
+razor_error_get_domain(struct razor_error *error)
{
- if (error->path_str)
- return error->path_str;
+ return error->domain;
+}
+
+RAZOR_EXPORT int
+razor_error_get_code(struct razor_error *error)
+{
+ return error->code;
+}
+
+RAZOR_EXPORT const char *
+razor_error_get_object(struct razor_error *error)
+{
+ return error->object;
+}
+
+static const char *razor_error_get_obj_str(struct razor_error *error)
+{
+ if (error->obj_str)
+ return error->obj_str;
- if (error->path) {
- error->path_str = razor_concat(error->path, ": ",
- error->str, NULL);
- return error->path_str;
+ if (error->object) {
+ error->obj_str = razor_concat(error->object, ": ",
+ error->str, NULL);
+ return error->obj_str;
}
return error->str;
*
* Retrieves the basic information about an error. If a summary has been set
* then this will be returned. Otherwise the error string possibly prefixed
- * by the path will be returned instead.
+ * by the object will be returned instead.
*
* Returns: Primary text of error.
**/
if (error->summary)
return error->summary;
- return razor_error_get_path_str(error);
+ return razor_error_get_obj_str(error);
}
/**
* razor_error_get_secondary_text:
*
* Retrieves more detailed information about an error, if any. If a summary
- * has been set the error string possibly prefixed by the path will be
+ * has been set the error string possibly prefixed by the object will be
* returned. Otherwise NULL will be returned.
*
* Returns: Secondary text of error or NULL.
if (!error->summary)
return NULL;
- return razor_error_get_path_str(error);
+ return razor_error_get_obj_str(error);
}
RAZOR_EXPORT const char *
#ifdef MSWIN_API
struct razor_error *
-razor_error_new_mswin(const wchar_t *path, DWORD err)
+razor_error_new_mswin(const wchar_t *object, DWORD err)
{
struct razor_error *error;
wchar_t *buf;
error = zalloc(sizeof *error);
- if (path)
- error->path = razor_utf16_to_utf8(path, -1);
+ error->domain = RAZOR_MSWIN_ERROR;
+ error->code = err;
+
+ if (object)
+ error->object = razor_utf16_to_utf8(object, -1);
FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER|
FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
}
struct razor_error *
-razor_error_new_str2(const wchar_t *path, const char *str)
+razor_error_new_str2(int domain, int code, const wchar_t *object,
+ const char *str)
{
struct razor_error *error;
error = zalloc(sizeof *error);
- if (path)
- error->path = razor_utf16_to_utf8(path, -1);
+ error->domain = domain;
+ error->code = code;
+
+ if (object)
+ error->object = razor_utf16_to_utf8(object, -1);
error->str = strdup(str);
#endif /* MSWIN_API */
RAZOR_EXPORT struct razor_error *
-razor_error_new_str(const char *path, const char *str)
+razor_error_new_str(int domain, int code, const char *object, const char *str)
{
struct razor_error *error;
error = zalloc(sizeof *error);
- if (path)
- error->path = strdup(path);
+ error->domain = domain;
+ error->code = code;
+
+ if (object)
+ error->object = strdup(object);
error->str = strdup(str);
error = zalloc(sizeof *error);
+ error->domain = src->domain;
+ error->code = src->code;
+
if (summary)
error->summary = strdup(summary);
else if (src->summary)
error->summary = strdup(src->summary);
- if (src->path)
- error->path = strdup(src->path);
+ if (src->object)
+ error->object = strdup(src->object);
if (src->str)
error->str = strdup(src->str);
RAZOR_EXPORT void
razor_error_free(struct razor_error *error)
{
- free(error->path);
+ free(error->object);
free(error->str);
- free(error->path_str);
+ free(error->obj_str);
free(error->summary);
free(error->msg);
free(error);
/*
* Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
* Copyright (C) 2008 Red Hat, Inc
- * Copyright (C) 2009, 2011-2012 J. Ali Harlow <ali@juiblex.co.uk>
+ * Copyright (C) 2009, 2011-2012, 2014 J. Ali Harlow <ali@juiblex.co.uk>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
/* Error functions */
struct razor_error {
- char *path;
+ int domain;
+ int code;
+ char *object;
char *str;
- char *path_str;
+ char *obj_str;
char *summary;
char *msg;
};
+#define razor_error_new_posix(object) \
+ razor_error_new_str(RAZOR_POSIX_ERROR, errno, object, strerror(errno))
+#define razor_set_error_posix(error, object) \
+ if (error) \
+ *(error) = razor_error_new_posix(object); \
+ else
+
#ifdef MSWIN_API
-struct razor_error *razor_error_new_mswin(const wchar_t *path, DWORD error);
-struct razor_error *razor_error_new_str2(const wchar_t *path, const char *str);
+struct razor_error *razor_error_new_mswin(const wchar_t *object, DWORD error);
+struct razor_error *razor_error_new_str2(int domain, int code,
+ const wchar_t *object,
+ const char *str);
-#define razor_set_error_mswin(error, path, err) \
+#define razor_set_error_mswin(error, object, err) \
if (error) \
- *(error) = razor_error_new_mswin(path, err); \
+ *(error) = razor_error_new_mswin(object, err); \
else
-#define razor_set_error2(error, path, str) \
+#define razor_set_error2(error, domain, code, object, str) \
if (error) \
- *(error) = razor_error_new_str2(path, str); \
+ *(error) = razor_error_new_str2(domain, code, object, str); \
else
#endif /* MSWIN_API */
struct razor_mapped_file *file;
const char *pool, *reason;
struct array *array;
- int i, j;
+ int i, j, code;
file = zalloc(sizeof *file);
if (file == NULL) {
- razor_set_error(error, NULL, "Not enough memory");
+ razor_set_error(error, RAZOR_POSIX_ERROR, ENOMEM, NULL,
+ "Not enough memory");
return -1;
}
return -1;
}
- if (file->size < sizeof *file->header)
+ if (file->size < sizeof *file->header) {
+ code = RAZOR_GENERAL_ERROR_DATABASE_CORRUPTED;
reason = "Premature EOF";
- else if (file->header->magic != RAZOR_MAGIC)
+ } else if (file->header->magic != RAZOR_MAGIC) {
+ code = RAZOR_GENERAL_ERROR_DATABASE_CORRUPTED;
reason = "Bad magic number";
- else if (file->header->version < RAZOR_HEADER_VERSION_MIN ||
- file->header->version > RAZOR_HEADER_VERSION)
+ } else if (file->header->version < RAZOR_HEADER_VERSION_MIN ||
+ file->header->version > RAZOR_HEADER_VERSION) {
+ code = RAZOR_GENERAL_ERROR_DATABASE_INCOMPATIBLE;
reason = "Incompatible file version";
- else
+ } else
reason = NULL;
if (reason) {
- razor_set_error(error, filename, reason);
+ razor_set_error(error, RAZOR_GENERAL_ERROR, code, filename,
+ reason);
razor_file_free_contents(file->header, file->size);
free(file);
return -1;
set = zalloc(sizeof *set);
if (!set) {
- razor_set_error(error, NULL, "Not enough memory");
+ razor_set_error(error, RAZOR_POSIX_ERROR, ENOMEM, NULL,
+ "Not enough memory");
return NULL;
}
*/
struct razor_error;
-struct razor_error *razor_error_new_str(const char *path, const char *str);
+struct razor_error *razor_error_new_str(int domain, int code,
+ const char *object, const char *str);
struct razor_error *razor_error_dup(struct razor_error *src,
const char *summary);
-#define razor_set_error(error, path, str) \
+#define razor_set_error(error, domain, code, object, str) \
if (error) \
- *(error) = razor_error_new_str(path, str); \
+ *(error) = razor_error_new_str(domain, code, object, str); \
else
#define razor_propagate_error(dest, src, summary) \
*(dest) = razor_error_dup(src, summary); \
else
+#define RAZOR_ERROR_DOMAIN(i1,i2,i3,c) \
+ (((i1)&0xff)<<24|((i2)&0xff)<<16|((i3)&0xff)<<8|(c)&0xff)
+
+#define RAZOR_GENERAL_ERROR RAZOR_ERROR_DOMAIN('R','z','r',0)
+#define RAZOR_POSIX_ERROR RAZOR_ERROR_DOMAIN('R','z','r',1)
+#define RAZOR_MSWIN_ERROR RAZOR_ERROR_DOMAIN('R','z','r',2)
+#define RAZOR_ZLIB_ERROR RAZOR_ERROR_DOMAIN('R','z','r',3)
+
+enum razor_general_error {
+ RAZOR_GENERAL_ERROR_FAILED,
+ RAZOR_GENERAL_ERROR_DATABASE_CORRUPTED,
+ RAZOR_GENERAL_ERROR_DATABASE_INCOMPATIBLE,
+ RAZOR_GENERAL_ERROR_DATABASE_EXISTS,
+ RAZOR_GENERAL_ERROR_DATABASE_LOCKED,
+ RAZOR_GENERAL_ERROR_RPM_UNSUPPORTED,
+};
+
+int razor_error_get_domain(struct razor_error *error);
+int razor_error_get_code(struct razor_error *error);
+const char *razor_error_get_object(struct razor_error *error);
const char *razor_error_get_primary_text(struct razor_error *error);
const char *razor_error_get_secondary_text(struct razor_error *error);
const char *razor_error_get_msg(struct razor_error *error);
const void *data, size_t size);
int razor_atomic_close(struct razor_atomic *atomic, int handle);
int razor_atomic_sync(struct razor_atomic *atomic, int handle);
-void razor_atomic_abort(struct razor_atomic *atomic, const char *error_msg);
+void razor_atomic_abort(struct razor_atomic *atomic, int domain, int code,
+ const char *error_msg);
+void razor_atomic_propagate_error(struct razor_atomic *atomic,
+ struct razor_error *error, const char *summary);
int razor_atomic_in_error_state(struct razor_atomic *atomic);
/**
#include <stdint.h>
#include <stdio.h>
#include <string.h>
+#include <errno.h>
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>
/* root is file system root */
} else if (stat(root, &buf) < 0) {
if (mkdir(root, 0777) < 0) {
- razor_set_error(error, root,
+ razor_set_error(error, RAZOR_POSIX_ERROR, errno, root,
"Could not create install root");
return -1;
}
} else if (!S_ISDIR(buf.st_mode)) {
- razor_set_error(error, root, "Not a directory");
+ razor_set_error(error, RAZOR_POSIX_ERROR, ENOTDIR, root,
+ "Not a directory");
return -1;
}
path = razor_path_add_root(file, root);
retval = !stat(path, &buf);
if (retval) {
- razor_set_error(error, NULL,
+ razor_set_error(error, RAZOR_GENERAL_ERROR,
+ RAZOR_GENERAL_ERROR_DATABASE_EXISTS, NULL,
"A razor install root is already initialized");
free(path);
free(file);
razor_root_init();
image = malloc(sizeof *image);
if (image == NULL) {
- razor_set_error(error, NULL, "Not enough memory");
+ razor_set_error(error, RAZOR_POSIX_ERROR, ENOMEM, NULL,
+ "Not enough memory");
return NULL;
}
image->system = razor_set_create_without_root();
if (image->system == NULL) {
free(image);
- razor_set_error(error, NULL, "Not enough memory");
+ razor_set_error(error, RAZOR_POSIX_ERROR, ENOMEM, NULL,
+ "Not enough memory");
return NULL;
}
free(lock_path);
if (r < 0) {
- razor_set_error(error, NULL,
+ razor_set_error(error, RAZOR_GENERAL_ERROR,
+ RAZOR_GENERAL_ERROR_DATABASE_LOCKED, NULL,
"Failed to aquire exclusive system lock");
razor_set_unref(image->system);
free(image);
razor_root_init();
set = razor_set_create_without_root();
if (set == NULL) {
- razor_set_error(error, NULL, "Not enough memory");
+ razor_set_error(error, RAZOR_POSIX_ERROR, ENOMEM, NULL,
+ "Not enough memory");
return NULL;
}
free(s);
if (razor_set_aquire_lock(set, path, 0) < 0) {
- razor_set_error(error, NULL,
+ razor_set_error(error, RAZOR_GENERAL_ERROR,
+ RAZOR_GENERAL_ERROR_DATABASE_LOCKED, NULL,
"Failed to aquire non-exclusive system lock");
free(path);
razor_set_unref(set);
rpm = zalloc(sizeof *rpm);
if (rpm == NULL) {
- razor_set_error(error, NULL, "Not enough memory");
+ razor_set_error(error, RAZOR_POSIX_ERROR, ENOMEM, NULL,
+ "Not enough memory");
return NULL;
}
memset(rpm, 0, sizeof *rpm);
&count);
if (name) {
razor_rpm_close(rpm);
- razor_set_error(error, filename,
+ razor_set_error(error, RAZOR_GENERAL_ERROR,
+ RAZOR_GENERAL_ERROR_RPM_UNSUPPORTED,
+ filename,
"Old filenames not supported");
return NULL;
}
&count);
if (prefix) {
razor_rpm_close(rpm);
- razor_set_error(error, filename,
+ razor_set_error(error, RAZOR_GENERAL_ERROR,
+ RAZOR_GENERAL_ERROR_RPM_UNSUPPORTED,
+ filename,
"Default prefix not supported");
return NULL;
}
installer->stream.avail_out = length;
err = inflate(&installer->stream, Z_SYNC_FLUSH);
if (err != Z_OK && err != Z_STREAM_END) {
- razor_atomic_abort(installer->atomic, "Failed to inflate");
+ razor_atomic_abort(installer->atomic, RAZOR_ZLIB_ERROR, err,
+ "Failed to inflate");
return -1;
}
err = inflate(&installer->stream, Z_SYNC_FLUSH);
if (err != Z_OK && err != Z_STREAM_END) {
- razor_atomic_abort(installer->atomic, "Failed to inflate");
+ razor_atomic_abort(installer->atomic, RAZOR_ZLIB_ERROR, err,
+ "Failed to inflate");
return -1;
}
return -1;
if (installer->length >= sizeof installer->buffer) {
razor_atomic_abort(installer->atomic,
+ RAZOR_GENERAL_ERROR,
+ RAZOR_GENERAL_ERROR_RPM_UNSUPPORTED,
"Link target too long");
return -1;
}
free(buffer);
buffer = razor_concat(s, " are not supported on this platform",
NULL);
- razor_atomic_abort(installer->atomic, buffer);
+ razor_atomic_abort(installer->atomic, RAZOR_GENERAL_ERROR,
+ RAZOR_GENERAL_ERROR_RPM_UNSUPPORTED, buffer);
free(buffer);
return -1;
case CDEV:
goto unsupported;
default:
free(buffer);
- razor_atomic_abort(installer->atomic, "Unknown file type");
+ razor_atomic_abort(installer->atomic, RAZOR_GENERAL_ERROR,
+ RAZOR_GENERAL_ERROR_RPM_UNSUPPORTED, "Unknown file type");
return -1;
}
}
gz_header = installer->rpm->payload;
if (gz_header[0] != 0x1f || gz_header[1] != 0x8b) {
- razor_atomic_abort(installer->atomic,
+ razor_atomic_abort(installer->atomic, RAZOR_GENERAL_ERROR,
+ RAZOR_GENERAL_ERROR_RPM_UNSUPPORTED,
"Payload section doesn't have gz header");
return -1;
}
flags = gz_header[3];
if (method != Z_DEFLATED || flags != 0) {
- razor_atomic_abort(installer->atomic,
+ razor_atomic_abort(installer->atomic, RAZOR_GENERAL_ERROR,
+ RAZOR_GENERAL_ERROR_RPM_UNSUPPORTED,
"Unknown payload compression method or "
"flags set");
return -1;
if (err != Z_OK) {
sprintf(buffer, "%d", err);
s = razor_concat("inflateEnd error: ", buffer, NULL);
- razor_atomic_abort(installer->atomic, s);
+ razor_atomic_abort(installer->atomic, RAZOR_ZLIB_ERROR, err, s);
free(s);
return -1;
}
if (err != Z_OK) {
sprintf(buffer, "%d", err);
s = razor_concat("inflateEnd error: ", buffer, NULL);
- razor_atomic_abort(installer->atomic, s);
+ razor_atomic_abort(installer->atomic, RAZOR_ZLIB_ERROR, err, s);
free(s);
}
const char *path;
size_t filesize;
char *s;
- int retval = 0;
+ int retval = 0, code;
assert (rpm != NULL);
assert (root != NULL);
installer.atomic = atomic;
/* FIXME: Only do this before a transaction, not per rpm. */
- if (*root && (stat(root, &buf) < 0 || !S_ISDIR(buf.st_mode))) {
+ if (*root && ((retval = stat(root, &buf)) || !S_ISDIR(buf.st_mode))) {
+ code = retval ? errno : ENOTDIR;
s = razor_concat(root, ": Directory does not exist", NULL);
- razor_atomic_abort(atomic, s);
+ razor_atomic_abort(atomic, RAZOR_POSIX_ERROR, code, s);
free(s);
return -1;
}
fd = open(filename, O_RDONLY | O_BINARY);
if (fd < 0) {
- razor_set_error(error, filename, strerror(errno));
+ razor_set_error_posix(error, filename);
return NULL;
}
if (fstat(fd, &st) < 0) {
- razor_set_error(error, filename, strerror(errno));
+ razor_set_error_posix(error, filename);
close(fd);
return NULL;
}
while(nb < st.st_size) {
res = read(fd, addr + nb, st.st_size - nb);
if (res <= 0) {
- razor_set_error(error, filename,
- strerror(errno));
+ razor_set_error_posix(error, filename);
free(addr);
addr = NULL;
break;
nb += res;
}
} else
- razor_set_error(error, NULL, "Not enough memory");
+ razor_set_error(error, RAZOR_POSIX_ERROR, ENOMEM, NULL,
+ "Not enough memory");
}
close(fd);
rpm = razor_rpm_open(file, &error);
free(file);
if (rpm == NULL) {
- razor_atomic_abort(atomic, razor_error_get_msg(error));
+ razor_atomic_propagate_error(atomic, error, NULL);
razor_error_free(error);
razor_package_iterator_destroy(pkg_iter);
razor_importer_destroy(importer);
rpm = razor_rpm_open(file, &error);
free(file);
if (rpm == NULL) {
- razor_atomic_abort(atomic, razor_error_get_msg(error));
+ razor_atomic_propagate_error(atomic, error, NULL);
fprintf(stderr, "%s\n", razor_error_get_msg(error));
razor_error_free(error);
return -1;