librazor/atomic-none.c
changeset 419 891991677a7f
child 423 6112bcc5d1cf
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/librazor/atomic-none.c	Thu Feb 09 20:45:27 2012 +0000
     1.3 @@ -0,0 +1,249 @@
     1.4 +/*
     1.5 + * Copyright (C) 2011-2012  J. Ali Harlow <ali@juiblex.co.uk>
     1.6 + *
     1.7 + * This program is free software; you can redistribute it and/or modify
     1.8 + * it under the terms of the GNU General Public License as published by
     1.9 + * the Free Software Foundation; either version 2 of the License, or
    1.10 + * (at your option) any later version.
    1.11 + *
    1.12 + * This program is distributed in the hope that it will be useful,
    1.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1.15 + * GNU General Public License for more details.
    1.16 + *
    1.17 + * You should have received a copy of the GNU General Public License along
    1.18 + * with this program; if not, write to the Free Software Foundation, Inc.,
    1.19 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
    1.20 + */
    1.21 +
    1.22 +#include "config.h"
    1.23 +
    1.24 +#if !ENABLE_ATOMIC
    1.25 +
    1.26 +#include <stdlib.h>
    1.27 +#ifdef MSWIN_API
    1.28 +#include <windows.h>
    1.29 +#endif
    1.30 +#include <stdio.h>
    1.31 +#include <limits.h>
    1.32 +#include <errno.h>
    1.33 +#include <unistd.h>
    1.34 +#include <fcntl.h>
    1.35 +#include <sys/stat.h>
    1.36 +#include <string.h>
    1.37 +#include <assert.h>
    1.38 +
    1.39 +#include "razor.h"
    1.40 +#include "razor-internal.h"
    1.41 +
    1.42 +#ifndef O_BINARY
    1.43 +#define O_BINARY	0
    1.44 +#endif
    1.45 +
    1.46 +RAZOR_EXPORT struct razor_atomic *
    1.47 +razor_atomic_open(const char *description)
    1.48 +{
    1.49 +	struct razor_atomic *atomic;
    1.50 +
    1.51 +	atomic = zalloc(sizeof *atomic);
    1.52 +
    1.53 +	return atomic;
    1.54 +}
    1.55 +
    1.56 +RAZOR_EXPORT int
    1.57 +razor_atomic_commit(struct razor_atomic *atomic)
    1.58 +{
    1.59 +	return razor_atomic_in_error_state(atomic);
    1.60 +}
    1.61 +
    1.62 +RAZOR_EXPORT void
    1.63 +razor_atomic_destroy(struct razor_atomic *atomic)
    1.64 +{
    1.65 +	free(atomic->error_path);
    1.66 +	free(atomic->error_str);
    1.67 +	free(atomic->error_msg);
    1.68 +	free(atomic);
    1.69 +}
    1.70 +
    1.71 +RAZOR_EXPORT int
    1.72 +razor_atomic_make_dirs(struct razor_atomic *atomic, const char *root,
    1.73 +		       const char *path)
    1.74 +{
    1.75 +	char buffer[PATH_MAX], *p;
    1.76 +	const char *slash, *next;
    1.77 +	struct stat buf;
    1.78 +
    1.79 +	if (razor_atomic_in_error_state(atomic))
    1.80 +		return -1;
    1.81 +
    1.82 +	strcpy(buffer, root);
    1.83 +	p = buffer + strlen(buffer);
    1.84 +	slash = path;
    1.85 +	for (slash = path; *slash != '\0'; slash = next) {
    1.86 +#ifdef MSWIN_API
    1.87 +		next = strpbrk(slash + 1, "/\\");
    1.88 +#else
    1.89 +		next = strchr(slash + 1, '/');
    1.90 +#endif
    1.91 +		if (next == NULL)
    1.92 +			break;
    1.93 +
    1.94 +		memcpy(p, slash, next - slash);
    1.95 +		p += next - slash;
    1.96 +		*p = '\0';
    1.97 +
    1.98 +		if (razor_valid_root_name(buffer))
    1.99 +			continue;
   1.100 +
   1.101 +		if (stat(buffer, &buf) == 0) {
   1.102 +			if (!S_ISDIR(buf.st_mode)) {
   1.103 +				razor_atomic_set_error_str(atomic, buffer,
   1.104 +							   "Not a directory");
   1.105 +				return -1;
   1.106 +			}
   1.107 +		} else if (mkdir(buffer, 0777) < 0) {
   1.108 +			razor_atomic_set_error_str(atomic, buffer,
   1.109 +						   strerror(errno));
   1.110 +			return -1;
   1.111 +		}
   1.112 +	}
   1.113 +
   1.114 +	return 0;
   1.115 +}
   1.116 +
   1.117 +RAZOR_EXPORT int
   1.118 +razor_atomic_remove(struct razor_atomic *atomic, const char *path)
   1.119 +{
   1.120 +#ifdef MSWIN_API
   1.121 +	wchar_t *buf;
   1.122 +	DWORD err;
   1.123 +#endif
   1.124 +
   1.125 +	if (razor_atomic_in_error_state(atomic))
   1.126 +		return -1;
   1.127 +
   1.128 +#ifdef MSWIN_API
   1.129 +	buf = razor_utf8_to_utf16(path, -1);
   1.130 +
   1.131 +	if (!DeleteFileW(buf)) {
   1.132 +		err = GetLastError();
   1.133 +		if (err != ERROR_FILE_NOT_FOUND &&
   1.134 +		    err != ERROR_PATH_NOT_FOUND &&
   1.135 +		    !(SetFileAttributesW(buf, FILE_ATTRIBUTE_NORMAL) &&
   1.136 +		      DeleteFileW(buf)) &&
   1.137 +		    !RemoveDirectoryW(buf) &&
   1.138 +		    GetLastError() != ERROR_DIR_NOT_EMPTY)
   1.139 +			razor_atomic_set_error_mswin(atomic, buf, err);
   1.140 +	}
   1.141 +
   1.142 +	free(buf);
   1.143 +#else
   1.144 +	if (remove(path))
   1.145 +		razor_atomic_set_error_str(atomic, path, strerror(errno));
   1.146 +#endif
   1.147 +
   1.148 +	return !!atomic->error_str;
   1.149 +}
   1.150 +
   1.151 +RAZOR_EXPORT int
   1.152 +razor_atomic_rename_file(struct razor_atomic *atomic, const char *oldpath,
   1.153 +			 const char *newpath)
   1.154 +{
   1.155 +#ifdef MSWIN_API
   1.156 +	wchar_t *oldbuf, *newbuf;
   1.157 +	const DWORD flags = MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING;
   1.158 +#endif
   1.159 +
   1.160 +	if (razor_atomic_in_error_state(atomic))
   1.161 +		return -1;
   1.162 +
   1.163 +#ifdef MSWIN_API
   1.164 +	newbuf = razor_utf8_to_utf16(newpath, -1);
   1.165 +	oldbuf = razor_utf8_to_utf16(oldpath, -1);
   1.166 +
   1.167 +	/*
   1.168 +	 * Passing MOVEFILE_REPLACE_EXISTING to MoveFileEx() will
   1.169 +	 * cover every case we care about _except_ replacing an empty
   1.170 +	 * directory with a file. Calling RemoveDirectory() will deal
   1.171 +	 * with this case while having no effect in all other cases.
   1.172 +	 */
   1.173 +	(void)RemoveDirectoryW(newbuf);
   1.174 +
   1.175 +	if (!MoveFileExW(oldbuf, newbuf, flags))
   1.176 +		razor_atomic_set_error_mswin(atomic, newbuf, GetLastError());
   1.177 +
   1.178 +	free(newbuf);
   1.179 +	free(oldbuf);
   1.180 +#else
   1.181 +	if (rename(oldpath, newpath))
   1.182 +		razor_atomic_set_error_str(atomic, newpath, strerror(errno));
   1.183 +#endif
   1.184 +
   1.185 +	return !!atomic->error_str;
   1.186 +}
   1.187 +
   1.188 +RAZOR_EXPORT int
   1.189 +razor_atomic_create_dir(struct razor_atomic *atomic, const char *dirname,
   1.190 +			mode_t mode)
   1.191 +{
   1.192 +	if (razor_atomic_in_error_state(atomic))
   1.193 +		return -1;
   1.194 +
   1.195 +	if (!mkdir(dirname, mode & (S_IRWXU | S_IRWXG | S_IRWXO)))
   1.196 +		return 0;
   1.197 +
   1.198 +	if (errno != EEXIST) {
   1.199 +		razor_atomic_set_error_str(atomic, dirname, strerror(errno));
   1.200 +		return -1;
   1.201 +	}
   1.202 +
   1.203 +	if (chmod(dirname, mode & (S_IRWXU | S_IRWXG | S_IRWXO)) < 0) {
   1.204 +		razor_atomic_set_error_str(atomic, dirname, strerror(errno));
   1.205 +		return -1;
   1.206 +	}
   1.207 +
   1.208 +	return 0;
   1.209 +}
   1.210 +
   1.211 +RAZOR_EXPORT int
   1.212 +razor_atomic_create_symlink(struct razor_atomic *atomic, const char *target,
   1.213 +			    const char *path)
   1.214 +{
   1.215 +	if (razor_atomic_in_error_state(atomic))
   1.216 +		return -1;
   1.217 +
   1.218 +#if HAVE_SYMLINK
   1.219 +	if (symlink(target, path) < 0) {
   1.220 +		razor_atomic_set_error_str(atomic, NULL, strerror(errno));
   1.221 +		return -1;
   1.222 +	}
   1.223 +
   1.224 +	return 0;
   1.225 +#else
   1.226 +	razor_atomic_set_error_str(atomic, NULL, "Symbolic links not supported "
   1.227 +						 "on this platform");
   1.228 +
   1.229 +	return -1;
   1.230 +#endif
   1.231 +}
   1.232 +
   1.233 +RAZOR_EXPORT int
   1.234 +razor_atomic_create_file(struct razor_atomic *atomic, const char *filename,
   1.235 +			 mode_t mode)
   1.236 +{
   1.237 +	int fd;
   1.238 +
   1.239 +	if (razor_atomic_in_error_state(atomic))
   1.240 +		return -1;
   1.241 +
   1.242 +	atomic->error_path = strdup(filename);
   1.243 +	fd = open(atomic->error_path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
   1.244 +		  mode & (S_IRWXU | S_IRWXG | S_IRWXO));
   1.245 +
   1.246 +	if (fd == -1)
   1.247 +		razor_atomic_set_error_str(atomic, NULL, strerror(errno));
   1.248 +
   1.249 +	return fd;
   1.250 +}
   1.251 +
   1.252 +#endif	/* !ENABLE_ATOMIC */