Add an error object.
authorJ. Ali Harlow <ali@juiblex.co.uk>
Sat Feb 11 23:50:26 2012 +0000 (2012-02-11)
changeset 4236112bcc5d1cf
parent 422 6fa783097ca1
child 424 8cbc438cc298
Add an error object.
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
librazor/razor-internal.h
librazor/razor.h
     1.1 --- a/configure.ac	Sat Feb 11 09:49:58 2012 +0000
     1.2 +++ b/configure.ac	Sat Feb 11 23:50:26 2012 +0000
     1.3 @@ -10,9 +10,9 @@
     1.4  #
     1.5  # See http://sources.redhat.com/autobook/autobook/autobook_91.html#SEC91 for details
     1.6  #
     1.7 -LT_CURRENT=3
     1.8 +LT_CURRENT=4
     1.9  LT_REVISION=0
    1.10 -LT_AGE=1
    1.11 +LT_AGE=2
    1.12  AC_SUBST(LT_CURRENT)
    1.13  AC_SUBST(LT_REVISION)
    1.14  AC_SUBST(LT_AGE)
     2.1 --- a/librazor/Makefile.am	Sat Feb 11 09:49:58 2012 +0000
     2.2 +++ b/librazor/Makefile.am	Sat Feb 11 23:50:26 2012 +0000
     2.3 @@ -33,6 +33,7 @@
     2.4  	iterator.c					\
     2.5  	importer.c					\
     2.6  	merger.c					\
     2.7 +	error.c						\
     2.8  	atomic.c					\
     2.9  	atomic-ktm.c					\
    2.10  	atomic-none.c					\
     3.1 --- a/librazor/atomic-actions.c	Sat Feb 11 09:49:58 2012 +0000
     3.2 +++ b/librazor/atomic-actions.c	Sat Feb 11 23:50:26 2012 +0000
     3.3 @@ -259,9 +259,9 @@
     3.4  		return 0;
     3.5  
     3.6  	if (errno != EEXIST || chmod(action->args.path, mode) < 0) {
     3.7 -		if (!atomic->error_str)
     3.8 -			razor_atomic_set_error_str(atomic, action->args.path,
     3.9 -						   strerror(errno));
    3.10 +		if (!atomic->error)
    3.11 +			atomic->error = razor_error_new_str(action->args.path,
    3.12 +							    strerror(errno));
    3.13  		atomic_action_free(action);
    3.14  		return NULL;
    3.15  	}
    3.16 @@ -278,9 +278,9 @@
    3.17  	}
    3.18  
    3.19  	if (rmdir(action->args.path) < 0) {
    3.20 -		if (!atomic->error_str)
    3.21 -			razor_atomic_set_error_str(atomic, action->args.path,
    3.22 -						   strerror(errno));
    3.23 +		if (!atomic->error)
    3.24 +			atomic->error = razor_error_new_str(action->args.path,
    3.25 +							    strerror(errno));
    3.26  		atomic_action_free(action);
    3.27  		return NULL;
    3.28  	} else
    3.29 @@ -301,9 +301,9 @@
    3.30  
    3.31  	r = symlink(action->args.u.create_symlink.target, action->args.path);
    3.32  	if (r < 0) {
    3.33 -		if (!atomic->error_str)
    3.34 -			razor_atomic_set_error_str(atomic, NULL,
    3.35 -						   strerror(errno));
    3.36 +		if (!atomic->error)
    3.37 +			atomic->error = razor_error_new_str(action->args.path,
    3.38 +							    strerror(errno));
    3.39  		atomic_action_free(action);
    3.40  		return NULL;
    3.41  	}
    3.42 @@ -321,9 +321,9 @@
    3.43  	}
    3.44  
    3.45  	if (unlink(action->args.path) < 0) {
    3.46 -		if (!atomic->error_str)
    3.47 -			razor_atomic_set_error_str(atomic, NULL,
    3.48 -						   strerror(errno));
    3.49 +		if (!atomic->error)
    3.50 +			atomic->error = razor_error_new_str(action->args.path,
    3.51 +							    strerror(errno));
    3.52  		atomic_action_free(action);
    3.53  		return NULL;
    3.54  	}
    3.55 @@ -351,9 +351,9 @@
    3.56  	(void)RemoveDirectoryW(newbuf);
    3.57  
    3.58  	if (!MoveFileExW(oldbuf, newbuf, flags)) {
    3.59 -		if (!atomic->error_str)
    3.60 -			razor_atomic_set_error_mswin(atomic, newbuf,
    3.61 -						     GetLastError());
    3.62 +		if (!atomic->error)
    3.63 +			atomic->error = razor_error_new_mswin(newbuf,
    3.64 +							      GetLastError());
    3.65  		return -1;
    3.66  	}
    3.67  
    3.68 @@ -361,9 +361,9 @@
    3.69  	free(oldbuf);
    3.70  #else
    3.71  	if (rename(path, dest)) {
    3.72 -		if (!atomic->error_str)
    3.73 -			razor_atomic_set_error_str(atomic, dest,
    3.74 -						   strerror(errno));
    3.75 +		if (!atomic->error)
    3.76 +			atomic->error = razor_error_new_str(dest,
    3.77 +							    strerror(errno));
    3.78  		return -1;
    3.79  	}
    3.80  #endif
     4.1 --- a/librazor/atomic-emulate.c	Sat Feb 11 09:49:58 2012 +0000
     4.2 +++ b/librazor/atomic-emulate.c	Sat Feb 11 23:50:26 2012 +0000
     4.3 @@ -21,6 +21,7 @@
     4.4  #if ENABLE_ATOMIC && !HAVE_WINDOWS_KTM
     4.5  
     4.6  #include <stdlib.h>
     4.7 +#include <stdio.h>
     4.8  #include <string.h>
     4.9  #include <unistd.h>
    4.10  #include <sys/types.h>
    4.11 @@ -108,7 +109,7 @@
    4.12  		atomic->toplevel = NULL;
    4.13  	}
    4.14  
    4.15 -	return !!atomic->error_str;
    4.16 +	return razor_atomic_in_error_state(atomic);
    4.17  }
    4.18  
    4.19  RAZOR_EXPORT void razor_atomic_destroy(struct razor_atomic *atomic)
    4.20 @@ -119,9 +120,9 @@
    4.21  		atomic->toplevel = NULL;
    4.22  	}
    4.23  
    4.24 -	free(atomic->error_path);
    4.25 -	free(atomic->error_str);
    4.26 -	free(atomic->error_msg);
    4.27 +	if (atomic->error)
    4.28 +		razor_error_free(atomic->error);
    4.29 +
    4.30  	free(atomic);
    4.31  }
    4.32  
    4.33 @@ -210,8 +211,9 @@
    4.34  
    4.35  	return 0;
    4.36  #else
    4.37 -	razor_atomic_set_error_str(atomic, NULL, "Symbolic links not supported "
    4.38 -						 "on this platform");
    4.39 +	atomic->error = razor_error_new_str(NULL,
    4.40 +					    "Symbolic links not supported "
    4.41 +					    "on this platform");
    4.42  
    4.43  	return -1;
    4.44  #endif
    4.45 @@ -228,13 +230,12 @@
    4.46  	if (razor_atomic_in_error_state(atomic))
    4.47  		return -1;
    4.48  
    4.49 -	atomic->error_path = strdup(filename);
    4.50  	tmpnam = atomic_action_attic_tmpnam(atomic);
    4.51  	fd = open(tmpnam, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
    4.52  		  mode & (S_IRWXU | S_IRWXG | S_IRWXO));
    4.53  
    4.54  	if (fd == -1)
    4.55 -		razor_atomic_set_error_str(atomic, NULL, strerror(errno));
    4.56 +		atomic->error = razor_error_new_str(filename, strerror(errno));
    4.57  	else {
    4.58  		a = atomic_action_new(ACTION_MOVE);
    4.59  		a->args.path = tmpnam;
     5.1 --- a/librazor/atomic-ktm.c	Sat Feb 11 09:49:58 2012 +0000
     5.2 +++ b/librazor/atomic-ktm.c	Sat Feb 11 23:50:26 2012 +0000
     5.3 @@ -131,45 +131,6 @@
     5.4  	return atomic;
     5.5  }
     5.6  
     5.7 -void
     5.8 -razor_atomic_set_error_str(struct razor_atomic *atomic, const wchar_t *path,
     5.9 -			   const char *str)
    5.10 -{
    5.11 -	assert(!atomic->error_str);
    5.12 -
    5.13 -	free(atomic->error_path);
    5.14 -
    5.15 -	if (path)
    5.16 -		atomic->error_path = razor_utf16_to_utf8(path, -1);
    5.17 -	else
    5.18 -		atomic->error_path = NULL;
    5.19 -
    5.20 -	atomic->error_str = strdup(str);
    5.21 -}
    5.22 -
    5.23 -static void
    5.24 -razor_atomic_set_error(struct razor_atomic *atomic, const wchar_t *path,
    5.25 -		       DWORD error)
    5.26 -{
    5.27 -	wchar_t *buf;
    5.28 -
    5.29 -	assert(!atomic->error_str);
    5.30 -
    5.31 -	free(atomic->error_path);
    5.32 -
    5.33 -	if (path)
    5.34 -		atomic->error_path = razor_utf16_to_utf8(path, -1);
    5.35 -	else
    5.36 -		atomic->error_path = NULL;
    5.37 -
    5.38 -	FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER|
    5.39 -		       FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
    5.40 -		       NULL, error, MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
    5.41 -		       (LPWSTR)&buf, 0, NULL);
    5.42 -	atomic->error_str = razor_utf16_to_utf8(buf, -1);
    5.43 -	LocalFree(buf);
    5.44 -}
    5.45 -
    5.46  RAZOR_EXPORT int
    5.47  razor_atomic_commit(struct razor_atomic *atomic)
    5.48  {
    5.49 @@ -181,7 +142,7 @@
    5.50  	retval = !CommitTransaction(atomic->transaction);
    5.51  
    5.52  	if (retval) {
    5.53 -		razor_atomic_set_error(atomic, NULL, GetLastError());
    5.54 +		atomic->error = razor_error_new_mswin(NULL, GetLastError());
    5.55  		RollbackTransaction(atomic->transaction);
    5.56  	}
    5.57  
    5.58 @@ -207,9 +168,8 @@
    5.59  		RollbackTransaction(atomic->transaction);
    5.60  		CloseHandle(atomic->transaction);
    5.61  	}
    5.62 -	free(atomic->error_path);
    5.63 -	free(atomic->error_str);
    5.64 -	free(atomic->error_msg);
    5.65 +	if (atomic->error)
    5.66 +		razor_error_free(atomic->error);
    5.67  	free(atomic);
    5.68  }
    5.69  
    5.70 @@ -250,16 +210,15 @@
    5.71  				if (err == ERROR_FILE_NOT_FOUND) {
    5.72  					creating = 1;
    5.73  				} else {
    5.74 -					razor_atomic_set_error(atomic,
    5.75 -							       buffer->str,
    5.76 -							       err);
    5.77 +					atomic->error = razor_error_new_mswin(buffer->str,
    5.78 +									      err);
    5.79  					razor_wstr_destroy(buffer);
    5.80  					return -1;
    5.81  				}
    5.82  			} else if (!(fa.dwFileAttributes&
    5.83  				     FILE_ATTRIBUTE_DIRECTORY)) {
    5.84 -				razor_atomic_set_error_str(atomic, buffer->str,
    5.85 -							   "Not a directory");
    5.86 +				atomic->error = razor_error_new_str(buffer->str,
    5.87 +								    "Not a directory");
    5.88  				razor_wstr_destroy(buffer);
    5.89  				return -1;
    5.90  			}
    5.91 @@ -267,8 +226,8 @@
    5.92  		if (creating) {
    5.93  			if (!CreateDirectoryTransactedW(NULL, buffer->str, NULL,
    5.94  							atomic->transaction)) {
    5.95 -				razor_atomic_set_error(atomic, buffer->str,
    5.96 -						       GetLastError());
    5.97 +				atomic->error = razor_error_new_mswin(buffer->str,
    5.98 +								      GetLastError());
    5.99  				razor_wstr_destroy(buffer);
   5.100  				return -1;
   5.101  			}
   5.102 @@ -328,7 +287,7 @@
   5.103  	 * same path, this is likely to cause more problems than it solves.
   5.104  	 */
   5.105  
   5.106 -	razor_atomic_set_error(atomic, buf, err);
   5.107 +	atomic->error = razor_error_new_mswin(buf, err);
   5.108  	free(buf);
   5.109  	return -1;
   5.110  }
   5.111 @@ -356,12 +315,12 @@
   5.112  
   5.113  	if (!MoveFileTransactedW(oldbuf, newbuf, NULL, NULL, flags,
   5.114  			         atomic->transaction))
   5.115 -		razor_atomic_set_error(atomic, newbuf, GetLastError());
   5.116 +		atomic->error = razor_error_new_mswin(newbuf, GetLastError());
   5.117  
   5.118  	free(newbuf);
   5.119  	free(oldbuf);
   5.120  
   5.121 -	return !!atomic->error_str;
   5.122 +	return razor_atomic_in_error_state(atomic);
   5.123  }
   5.124  
   5.125  RAZOR_EXPORT int
   5.126 @@ -381,7 +340,7 @@
   5.127  		err = GetLastError();
   5.128  		if (err != ERROR_FILE_EXISTS && err != ERROR_ALREADY_EXISTS) {
   5.129  abort:
   5.130 -			razor_atomic_set_error(atomic, buf, err);
   5.131 +			atomic->error = razor_error_new_mswin(buf, err);
   5.132  			free(buf);
   5.133  			return -1;
   5.134  		}
   5.135 @@ -421,8 +380,9 @@
   5.136  	 * and we don't always know that at the time when the
   5.137  	 * link is created, so it's a convienent lie for now.
   5.138  	 */
   5.139 -	razor_atomic_set_error_str(atomic, NULL, "Symbolic links not supported "
   5.140 -						 "on this platform");
   5.141 +	atomic->error = razor_error_new_str(NULL,
   5.142 +					    "Symbolic links not supported "
   5.143 +					    "on this platform");
   5.144  
   5.145  	return -1;
   5.146  }
   5.147 @@ -441,7 +401,7 @@
   5.148  	files = realloc(atomic->files,
   5.149  			(atomic->n_files+1) * sizeof(struct razor_atomic_file));
   5.150  	if (!files) {
   5.151 -		razor_atomic_set_error_str(atomic, NULL, "Not enough memory");
   5.152 +		atomic->error = razor_error_new_str(NULL, "Not enough memory");
   5.153  		return -1;
   5.154  	}
   5.155  	atomic->n_files++;
   5.156 @@ -468,7 +428,8 @@
   5.157  					   NULL);
   5.158  
   5.159  	if (files[i].h == INVALID_HANDLE_VALUE) {
   5.160 -		razor_atomic_set_error(atomic, files[i].path, GetLastError());
   5.161 +		atomic->error = razor_error_new_mswin(files[i].path,
   5.162 +						      GetLastError());
   5.163  		free(files[i].path);
   5.164  		atomic->n_files--;
   5.165  		return -1;
   5.166 @@ -492,9 +453,8 @@
   5.167  	while(size) {
   5.168  		if (!WriteFile(atomic->files[handle].h, data, size, &written,
   5.169  			       NULL)) {
   5.170 -			razor_atomic_set_error(atomic,
   5.171 -					       atomic->files[handle].path,
   5.172 -					       GetLastError());
   5.173 +			atomic->error = razor_error_new_mswin(atomic->files[handle].path,
   5.174 +							      GetLastError());
   5.175  
   5.176  			(void)CloseHandle(atomic->files[handle].h);
   5.177  			free(atomic->files[handle].path);
   5.178 @@ -523,8 +483,8 @@
   5.179  	assert(atomic->files[handle].h != INVALID_HANDLE_VALUE);
   5.180  
   5.181  	if (!CloseHandle(atomic->files[handle].h)) {
   5.182 -		razor_atomic_set_error(atomic, atomic->files[handle].path,
   5.183 -				       GetLastError());
   5.184 +		atomic->error = razor_error_new_mswin(atomic->files[handle].path,
   5.185 +						      GetLastError());
   5.186  		free(atomic->files[handle].path);
   5.187  		atomic->files[handle].path = NULL;
   5.188  		atomic->files[handle].h = INVALID_HANDLE_VALUE;
   5.189 @@ -537,14 +497,14 @@
   5.190  	atomic->files[handle].h = h;
   5.191  
   5.192  	if (atomic->files[handle].h == INVALID_HANDLE_VALUE) {
   5.193 -		razor_atomic_set_error(atomic, atomic->files[handle].path,
   5.194 -				       GetLastError());
   5.195 +		atomic->error = razor_error_new_mswin(atomic->files[handle].path,
   5.196 +						      GetLastError());
   5.197  		free(atomic->files[handle].path);
   5.198  		atomic->files[handle].path = NULL;
   5.199  		return -1;
   5.200  	}
   5.201  
   5.202 -	return !!atomic->error_str;
   5.203 +	return razor_atomic_in_error_state(atomic);
   5.204  }
   5.205  
   5.206  RAZOR_EXPORT int
   5.207 @@ -557,8 +517,8 @@
   5.208  	assert(atomic->files[handle].h != INVALID_HANDLE_VALUE);
   5.209  
   5.210  	if (!CloseHandle(atomic->files[handle].h))
   5.211 -		razor_atomic_set_error(atomic, atomic->files[handle].path,
   5.212 -				       GetLastError());
   5.213 +		atomic->error = razor_error_new_mswin(atomic->files[handle].path,
   5.214 +						      GetLastError());
   5.215  
   5.216  	free(atomic->files[handle].path);
   5.217  	atomic->files[handle].path = NULL;
   5.218 @@ -568,7 +528,7 @@
   5.219  	      atomic->files[atomic->n_files-1].h == INVALID_HANDLE_VALUE)
   5.220  		atomic->n_files--;
   5.221  
   5.222 -	return !!atomic->error_str;
   5.223 +	return razor_atomic_in_error_state(atomic);
   5.224  }
   5.225  
   5.226  #endif		/* HAVE_WINDOWS_KTM */
     6.1 --- a/librazor/atomic-none.c	Sat Feb 11 09:49:58 2012 +0000
     6.2 +++ b/librazor/atomic-none.c	Sat Feb 11 23:50:26 2012 +0000
     6.3 @@ -59,9 +59,9 @@
     6.4  RAZOR_EXPORT void
     6.5  razor_atomic_destroy(struct razor_atomic *atomic)
     6.6  {
     6.7 -	free(atomic->error_path);
     6.8 -	free(atomic->error_str);
     6.9 -	free(atomic->error_msg);
    6.10 +	if (atomic->error)
    6.11 +		razor_error_free(atomic->error);
    6.12 +
    6.13  	free(atomic);
    6.14  }
    6.15  
    6.16 @@ -97,13 +97,13 @@
    6.17  
    6.18  		if (stat(buffer, &buf) == 0) {
    6.19  			if (!S_ISDIR(buf.st_mode)) {
    6.20 -				razor_atomic_set_error_str(atomic, buffer,
    6.21 -							   "Not a directory");
    6.22 +				atomic->error = razor_error_new_str(buffer,
    6.23 +								    "Not a directory");
    6.24  				return -1;
    6.25  			}
    6.26  		} else if (mkdir(buffer, 0777) < 0) {
    6.27 -			razor_atomic_set_error_str(atomic, buffer,
    6.28 -						   strerror(errno));
    6.29 +			atomic->error = razor_error_new_str(buffer,
    6.30 +							    strerror(errno));
    6.31  			return -1;
    6.32  		}
    6.33  	}
    6.34 @@ -133,16 +133,16 @@
    6.35  		      DeleteFileW(buf)) &&
    6.36  		    !RemoveDirectoryW(buf) &&
    6.37  		    GetLastError() != ERROR_DIR_NOT_EMPTY)
    6.38 -			razor_atomic_set_error_mswin(atomic, buf, err);
    6.39 +			atomic->error = razor_error_new_mswin(buf, err);
    6.40  	}
    6.41  
    6.42  	free(buf);
    6.43  #else
    6.44  	if (remove(path))
    6.45 -		razor_atomic_set_error_str(atomic, path, strerror(errno));
    6.46 +		atomic->error = razor_error_new_str(path, strerror(errno));
    6.47  #endif
    6.48  
    6.49 -	return !!atomic->error_str;
    6.50 +	return razor_atomic_in_error_state(atomic);
    6.51  }
    6.52  
    6.53  RAZOR_EXPORT int
    6.54 @@ -170,16 +170,16 @@
    6.55  	(void)RemoveDirectoryW(newbuf);
    6.56  
    6.57  	if (!MoveFileExW(oldbuf, newbuf, flags))
    6.58 -		razor_atomic_set_error_mswin(atomic, newbuf, GetLastError());
    6.59 +		atomic->error = razor_error_new_mswin(newbuf, GetLastError());
    6.60  
    6.61  	free(newbuf);
    6.62  	free(oldbuf);
    6.63  #else
    6.64  	if (rename(oldpath, newpath))
    6.65 -		razor_atomic_set_error_str(atomic, newpath, strerror(errno));
    6.66 +		atomic->error = razor_error_new_str(newpath, strerror(errno));
    6.67  #endif
    6.68  
    6.69 -	return !!atomic->error_str;
    6.70 +	return razor_atomic_in_error_state(atomic);
    6.71  }
    6.72  
    6.73  RAZOR_EXPORT int
    6.74 @@ -193,12 +193,12 @@
    6.75  		return 0;
    6.76  
    6.77  	if (errno != EEXIST) {
    6.78 -		razor_atomic_set_error_str(atomic, dirname, strerror(errno));
    6.79 +		atomic->error = razor_error_new_str(dirname, strerror(errno));
    6.80  		return -1;
    6.81  	}
    6.82  
    6.83  	if (chmod(dirname, mode & (S_IRWXU | S_IRWXG | S_IRWXO)) < 0) {
    6.84 -		razor_atomic_set_error_str(atomic, dirname, strerror(errno));
    6.85 +		atomic->error = razor_error_new_str(dirname, strerror(errno));
    6.86  		return -1;
    6.87  	}
    6.88  
    6.89 @@ -214,14 +214,15 @@
    6.90  
    6.91  #if HAVE_SYMLINK
    6.92  	if (symlink(target, path) < 0) {
    6.93 -		razor_atomic_set_error_str(atomic, NULL, strerror(errno));
    6.94 +		atomic->error = razor_error_new_str(path, strerror(errno));
    6.95  		return -1;
    6.96  	}
    6.97  
    6.98  	return 0;
    6.99  #else
   6.100 -	razor_atomic_set_error_str(atomic, NULL, "Symbolic links not supported "
   6.101 -						 "on this platform");
   6.102 +	atomic->error = razor_error_new_str(NULL,
   6.103 +					    "Symbolic links not supported "
   6.104 +					    "on this platform");
   6.105  
   6.106  	return -1;
   6.107  #endif
   6.108 @@ -236,12 +237,11 @@
   6.109  	if (razor_atomic_in_error_state(atomic))
   6.110  		return -1;
   6.111  
   6.112 -	atomic->error_path = strdup(filename);
   6.113 -	fd = open(atomic->error_path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
   6.114 +	fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
   6.115  		  mode & (S_IRWXU | S_IRWXG | S_IRWXO));
   6.116  
   6.117  	if (fd == -1)
   6.118 -		razor_atomic_set_error_str(atomic, NULL, strerror(errno));
   6.119 +		atomic->error = razor_error_new_str(filename, strerror(errno));
   6.120  
   6.121  	return fd;
   6.122  }
     7.1 --- a/librazor/atomic.c	Sat Feb 11 09:49:58 2012 +0000
     7.2 +++ b/librazor/atomic.c	Sat Feb 11 23:50:26 2012 +0000
     7.3 @@ -56,30 +56,23 @@
     7.4  RAZOR_EXPORT const char *
     7.5  razor_atomic_get_error_msg(struct razor_atomic *atomic)
     7.6  {
     7.7 -	if (!atomic->error_msg) {
     7.8 -		if (atomic->error_path)
     7.9 -			atomic->error_msg = razor_concat(atomic->error_path,
    7.10 -							 ": ",
    7.11 -							 atomic->error_str,
    7.12 -							 NULL);
    7.13 -		else
    7.14 -			atomic->error_msg = strdup(atomic->error_str);
    7.15 -	}
    7.16 -
    7.17 -	return atomic->error_msg;
    7.18 +	if (atomic->error)
    7.19 +		return razor_error_get_msg(atomic->error);
    7.20 +	else
    7.21 +		return NULL;
    7.22  }
    7.23  
    7.24  RAZOR_EXPORT void
    7.25  razor_atomic_abort(struct razor_atomic *atomic, const char *error_msg)
    7.26  {
    7.27 -	if (!atomic->error_str)
    7.28 -		razor_atomic_set_error_str(atomic, NULL, error_msg);
    7.29 +	if (!atomic->error)
    7.30 +		atomic->error = razor_error_new_str(NULL, error_msg);
    7.31  }
    7.32  
    7.33  RAZOR_EXPORT int
    7.34  razor_atomic_in_error_state(struct razor_atomic *atomic)
    7.35  {
    7.36 -	return atomic->error_str && !atomic->in_undo;
    7.37 +	return atomic->error && !atomic->in_undo;
    7.38  }
    7.39  
    7.40  #if !HAVE_WINDOWS_KTM
    7.41 @@ -110,41 +103,6 @@
    7.42  #endif
    7.43  }
    7.44  
    7.45 -#ifdef MSWIN_API
    7.46 -void
    7.47 -razor_atomic_set_error_mswin(struct razor_atomic *atomic, const wchar_t *path,
    7.48 -			     DWORD error)
    7.49 -{
    7.50 -	wchar_t *buf;
    7.51 -
    7.52 -	assert(!atomic->error_str);
    7.53 -
    7.54 -	free(atomic->error_path);
    7.55 -
    7.56 -	if (path)
    7.57 -		atomic->error_path = razor_utf16_to_utf8(path, -1);
    7.58 -	else
    7.59 -		atomic->error_path = NULL;
    7.60 -
    7.61 -	FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER|
    7.62 -		       FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
    7.63 -		       NULL, error, MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
    7.64 -		       (LPWSTR)&buf, 0, NULL);
    7.65 -	atomic->error_str = razor_utf16_to_utf8(buf, -1);
    7.66 -	LocalFree(buf);
    7.67 -}
    7.68 -#endif
    7.69 -
    7.70 -void
    7.71 -razor_atomic_set_error_str(struct razor_atomic *atomic, const char *path,
    7.72 -			   const char *str)
    7.73 -{
    7.74 -	assert(!atomic->error_str);
    7.75 -
    7.76 -	atomic->error_path = path ? strdup(path) : NULL;
    7.77 -	atomic->error_str = strdup(str);
    7.78 -}
    7.79 -
    7.80  RAZOR_EXPORT int
    7.81  razor_atomic_write(struct razor_atomic *atomic, int fd, const void *data,
    7.82  		   size_t size)
    7.83 @@ -157,8 +115,8 @@
    7.84  	while(size) {
    7.85  		written = write(fd, data, size);
    7.86  		if (written < 0) {
    7.87 -			razor_atomic_set_error_str(atomic, NULL,
    7.88 -						   strerror(errno));
    7.89 +			atomic->error = razor_error_new_str(NULL,
    7.90 +							    strerror(errno));
    7.91  
    7.92  			(void)close(fd);
    7.93  
    7.94 @@ -179,13 +137,10 @@
    7.95  		return -1;
    7.96  
    7.97  	if (fsync(handle) < 0) {
    7.98 -		razor_atomic_set_error_str(atomic, NULL, strerror(errno));
    7.99 +		atomic->error = razor_error_new_str(NULL, strerror(errno));
   7.100  		return -1;
   7.101  	}
   7.102  
   7.103 -	free(atomic->error_path);
   7.104 -	atomic->error_path = NULL;
   7.105 -
   7.106  	return 0;
   7.107  }
   7.108  
   7.109 @@ -196,13 +151,10 @@
   7.110  		return -1;
   7.111  
   7.112  	if (close(fd) < 0) {
   7.113 -		razor_atomic_set_error_str(atomic, NULL, strerror(errno));
   7.114 +		atomic->error = razor_error_new_str(NULL, strerror(errno));
   7.115  		return -1;
   7.116  	}
   7.117  
   7.118 -	free(atomic->error_path);
   7.119 -	atomic->error_path = NULL;
   7.120 -
   7.121  	return 0;
   7.122  }
   7.123  
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/librazor/error.c	Sat Feb 11 23:50:26 2012 +0000
     8.3 @@ -0,0 +1,98 @@
     8.4 +/*
     8.5 + * Copyright (C) 2011-2012  J. Ali Harlow <ali@juiblex.co.uk>
     8.6 + *
     8.7 + * This program is free software; you can redistribute it and/or modify
     8.8 + * it under the terms of the GNU General Public License as published by
     8.9 + * the Free Software Foundation; either version 2 of the License, or
    8.10 + * (at your option) any later version.
    8.11 + *
    8.12 + * This program is distributed in the hope that it will be useful,
    8.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    8.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    8.15 + * GNU General Public License for more details.
    8.16 + *
    8.17 + * You should have received a copy of the GNU General Public License along
    8.18 + * with this program; if not, write to the Free Software Foundation, Inc.,
    8.19 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
    8.20 + */
    8.21 +
    8.22 +#include "config.h"
    8.23 +
    8.24 +#ifdef MSWIN_API
    8.25 +#include <windows.h>
    8.26 +#endif
    8.27 +#include <stdlib.h>
    8.28 +#include <string.h>
    8.29 +
    8.30 +#include "razor.h"
    8.31 +#include "razor-internal.h"
    8.32 +
    8.33 +RAZOR_EXPORT const char *
    8.34 +razor_error_get_msg(struct razor_error *error)
    8.35 +{
    8.36 +	if (!error->msg) {
    8.37 +		if (error->path)
    8.38 +			error->msg = razor_concat(error->path, ": ", error->str,
    8.39 +						  NULL);
    8.40 +		else
    8.41 +			error->msg = strdup(error->str);
    8.42 +	}
    8.43 +
    8.44 +	return error->msg;
    8.45 +}
    8.46 +
    8.47 +#ifdef MSWIN_API
    8.48 +struct razor_error *
    8.49 +razor_error_new_mswin(const wchar_t *path, DWORD err)
    8.50 +{
    8.51 +	struct razor_error *error;
    8.52 +	wchar_t *buf;
    8.53 +
    8.54 +	error = zalloc(sizeof *error);
    8.55 +
    8.56 +	if (path)
    8.57 +		error->path = razor_utf16_to_utf8(path, -1);
    8.58 +
    8.59 +	FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER|
    8.60 +		       FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
    8.61 +		       NULL, err, MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
    8.62 +		       (LPWSTR)&buf, 0, NULL);
    8.63 +	error->str = razor_utf16_to_utf8(buf, -1);
    8.64 +	LocalFree(buf);
    8.65 +
    8.66 +	return error;
    8.67 +}
    8.68 +#endif
    8.69 +
    8.70 +#if HAVE_WINDOWS_KTM
    8.71 +struct razor_error *
    8.72 +razor_error_new_str(const wchar_t *path, const char *str)
    8.73 +#else
    8.74 +struct razor_error *
    8.75 +razor_error_new_str(const char *path, const char *str)
    8.76 +#endif
    8.77 +{
    8.78 +	struct razor_error *error;
    8.79 +
    8.80 +	error = zalloc(sizeof *error);
    8.81 +
    8.82 +#if HAVE_WINDOWS_KTM
    8.83 +	if (path)
    8.84 +		error->path = razor_utf16_to_utf8(path, -1);
    8.85 +#else
    8.86 +	if (path)
    8.87 +		error->path = strdup(path);
    8.88 +#endif
    8.89 +
    8.90 +	error->str = strdup(str);
    8.91 +
    8.92 +	return error;
    8.93 +}
    8.94 +
    8.95 +void razor_error_free(struct razor_error *error)
    8.96 +{
    8.97 +    free(error->path);
    8.98 +    free(error->str);
    8.99 +    free(error->msg);
   8.100 +    free(error);
   8.101 +}
     9.1 --- a/librazor/razor-internal.h	Sat Feb 11 09:49:58 2012 +0000
     9.2 +++ b/librazor/razor-internal.h	Sat Feb 11 23:50:26 2012 +0000
     9.3 @@ -242,6 +242,23 @@
     9.4  wchar_t *razor_utf8_to_utf16(const char *utf8, int len);
     9.5  #endif
     9.6  
     9.7 +/* Error functions */
     9.8 +struct razor_error {
     9.9 +	char *path;
    9.10 +	char *str;
    9.11 +	char *msg;
    9.12 +};
    9.13 +
    9.14 +#ifdef MSWIN_API
    9.15 +struct razor_error *razor_error_new_mswin(const wchar_t *path, DWORD error);
    9.16 +#endif
    9.17 +
    9.18 +#if HAVE_WINDOWS_KTM
    9.19 +struct razor_error *razor_error_new_str(const wchar_t *path, const char *str);
    9.20 +#else
    9.21 +struct razor_error *razor_error_new_str(const char *path, const char *str);
    9.22 +#endif
    9.23 +
    9.24  /* Atomic functions */
    9.25  
    9.26  #if HAVE_WINDOWS_KTM
    9.27 @@ -253,9 +270,7 @@
    9.28  		HANDLE h;
    9.29  	} *files;
    9.30  	int in_undo;
    9.31 -	char *error_path;
    9.32 -	char *error_str;
    9.33 -	char *error_msg;
    9.34 +	struct razor_error *error;
    9.35  };
    9.36  #elif ENABLE_ATOMIC
    9.37  struct atomic_action {
    9.38 @@ -298,9 +313,7 @@
    9.39  	char *toplevel;
    9.40  	unsigned next_file_tag;
    9.41  	int in_undo;
    9.42 -	char *error_path;
    9.43 -	char *error_str;
    9.44 -	char *error_msg;
    9.45 +	struct razor_error *error;
    9.46  };
    9.47  
    9.48  char *atomic_action_attic_tmpnam(struct razor_atomic *atomic);
    9.49 @@ -317,29 +330,11 @@
    9.50  #else	/* !HAVE_WINDOWS_KTM && !ENABLE_ATOMIC */
    9.51  struct razor_atomic {
    9.52  	int in_undo;
    9.53 -	char *error_path;
    9.54 -	char *error_str;
    9.55 -	char *error_msg;
    9.56 +	struct razor_error *error;
    9.57  };
    9.58  #endif
    9.59  
    9.60  int razor_allow_all_root_names(void);
    9.61  int razor_valid_root_name(const char *name);
    9.62  
    9.63 -#ifdef MSWIN_API
    9.64 -void
    9.65 -razor_atomic_set_error_mswin(struct razor_atomic *atomic, const wchar_t *path,
    9.66 -			     DWORD error);
    9.67 -#endif
    9.68 -
    9.69 -#if HAVE_WINDOWS_KTM
    9.70 -void
    9.71 -razor_atomic_set_error_str(struct razor_atomic *atomic, const wchar_t *path,
    9.72 -			   const char *str);
    9.73 -#else
    9.74 -void
    9.75 -razor_atomic_set_error_str(struct razor_atomic *atomic, const char *path,
    9.76 -			   const char *str);
    9.77 -#endif
    9.78 -
    9.79  #endif /* _RAZOR_INTERNAL_H_ */
    10.1 --- a/librazor/razor.h	Sat Feb 11 09:49:58 2012 +0000
    10.2 +++ b/librazor/razor.h	Sat Feb 11 23:50:26 2012 +0000
    10.3 @@ -96,6 +96,18 @@
    10.4  };
    10.5  
    10.6  /**
    10.7 + * SECTION:error
    10.8 + * @title: Error reporting
    10.9 + * @short_description: A system for reporting errors.
   10.10 + *
   10.11 + * This object represents an error condition.
   10.12 + */
   10.13 +struct razor_error;
   10.14 +
   10.15 +const char *razor_error_get_msg(struct razor_error *error);
   10.16 +void razor_error_free(struct razor_error *error);
   10.17 +
   10.18 +/**
   10.19   * SECTION:atomic
   10.20   * @title: Atomic transactions
   10.21   * @short_description: File-based transactions that shouldn't half-succeed