librazor/atomic-none.c
author J. Ali Harlow <ali@juiblex.co.uk>
Tue Sep 09 15:04:24 2014 +0100 (2014-09-09)
changeset 446 4277359896dc
parent 423 6112bcc5d1cf
child 450 f969505e9265
permissions -rw-r--r--
Add razor_transaction_unsatisfied()
     1 /*
     2  * Copyright (C) 2011, 2012, 2014  J. Ali Harlow <ali@juiblex.co.uk>
     3  *
     4  * This program is free software; you can redistribute it and/or modify
     5  * it under the terms of the GNU General Public License as published by
     6  * the Free Software Foundation; either version 2 of the License, or
     7  * (at your option) any later version.
     8  *
     9  * This program is distributed in the hope that it will be useful,
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  * GNU General Public License for more details.
    13  *
    14  * You should have received a copy of the GNU General Public License along
    15  * with this program; if not, write to the Free Software Foundation, Inc.,
    16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
    17  */
    18 
    19 #include "config.h"
    20 
    21 #if !ENABLE_ATOMIC
    22 
    23 #include <stdlib.h>
    24 #ifdef MSWIN_API
    25 #include <windows.h>
    26 #endif
    27 #include <stdio.h>
    28 #include <limits.h>
    29 #include <errno.h>
    30 #include <unistd.h>
    31 #include <fcntl.h>
    32 #include <sys/stat.h>
    33 #include <string.h>
    34 #include <assert.h>
    35 
    36 #include "razor.h"
    37 #include "razor-internal.h"
    38 
    39 #ifndef O_BINARY
    40 #define O_BINARY	0
    41 #endif
    42 
    43 RAZOR_EXPORT struct razor_atomic *
    44 razor_atomic_open(const char *description)
    45 {
    46 	struct razor_atomic *atomic;
    47 
    48 	atomic = zalloc(sizeof *atomic);
    49 
    50 	return atomic;
    51 }
    52 
    53 RAZOR_EXPORT int
    54 razor_atomic_commit(struct razor_atomic *atomic)
    55 {
    56 	return razor_atomic_in_error_state(atomic);
    57 }
    58 
    59 RAZOR_EXPORT void
    60 razor_atomic_destroy(struct razor_atomic *atomic)
    61 {
    62 	if (atomic->error)
    63 		razor_error_free(atomic->error);
    64 
    65 	free(atomic);
    66 }
    67 
    68 RAZOR_EXPORT int
    69 razor_atomic_make_dirs(struct razor_atomic *atomic, const char *root,
    70 		       const char *path)
    71 {
    72 	char buffer[PATH_MAX], *p;
    73 	const char *slash, *next;
    74 	struct stat buf;
    75 
    76 	if (razor_atomic_in_error_state(atomic))
    77 		return -1;
    78 
    79 	strcpy(buffer, root);
    80 	p = buffer + strlen(buffer);
    81 	slash = (p > buffer) ? SKIP_DRIVE_PATH(path) : path;
    82 
    83 	for (slash = path; *slash != '\0'; slash = next) {
    84 #ifdef MSWIN_API
    85 		next = strpbrk(slash + 1, "/\\");
    86 #else
    87 		next = strchr(slash + 1, '/');
    88 #endif
    89 		if (next == NULL)
    90 			break;
    91 
    92 		memcpy(p, slash, next - slash);
    93 		p += next - slash;
    94 		*p = '\0';
    95 
    96 		if (razor_valid_root_name(buffer))
    97 			continue;
    98 
    99 		if (stat(buffer, &buf) == 0) {
   100 			if (!S_ISDIR(buf.st_mode)) {
   101 				atomic->error = razor_error_new_str(buffer,
   102 								    "Not a directory");
   103 				return -1;
   104 			}
   105 		} else if (mkdir(buffer, 0777) < 0) {
   106 			atomic->error = razor_error_new_str(buffer,
   107 							    strerror(errno));
   108 			return -1;
   109 		}
   110 	}
   111 
   112 	return 0;
   113 }
   114 
   115 RAZOR_EXPORT int
   116 razor_atomic_remove(struct razor_atomic *atomic, const char *path)
   117 {
   118 #ifdef MSWIN_API
   119 	wchar_t *buf;
   120 	DWORD err;
   121 #endif
   122 
   123 	if (razor_atomic_in_error_state(atomic))
   124 		return -1;
   125 
   126 #ifdef MSWIN_API
   127 	buf = razor_utf8_to_utf16(path, -1);
   128 
   129 	if (!DeleteFileW(buf)) {
   130 		err = GetLastError();
   131 		if (err != ERROR_FILE_NOT_FOUND &&
   132 		    err != ERROR_PATH_NOT_FOUND &&
   133 		    !(SetFileAttributesW(buf, FILE_ATTRIBUTE_NORMAL) &&
   134 		      DeleteFileW(buf)) &&
   135 		    !RemoveDirectoryW(buf) &&
   136 		    GetLastError() != ERROR_DIR_NOT_EMPTY)
   137 			atomic->error = razor_error_new_mswin(buf, err);
   138 	}
   139 
   140 	free(buf);
   141 #else
   142 	if (remove(path))
   143 		atomic->error = razor_error_new_str(path, strerror(errno));
   144 #endif
   145 
   146 	return razor_atomic_in_error_state(atomic);
   147 }
   148 
   149 RAZOR_EXPORT int
   150 razor_atomic_rename_file(struct razor_atomic *atomic, const char *oldpath,
   151 			 const char *newpath)
   152 {
   153 #ifdef MSWIN_API
   154 	wchar_t *oldbuf, *newbuf;
   155 	const DWORD flags = MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING;
   156 #endif
   157 
   158 	if (razor_atomic_in_error_state(atomic))
   159 		return -1;
   160 
   161 #ifdef MSWIN_API
   162 	newbuf = razor_utf8_to_utf16(newpath, -1);
   163 	oldbuf = razor_utf8_to_utf16(oldpath, -1);
   164 
   165 	/*
   166 	 * Passing MOVEFILE_REPLACE_EXISTING to MoveFileEx() will
   167 	 * cover every case we care about _except_ replacing an empty
   168 	 * directory with a file. Calling RemoveDirectory() will deal
   169 	 * with this case while having no effect in all other cases.
   170 	 */
   171 	(void)RemoveDirectoryW(newbuf);
   172 
   173 	if (!MoveFileExW(oldbuf, newbuf, flags))
   174 		atomic->error = razor_error_new_mswin(newbuf, GetLastError());
   175 
   176 	free(newbuf);
   177 	free(oldbuf);
   178 #else
   179 	if (rename(oldpath, newpath))
   180 		atomic->error = razor_error_new_str(newpath, strerror(errno));
   181 #endif
   182 
   183 	return razor_atomic_in_error_state(atomic);
   184 }
   185 
   186 RAZOR_EXPORT int
   187 razor_atomic_create_dir(struct razor_atomic *atomic, const char *dirname,
   188 			mode_t mode)
   189 {
   190 	if (razor_atomic_in_error_state(atomic))
   191 		return -1;
   192 
   193 	if (!mkdir(dirname, mode & (S_IRWXU | S_IRWXG | S_IRWXO)))
   194 		return 0;
   195 
   196 	if (errno != EEXIST) {
   197 		atomic->error = razor_error_new_str(dirname, strerror(errno));
   198 		return -1;
   199 	}
   200 
   201 	if (chmod(dirname, mode & (S_IRWXU | S_IRWXG | S_IRWXO)) < 0) {
   202 		atomic->error = razor_error_new_str(dirname, strerror(errno));
   203 		return -1;
   204 	}
   205 
   206 	return 0;
   207 }
   208 
   209 RAZOR_EXPORT int
   210 razor_atomic_create_symlink(struct razor_atomic *atomic, const char *target,
   211 			    const char *path)
   212 {
   213 	if (razor_atomic_in_error_state(atomic))
   214 		return -1;
   215 
   216 #if HAVE_SYMLINK
   217 	if (symlink(target, path) < 0) {
   218 		atomic->error = razor_error_new_str(path, strerror(errno));
   219 		return -1;
   220 	}
   221 
   222 	return 0;
   223 #else
   224 	atomic->error = razor_error_new_str(NULL,
   225 					    "Symbolic links not supported "
   226 					    "on this platform");
   227 
   228 	return -1;
   229 #endif
   230 }
   231 
   232 RAZOR_EXPORT int
   233 razor_atomic_create_file(struct razor_atomic *atomic, const char *filename,
   234 			 mode_t mode)
   235 {
   236 	int fd;
   237 
   238 	if (razor_atomic_in_error_state(atomic))
   239 		return -1;
   240 
   241 	fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
   242 		  mode & (S_IRWXU | S_IRWXG | S_IRWXO));
   243 
   244 	if (fd == -1)
   245 		atomic->error = razor_error_new_str(filename, strerror(errno));
   246 
   247 	return fd;
   248 }
   249 
   250 #endif	/* !ENABLE_ATOMIC */