Add an error object.
authorJ. Ali Harlow <ali@juiblex.co.uk>
Sat, 11 Feb 2012 23:50:26 +0000 (23:50 +0000)
committerJ. Ali Harlow <ali@juiblex.co.uk>
Sat, 11 Feb 2012 23:50:26 +0000 (23:50 +0000)
This is intended to dis-entangle the two roles that the atomic
object has evolved into so that atomic need only be used where
atomic actions are actually being undertaken.

configure.ac
librazor/Makefile.am
librazor/atomic-actions.c
librazor/atomic-emulate.c
librazor/atomic-ktm.c
librazor/atomic-none.c
librazor/atomic.c
librazor/error.c [new file with mode: 0644]
librazor/razor-internal.h
librazor/razor.h

index 511e572..892f35f 100644 (file)
@@ -10,9 +10,9 @@ AM_MAINTAINER_MODE
 #
 # See http://sources.redhat.com/autobook/autobook/autobook_91.html#SEC91 for details
 #
-LT_CURRENT=3
+LT_CURRENT=4
 LT_REVISION=0
-LT_AGE=1
+LT_AGE=2
 AC_SUBST(LT_CURRENT)
 AC_SUBST(LT_REVISION)
 AC_SUBST(LT_AGE)
index 7196484..a63336d 100644 (file)
@@ -33,6 +33,7 @@ librazor_la_SOURCES =                                 \
        iterator.c                                      \
        importer.c                                      \
        merger.c                                        \
+       error.c                                         \
        atomic.c                                        \
        atomic-ktm.c                                    \
        atomic-none.c                                   \
index 0b4662b..f545856 100644 (file)
@@ -259,9 +259,9 @@ atomic_action_create_dir(struct razor_atomic *atomic,
                return 0;
 
        if (errno != EEXIST || chmod(action->args.path, mode) < 0) {
-               if (!atomic->error_str)
-                       razor_atomic_set_error_str(atomic, action->args.path,
-                                                  strerror(errno));
+               if (!atomic->error)
+                       atomic->error = razor_error_new_str(action->args.path,
+                                                           strerror(errno));
                atomic_action_free(action);
                return NULL;
        }
@@ -278,9 +278,9 @@ static struct atomic_action *atomic_action_rmdir(struct razor_atomic *atomic,
        }
 
        if (rmdir(action->args.path) < 0) {
-               if (!atomic->error_str)
-                       razor_atomic_set_error_str(atomic, action->args.path,
-                                                  strerror(errno));
+               if (!atomic->error)
+                       atomic->error = razor_error_new_str(action->args.path,
+                                                           strerror(errno));
                atomic_action_free(action);
                return NULL;
        } else
@@ -301,9 +301,9 @@ atomic_action_create_symlink(struct razor_atomic *atomic,
 
        r = symlink(action->args.u.create_symlink.target, action->args.path);
        if (r < 0) {
-               if (!atomic->error_str)
-                       razor_atomic_set_error_str(atomic, NULL,
-                                                  strerror(errno));
+               if (!atomic->error)
+                       atomic->error = razor_error_new_str(action->args.path,
+                                                           strerror(errno));
                atomic_action_free(action);
                return NULL;
        }
@@ -321,9 +321,9 @@ atomic_action_remove_symlink(struct razor_atomic *atomic,
        }
 
        if (unlink(action->args.path) < 0) {
-               if (!atomic->error_str)
-                       razor_atomic_set_error_str(atomic, NULL,
-                                                  strerror(errno));
+               if (!atomic->error)
+                       atomic->error = razor_error_new_str(action->args.path,
+                                                           strerror(errno));
                atomic_action_free(action);
                return NULL;
        }
@@ -351,9 +351,9 @@ move_file(struct razor_atomic *atomic, const char *path, const char *dest)
        (void)RemoveDirectoryW(newbuf);
 
        if (!MoveFileExW(oldbuf, newbuf, flags)) {
-               if (!atomic->error_str)
-                       razor_atomic_set_error_mswin(atomic, newbuf,
-                                                    GetLastError());
+               if (!atomic->error)
+                       atomic->error = razor_error_new_mswin(newbuf,
+                                                             GetLastError());
                return -1;
        }
 
@@ -361,9 +361,9 @@ move_file(struct razor_atomic *atomic, const char *path, const char *dest)
        free(oldbuf);
 #else
        if (rename(path, dest)) {
-               if (!atomic->error_str)
-                       razor_atomic_set_error_str(atomic, dest,
-                                                  strerror(errno));
+               if (!atomic->error)
+                       atomic->error = razor_error_new_str(dest,
+                                                           strerror(errno));
                return -1;
        }
 #endif
index c8f88e0..a467626 100644 (file)
@@ -21,6 +21,7 @@
 #if ENABLE_ATOMIC && !HAVE_WINDOWS_KTM
 
 #include <stdlib.h>
+#include <stdio.h>
 #include <string.h>
 #include <unistd.h>
 #include <sys/types.h>
@@ -108,7 +109,7 @@ RAZOR_EXPORT int razor_atomic_commit(struct razor_atomic *atomic)
                atomic->toplevel = NULL;
        }
 
-       return !!atomic->error_str;
+       return razor_atomic_in_error_state(atomic);
 }
 
 RAZOR_EXPORT void razor_atomic_destroy(struct razor_atomic *atomic)
@@ -119,9 +120,9 @@ RAZOR_EXPORT void razor_atomic_destroy(struct razor_atomic *atomic)
                atomic->toplevel = NULL;
        }
 
-       free(atomic->error_path);
-       free(atomic->error_str);
-       free(atomic->error_msg);
+       if (atomic->error)
+               razor_error_free(atomic->error);
+
        free(atomic);
 }
 
@@ -210,8 +211,9 @@ razor_atomic_create_symlink(struct razor_atomic *atomic, const char *target,
 
        return 0;
 #else
-       razor_atomic_set_error_str(atomic, NULL, "Symbolic links not supported "
-                                                "on this platform");
+       atomic->error = razor_error_new_str(NULL,
+                                           "Symbolic links not supported "
+                                           "on this platform");
 
        return -1;
 #endif
@@ -228,13 +230,12 @@ razor_atomic_create_file(struct razor_atomic *atomic, const char *filename,
        if (razor_atomic_in_error_state(atomic))
                return -1;
 
-       atomic->error_path = strdup(filename);
        tmpnam = atomic_action_attic_tmpnam(atomic);
        fd = open(tmpnam, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
                  mode & (S_IRWXU | S_IRWXG | S_IRWXO));
 
        if (fd == -1)
-               razor_atomic_set_error_str(atomic, NULL, strerror(errno));
+               atomic->error = razor_error_new_str(filename, strerror(errno));
        else {
                a = atomic_action_new(ACTION_MOVE);
                a->args.path = tmpnam;
index 5b4b751..37b506e 100644 (file)
@@ -131,45 +131,6 @@ razor_atomic_open(const char *description)
        return atomic;
 }
 
-void
-razor_atomic_set_error_str(struct razor_atomic *atomic, const wchar_t *path,
-                          const char *str)
-{
-       assert(!atomic->error_str);
-
-       free(atomic->error_path);
-
-       if (path)
-               atomic->error_path = razor_utf16_to_utf8(path, -1);
-       else
-               atomic->error_path = NULL;
-
-       atomic->error_str = strdup(str);
-}
-
-static void
-razor_atomic_set_error(struct razor_atomic *atomic, const wchar_t *path,
-                      DWORD error)
-{
-       wchar_t *buf;
-
-       assert(!atomic->error_str);
-
-       free(atomic->error_path);
-
-       if (path)
-               atomic->error_path = razor_utf16_to_utf8(path, -1);
-       else
-               atomic->error_path = NULL;
-
-       FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER|
-                      FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
-                      NULL, error, MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
-                      (LPWSTR)&buf, 0, NULL);
-       atomic->error_str = razor_utf16_to_utf8(buf, -1);
-       LocalFree(buf);
-}
-
 RAZOR_EXPORT int
 razor_atomic_commit(struct razor_atomic *atomic)
 {
@@ -181,7 +142,7 @@ razor_atomic_commit(struct razor_atomic *atomic)
        retval = !CommitTransaction(atomic->transaction);
 
        if (retval) {
-               razor_atomic_set_error(atomic, NULL, GetLastError());
+               atomic->error = razor_error_new_mswin(NULL, GetLastError());
                RollbackTransaction(atomic->transaction);
        }
 
@@ -207,9 +168,8 @@ razor_atomic_destroy(struct razor_atomic *atomic)
                RollbackTransaction(atomic->transaction);
                CloseHandle(atomic->transaction);
        }
-       free(atomic->error_path);
-       free(atomic->error_str);
-       free(atomic->error_msg);
+       if (atomic->error)
+               razor_error_free(atomic->error);
        free(atomic);
 }
 
@@ -250,16 +210,15 @@ razor_atomic_make_dirs(struct razor_atomic *atomic, const char *root,
                                if (err == ERROR_FILE_NOT_FOUND) {
                                        creating = 1;
                                } else {
-                                       razor_atomic_set_error(atomic,
-                                                              buffer->str,
-                                                              err);
+                                       atomic->error = razor_error_new_mswin(buffer->str,
+                                                                             err);
                                        razor_wstr_destroy(buffer);
                                        return -1;
                                }
                        } else if (!(fa.dwFileAttributes&
                                     FILE_ATTRIBUTE_DIRECTORY)) {
-                               razor_atomic_set_error_str(atomic, buffer->str,
-                                                          "Not a directory");
+                               atomic->error = razor_error_new_str(buffer->str,
+                                                                   "Not a directory");
                                razor_wstr_destroy(buffer);
                                return -1;
                        }
@@ -267,8 +226,8 @@ razor_atomic_make_dirs(struct razor_atomic *atomic, const char *root,
                if (creating) {
                        if (!CreateDirectoryTransactedW(NULL, buffer->str, NULL,
                                                        atomic->transaction)) {
-                               razor_atomic_set_error(atomic, buffer->str,
-                                                      GetLastError());
+                               atomic->error = razor_error_new_mswin(buffer->str,
+                                                                     GetLastError());
                                razor_wstr_destroy(buffer);
                                return -1;
                        }
@@ -328,7 +287,7 @@ razor_atomic_remove(struct razor_atomic *atomic, const char *path)
         * same path, this is likely to cause more problems than it solves.
         */
 
-       razor_atomic_set_error(atomic, buf, err);
+       atomic->error = razor_error_new_mswin(buf, err);
        free(buf);
        return -1;
 }
@@ -356,12 +315,12 @@ razor_atomic_rename_file(struct razor_atomic *atomic, const char *oldpath,
 
        if (!MoveFileTransactedW(oldbuf, newbuf, NULL, NULL, flags,
                                 atomic->transaction))
-               razor_atomic_set_error(atomic, newbuf, GetLastError());
+               atomic->error = razor_error_new_mswin(newbuf, GetLastError());
 
        free(newbuf);
        free(oldbuf);
 
-       return !!atomic->error_str;
+       return razor_atomic_in_error_state(atomic);
 }
 
 RAZOR_EXPORT int
@@ -381,7 +340,7 @@ razor_atomic_create_dir(struct razor_atomic *atomic, const char *dirname,
                err = GetLastError();
                if (err != ERROR_FILE_EXISTS && err != ERROR_ALREADY_EXISTS) {
 abort:
-                       razor_atomic_set_error(atomic, buf, err);
+                       atomic->error = razor_error_new_mswin(buf, err);
                        free(buf);
                        return -1;
                }
@@ -421,8 +380,9 @@ razor_atomic_create_symlink(struct razor_atomic *atomic, const char *target,
         * and we don't always know that at the time when the
         * link is created, so it's a convienent lie for now.
         */
-       razor_atomic_set_error_str(atomic, NULL, "Symbolic links not supported "
-                                                "on this platform");
+       atomic->error = razor_error_new_str(NULL,
+                                           "Symbolic links not supported "
+                                           "on this platform");
 
        return -1;
 }
@@ -441,7 +401,7 @@ razor_atomic_create_file(struct razor_atomic *atomic, const char *filename,
        files = realloc(atomic->files,
                        (atomic->n_files+1) * sizeof(struct razor_atomic_file));
        if (!files) {
-               razor_atomic_set_error_str(atomic, NULL, "Not enough memory");
+               atomic->error = razor_error_new_str(NULL, "Not enough memory");
                return -1;
        }
        atomic->n_files++;
@@ -468,7 +428,8 @@ razor_atomic_create_file(struct razor_atomic *atomic, const char *filename,
                                           NULL);
 
        if (files[i].h == INVALID_HANDLE_VALUE) {
-               razor_atomic_set_error(atomic, files[i].path, GetLastError());
+               atomic->error = razor_error_new_mswin(files[i].path,
+                                                     GetLastError());
                free(files[i].path);
                atomic->n_files--;
                return -1;
@@ -492,9 +453,8 @@ razor_atomic_write(struct razor_atomic *atomic, int handle, const void *data,
        while(size) {
                if (!WriteFile(atomic->files[handle].h, data, size, &written,
                               NULL)) {
-                       razor_atomic_set_error(atomic,
-                                              atomic->files[handle].path,
-                                              GetLastError());
+                       atomic->error = razor_error_new_mswin(atomic->files[handle].path,
+                                                             GetLastError());
 
                        (void)CloseHandle(atomic->files[handle].h);
                        free(atomic->files[handle].path);
@@ -523,8 +483,8 @@ razor_atomic_sync(struct razor_atomic *atomic, int handle)
        assert(atomic->files[handle].h != INVALID_HANDLE_VALUE);
 
        if (!CloseHandle(atomic->files[handle].h)) {
-               razor_atomic_set_error(atomic, atomic->files[handle].path,
-                                      GetLastError());
+               atomic->error = razor_error_new_mswin(atomic->files[handle].path,
+                                                     GetLastError());
                free(atomic->files[handle].path);
                atomic->files[handle].path = NULL;
                atomic->files[handle].h = INVALID_HANDLE_VALUE;
@@ -537,14 +497,14 @@ razor_atomic_sync(struct razor_atomic *atomic, int handle)
        atomic->files[handle].h = h;
 
        if (atomic->files[handle].h == INVALID_HANDLE_VALUE) {
-               razor_atomic_set_error(atomic, atomic->files[handle].path,
-                                      GetLastError());
+               atomic->error = razor_error_new_mswin(atomic->files[handle].path,
+                                                     GetLastError());
                free(atomic->files[handle].path);
                atomic->files[handle].path = NULL;
                return -1;
        }
 
-       return !!atomic->error_str;
+       return razor_atomic_in_error_state(atomic);
 }
 
 RAZOR_EXPORT int
@@ -557,8 +517,8 @@ razor_atomic_close(struct razor_atomic *atomic, int handle)
        assert(atomic->files[handle].h != INVALID_HANDLE_VALUE);
 
        if (!CloseHandle(atomic->files[handle].h))
-               razor_atomic_set_error(atomic, atomic->files[handle].path,
-                                      GetLastError());
+               atomic->error = razor_error_new_mswin(atomic->files[handle].path,
+                                                     GetLastError());
 
        free(atomic->files[handle].path);
        atomic->files[handle].path = NULL;
@@ -568,7 +528,7 @@ razor_atomic_close(struct razor_atomic *atomic, int handle)
              atomic->files[atomic->n_files-1].h == INVALID_HANDLE_VALUE)
                atomic->n_files--;
 
-       return !!atomic->error_str;
+       return razor_atomic_in_error_state(atomic);
 }
 
 #endif         /* HAVE_WINDOWS_KTM */
index 75b7434..c06b7c7 100644 (file)
@@ -59,9 +59,9 @@ razor_atomic_commit(struct razor_atomic *atomic)
 RAZOR_EXPORT void
 razor_atomic_destroy(struct razor_atomic *atomic)
 {
-       free(atomic->error_path);
-       free(atomic->error_str);
-       free(atomic->error_msg);
+       if (atomic->error)
+               razor_error_free(atomic->error);
+
        free(atomic);
 }
 
@@ -97,13 +97,13 @@ razor_atomic_make_dirs(struct razor_atomic *atomic, const char *root,
 
                if (stat(buffer, &buf) == 0) {
                        if (!S_ISDIR(buf.st_mode)) {
-                               razor_atomic_set_error_str(atomic, buffer,
-                                                          "Not a directory");
+                               atomic->error = razor_error_new_str(buffer,
+                                                                   "Not a directory");
                                return -1;
                        }
                } else if (mkdir(buffer, 0777) < 0) {
-                       razor_atomic_set_error_str(atomic, buffer,
-                                                  strerror(errno));
+                       atomic->error = razor_error_new_str(buffer,
+                                                           strerror(errno));
                        return -1;
                }
        }
@@ -133,16 +133,16 @@ razor_atomic_remove(struct razor_atomic *atomic, const char *path)
                      DeleteFileW(buf)) &&
                    !RemoveDirectoryW(buf) &&
                    GetLastError() != ERROR_DIR_NOT_EMPTY)
-                       razor_atomic_set_error_mswin(atomic, buf, err);
+                       atomic->error = razor_error_new_mswin(buf, err);
        }
 
        free(buf);
 #else
        if (remove(path))
-               razor_atomic_set_error_str(atomic, path, strerror(errno));
+               atomic->error = razor_error_new_str(path, strerror(errno));
 #endif
 
-       return !!atomic->error_str;
+       return razor_atomic_in_error_state(atomic);
 }
 
 RAZOR_EXPORT int
@@ -170,16 +170,16 @@ razor_atomic_rename_file(struct razor_atomic *atomic, const char *oldpath,
        (void)RemoveDirectoryW(newbuf);
 
        if (!MoveFileExW(oldbuf, newbuf, flags))
-               razor_atomic_set_error_mswin(atomic, newbuf, GetLastError());
+               atomic->error = razor_error_new_mswin(newbuf, GetLastError());
 
        free(newbuf);
        free(oldbuf);
 #else
        if (rename(oldpath, newpath))
-               razor_atomic_set_error_str(atomic, newpath, strerror(errno));
+               atomic->error = razor_error_new_str(newpath, strerror(errno));
 #endif
 
-       return !!atomic->error_str;
+       return razor_atomic_in_error_state(atomic);
 }
 
 RAZOR_EXPORT int
@@ -193,12 +193,12 @@ razor_atomic_create_dir(struct razor_atomic *atomic, const char *dirname,
                return 0;
 
        if (errno != EEXIST) {
-               razor_atomic_set_error_str(atomic, dirname, strerror(errno));
+               atomic->error = razor_error_new_str(dirname, strerror(errno));
                return -1;
        }
 
        if (chmod(dirname, mode & (S_IRWXU | S_IRWXG | S_IRWXO)) < 0) {
-               razor_atomic_set_error_str(atomic, dirname, strerror(errno));
+               atomic->error = razor_error_new_str(dirname, strerror(errno));
                return -1;
        }
 
@@ -214,14 +214,15 @@ razor_atomic_create_symlink(struct razor_atomic *atomic, const char *target,
 
 #if HAVE_SYMLINK
        if (symlink(target, path) < 0) {
-               razor_atomic_set_error_str(atomic, NULL, strerror(errno));
+               atomic->error = razor_error_new_str(path, strerror(errno));
                return -1;
        }
 
        return 0;
 #else
-       razor_atomic_set_error_str(atomic, NULL, "Symbolic links not supported "
-                                                "on this platform");
+       atomic->error = razor_error_new_str(NULL,
+                                           "Symbolic links not supported "
+                                           "on this platform");
 
        return -1;
 #endif
@@ -236,12 +237,11 @@ razor_atomic_create_file(struct razor_atomic *atomic, const char *filename,
        if (razor_atomic_in_error_state(atomic))
                return -1;
 
-       atomic->error_path = strdup(filename);
-       fd = open(atomic->error_path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
+       fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
                  mode & (S_IRWXU | S_IRWXG | S_IRWXO));
 
        if (fd == -1)
-               razor_atomic_set_error_str(atomic, NULL, strerror(errno));
+               atomic->error = razor_error_new_str(filename, strerror(errno));
 
        return fd;
 }
index 261afe7..028d57e 100644 (file)
@@ -56,30 +56,23 @@ razor_allow_all_root_names(void)
 RAZOR_EXPORT const char *
 razor_atomic_get_error_msg(struct razor_atomic *atomic)
 {
-       if (!atomic->error_msg) {
-               if (atomic->error_path)
-                       atomic->error_msg = razor_concat(atomic->error_path,
-                                                        ": ",
-                                                        atomic->error_str,
-                                                        NULL);
-               else
-                       atomic->error_msg = strdup(atomic->error_str);
-       }
-
-       return atomic->error_msg;
+       if (atomic->error)
+               return razor_error_get_msg(atomic->error);
+       else
+               return NULL;
 }
 
 RAZOR_EXPORT void
 razor_atomic_abort(struct razor_atomic *atomic, const char *error_msg)
 {
-       if (!atomic->error_str)
-               razor_atomic_set_error_str(atomic, NULL, error_msg);
+       if (!atomic->error)
+               atomic->error = razor_error_new_str(NULL, error_msg);
 }
 
 RAZOR_EXPORT int
 razor_atomic_in_error_state(struct razor_atomic *atomic)
 {
-       return atomic->error_str && !atomic->in_undo;
+       return atomic->error && !atomic->in_undo;
 }
 
 #if !HAVE_WINDOWS_KTM
@@ -110,41 +103,6 @@ razor_valid_root_name(const char *name)
 #endif
 }
 
-#ifdef MSWIN_API
-void
-razor_atomic_set_error_mswin(struct razor_atomic *atomic, const wchar_t *path,
-                            DWORD error)
-{
-       wchar_t *buf;
-
-       assert(!atomic->error_str);
-
-       free(atomic->error_path);
-
-       if (path)
-               atomic->error_path = razor_utf16_to_utf8(path, -1);
-       else
-               atomic->error_path = NULL;
-
-       FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER|
-                      FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
-                      NULL, error, MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
-                      (LPWSTR)&buf, 0, NULL);
-       atomic->error_str = razor_utf16_to_utf8(buf, -1);
-       LocalFree(buf);
-}
-#endif
-
-void
-razor_atomic_set_error_str(struct razor_atomic *atomic, const char *path,
-                          const char *str)
-{
-       assert(!atomic->error_str);
-
-       atomic->error_path = path ? strdup(path) : NULL;
-       atomic->error_str = strdup(str);
-}
-
 RAZOR_EXPORT int
 razor_atomic_write(struct razor_atomic *atomic, int fd, const void *data,
                   size_t size)
@@ -157,8 +115,8 @@ razor_atomic_write(struct razor_atomic *atomic, int fd, const void *data,
        while(size) {
                written = write(fd, data, size);
                if (written < 0) {
-                       razor_atomic_set_error_str(atomic, NULL,
-                                                  strerror(errno));
+                       atomic->error = razor_error_new_str(NULL,
+                                                           strerror(errno));
 
                        (void)close(fd);
 
@@ -179,13 +137,10 @@ razor_atomic_sync(struct razor_atomic *atomic, int handle)
                return -1;
 
        if (fsync(handle) < 0) {
-               razor_atomic_set_error_str(atomic, NULL, strerror(errno));
+               atomic->error = razor_error_new_str(NULL, strerror(errno));
                return -1;
        }
 
-       free(atomic->error_path);
-       atomic->error_path = NULL;
-
        return 0;
 }
 
@@ -196,13 +151,10 @@ razor_atomic_close(struct razor_atomic *atomic, int fd)
                return -1;
 
        if (close(fd) < 0) {
-               razor_atomic_set_error_str(atomic, NULL, strerror(errno));
+               atomic->error = razor_error_new_str(NULL, strerror(errno));
                return -1;
        }
 
-       free(atomic->error_path);
-       atomic->error_path = NULL;
-
        return 0;
 }
 
diff --git a/librazor/error.c b/librazor/error.c
new file mode 100644 (file)
index 0000000..3670ff5
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2011-2012  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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#ifdef MSWIN_API
+#include <windows.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+
+#include "razor.h"
+#include "razor-internal.h"
+
+RAZOR_EXPORT const char *
+razor_error_get_msg(struct razor_error *error)
+{
+       if (!error->msg) {
+               if (error->path)
+                       error->msg = razor_concat(error->path, ": ", error->str,
+                                                 NULL);
+               else
+                       error->msg = strdup(error->str);
+       }
+
+       return error->msg;
+}
+
+#ifdef MSWIN_API
+struct razor_error *
+razor_error_new_mswin(const wchar_t *path, DWORD err)
+{
+       struct razor_error *error;
+       wchar_t *buf;
+
+       error = zalloc(sizeof *error);
+
+       if (path)
+               error->path = razor_utf16_to_utf8(path, -1);
+
+       FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER|
+                      FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
+                      NULL, err, MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
+                      (LPWSTR)&buf, 0, NULL);
+       error->str = razor_utf16_to_utf8(buf, -1);
+       LocalFree(buf);
+
+       return error;
+}
+#endif
+
+#if HAVE_WINDOWS_KTM
+struct razor_error *
+razor_error_new_str(const wchar_t *path, const char *str)
+#else
+struct razor_error *
+razor_error_new_str(const char *path, const char *str)
+#endif
+{
+       struct razor_error *error;
+
+       error = zalloc(sizeof *error);
+
+#if HAVE_WINDOWS_KTM
+       if (path)
+               error->path = razor_utf16_to_utf8(path, -1);
+#else
+       if (path)
+               error->path = strdup(path);
+#endif
+
+       error->str = strdup(str);
+
+       return error;
+}
+
+void razor_error_free(struct razor_error *error)
+{
+    free(error->path);
+    free(error->str);
+    free(error->msg);
+    free(error);
+}
index 790429d..691ef88 100644 (file)
@@ -242,6 +242,23 @@ char *razor_utf16_to_utf8(const wchar_t *utf16, int len);
 wchar_t *razor_utf8_to_utf16(const char *utf8, int len);
 #endif
 
+/* Error functions */
+struct razor_error {
+       char *path;
+       char *str;
+       char *msg;
+};
+
+#ifdef MSWIN_API
+struct razor_error *razor_error_new_mswin(const wchar_t *path, DWORD error);
+#endif
+
+#if HAVE_WINDOWS_KTM
+struct razor_error *razor_error_new_str(const wchar_t *path, const char *str);
+#else
+struct razor_error *razor_error_new_str(const char *path, const char *str);
+#endif
+
 /* Atomic functions */
 
 #if HAVE_WINDOWS_KTM
@@ -253,9 +270,7 @@ struct razor_atomic {
                HANDLE h;
        } *files;
        int in_undo;
-       char *error_path;
-       char *error_str;
-       char *error_msg;
+       struct razor_error *error;
 };
 #elif ENABLE_ATOMIC
 struct atomic_action {
@@ -298,9 +313,7 @@ struct razor_atomic {
        char *toplevel;
        unsigned next_file_tag;
        int in_undo;
-       char *error_path;
-       char *error_str;
-       char *error_msg;
+       struct razor_error *error;
 };
 
 char *atomic_action_attic_tmpnam(struct razor_atomic *atomic);
@@ -317,29 +330,11 @@ atomic_action_undo(struct razor_atomic *atomic, struct atomic_action *action);
 #else  /* !HAVE_WINDOWS_KTM && !ENABLE_ATOMIC */
 struct razor_atomic {
        int in_undo;
-       char *error_path;
-       char *error_str;
-       char *error_msg;
+       struct razor_error *error;
 };
 #endif
 
 int razor_allow_all_root_names(void);
 int razor_valid_root_name(const char *name);
 
-#ifdef MSWIN_API
-void
-razor_atomic_set_error_mswin(struct razor_atomic *atomic, const wchar_t *path,
-                            DWORD error);
-#endif
-
-#if HAVE_WINDOWS_KTM
-void
-razor_atomic_set_error_str(struct razor_atomic *atomic, const wchar_t *path,
-                          const char *str);
-#else
-void
-razor_atomic_set_error_str(struct razor_atomic *atomic, const char *path,
-                          const char *str);
-#endif
-
 #endif /* _RAZOR_INTERNAL_H_ */
index 8aeebf4..6ee7323 100644 (file)
@@ -96,6 +96,18 @@ enum razor_property_flags {
 };
 
 /**
+ * SECTION:error
+ * @title: Error reporting
+ * @short_description: A system for reporting errors.
+ *
+ * This object represents an error condition.
+ */
+struct razor_error;
+
+const char *razor_error_get_msg(struct razor_error *error);
+void razor_error_free(struct razor_error *error);
+
+/**
  * SECTION:atomic
  * @title: Atomic transactions
  * @short_description: File-based transactions that shouldn't half-succeed