librazor/atomic-ktm.c
changeset 478 8e4bf84a7bb8
parent 475 008c75a5e08d
child 494 889dc38157ac
     1.1 --- a/librazor/atomic-ktm.c	Mon Jul 04 10:48:18 2016 +0100
     1.2 +++ b/librazor/atomic-ktm.c	Thu Jul 07 11:04:10 2016 +0100
     1.3 @@ -168,24 +168,84 @@
     1.4  	free(atomic);
     1.5  }
     1.6  
     1.7 +/*
     1.8 + * If root_uri is empty, then uri can be a URI (but not a relative-ref; ie.,
     1.9 + * a scheme must be specified). If root_uri is non-empty, then it must be a
    1.10 + * URI (but not a relative-ref) and uri must be a non-empty path.
    1.11 + */
    1.12  RAZOR_EXPORT int
    1.13 -razor_atomic_make_dirs(struct razor_atomic *atomic, const char *root,
    1.14 -		       const char *path)
    1.15 +razor_atomic_make_dirs(struct razor_atomic *atomic, const char *root_uri,
    1.16 +		       const char *uri)
    1.17  {
    1.18  	struct razor_wstr *buffer;
    1.19  	const char *slash, *next;
    1.20  	WIN32_FILE_ATTRIBUTE_DATA fa;
    1.21  	DWORD err;
    1.22  	int r, creating = 0;
    1.23 +	struct razor_uri ru;
    1.24 +	struct razor_error *tmp_error = NULL;
    1.25 +	char *s, *root, *path;
    1.26  
    1.27  	if (razor_atomic_in_error_state(atomic))
    1.28  		return -1;
    1.29  
    1.30 +	if (!*root_uri) {
    1.31 +                if (razor_uri_parse(&ru, uri, &tmp_error)) {
    1.32 +			razor_atomic_propagate_error(atomic, tmp_error, NULL);
    1.33 +			return -1;
    1.34 +		}
    1.35 +		s = SKIP_DRIVE_LETTER(ru.path);
    1.36 +		if (*s == '/')
    1.37 +			s++;
    1.38 +		*s = '\0';
    1.39 +		s = razor_uri_recompose(&ru);
    1.40 +		uri += strlen(s);
    1.41 +		free(s);
    1.42 +		root = razor_path_from_parsed_uri(&ru, &tmp_error);
    1.43 +		razor_uri_destroy(&ru);
    1.44 +		if (!root) {
    1.45 +			razor_atomic_propagate_error(atomic, tmp_error, NULL);
    1.46 +			return -1;
    1.47 +		}
    1.48 +		path = razor_path_from_uri(uri, &tmp_error);
    1.49 +		if (!path) {
    1.50 +			razor_atomic_propagate_error(atomic, tmp_error, NULL);
    1.51 +			free(root);
    1.52 +			return -1;
    1.53 +		}
    1.54 +	} else {
    1.55 +		root = razor_path_from_uri(root_uri, &tmp_error);
    1.56 +		if (!root) {
    1.57 +			razor_atomic_propagate_error(atomic, tmp_error, NULL);
    1.58 +			return -1;
    1.59 +		}
    1.60 +		s = razor_concat("file:", uri, NULL);
    1.61 +		path = razor_path_from_uri(s, &tmp_error);
    1.62 +		free(s);
    1.63 +		if (!path) {
    1.64 +			razor_atomic_propagate_error(atomic, tmp_error, NULL);
    1.65 +			free(root);
    1.66 +			return -1;
    1.67 +		}
    1.68 +		/*
    1.69 +		 * Arguably, razor_atomic_make_dirs(a, "file:///", "c:/xxx")
    1.70 +		 * is wrong, and we should be called as:
    1.71 +		 * razor_atomic_make_dirs(a, "file:///c:/", "xxx")
    1.72 +		 * but cope with it anyway.
    1.73 +		 */
    1.74 +		s = SKIP_DRIVE_LETTER(path);
    1.75 +		if (!strcmp(root, "/") && *s == '/') {
    1.76 +			free(root);
    1.77 +			root = strdup("");
    1.78 +		}
    1.79 +	}
    1.80 +
    1.81  	buffer = razor_wstr_create(root, -1);
    1.82 +	free(root);
    1.83  	slash = buffer->len ? SKIP_DRIVE_LETTER(path) : path;
    1.84  
    1.85  	for (; *slash != '\0'; slash = next) {
    1.86 -		next = strpbrk(slash + 1, "/\\");
    1.87 +		next = strchr(slash + 1, '/');
    1.88  		if (next == NULL)
    1.89  			break;
    1.90  
    1.91 @@ -208,6 +268,7 @@
    1.92  					razor_set_error_mswin(&atomic->error,
    1.93  							      buffer->str, err);
    1.94  					razor_wstr_destroy(buffer);
    1.95 +					free(path);
    1.96  					return -1;
    1.97  				}
    1.98  			} else if (!(fa.dwFileAttributes&
    1.99 @@ -217,6 +278,7 @@
   1.100  						 ERROR_DIRECTORY, buffer->str,
   1.101  						 "Not a directory");
   1.102  				razor_wstr_destroy(buffer);
   1.103 +				free(path);
   1.104  				return -1;
   1.105  			}
   1.106  		}
   1.107 @@ -227,6 +289,7 @@
   1.108  						      buffer->str,
   1.109  						      GetLastError());
   1.110  				razor_wstr_destroy(buffer);
   1.111 +				free(path);
   1.112  				return -1;
   1.113  			}
   1.114  
   1.115 @@ -236,21 +299,32 @@
   1.116  	}
   1.117  
   1.118  	razor_wstr_destroy(buffer);
   1.119 +	free(path);
   1.120  
   1.121  	return 0;
   1.122  }
   1.123  
   1.124  RAZOR_EXPORT int
   1.125 -razor_atomic_remove(struct razor_atomic *atomic, const char *path)
   1.126 +razor_atomic_remove(struct razor_atomic *atomic, const char *uri)
   1.127  {
   1.128 +	struct razor_error *tmp_error = NULL;
   1.129 +	char *path;
   1.130  	wchar_t *buf;
   1.131  	DWORD err;
   1.132  
   1.133  	if (razor_atomic_in_error_state(atomic))
   1.134  		return -1;
   1.135  
   1.136 +	path = razor_path_from_uri(uri, &tmp_error);
   1.137 +	if (!path) {
   1.138 +		razor_atomic_propagate_error(atomic, tmp_error, NULL);
   1.139 +		return -1;
   1.140 +	}
   1.141 +
   1.142  	buf = razor_utf8_to_utf16(path, -1);
   1.143  
   1.144 +	free(path);
   1.145 +
   1.146  	if (DeleteFileTransactedW(buf, atomic->transaction)) {
   1.147  		free(buf);
   1.148  		return 0;
   1.149 @@ -291,18 +365,36 @@
   1.150  }
   1.151  
   1.152  RAZOR_EXPORT int
   1.153 -razor_atomic_rename_file(struct razor_atomic *atomic, const char *oldpath,
   1.154 -			 const char *newpath)
   1.155 +razor_atomic_rename_file(struct razor_atomic *atomic, const char *old_uri,
   1.156 +			 const char *new_uri)
   1.157  {
   1.158 +	struct razor_error *tmp_error = NULL;
   1.159 +	char *oldpath, *newpath;
   1.160  	wchar_t *oldbuf, *newbuf;
   1.161  	const DWORD flags = MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING;
   1.162  
   1.163  	if (razor_atomic_in_error_state(atomic))
   1.164  		return -1;
   1.165  
   1.166 +	newpath = razor_path_from_uri(new_uri, &tmp_error);
   1.167 +	if (!newpath) {
   1.168 +		razor_atomic_propagate_error(atomic, tmp_error, NULL);
   1.169 +		return -1;
   1.170 +	}
   1.171 +
   1.172 +	oldpath = razor_path_from_uri(old_uri, &tmp_error);
   1.173 +	if (!oldpath) {
   1.174 +		razor_atomic_propagate_error(atomic, tmp_error, NULL);
   1.175 +		free(newpath);
   1.176 +		return -1;
   1.177 +	}
   1.178 +
   1.179  	newbuf = razor_utf8_to_utf16(newpath, -1);
   1.180  	oldbuf = razor_utf8_to_utf16(oldpath, -1);
   1.181  
   1.182 +	free(newpath);
   1.183 +	free(oldpath);
   1.184 +
   1.185  	/*
   1.186  	 * Passing MOVEFILE_REPLACE_EXISTING to MoveFileTransaction() will
   1.187  	 * cover every case we care about _except_ replacing an empty
   1.188 @@ -322,9 +414,11 @@
   1.189  }
   1.190  
   1.191  RAZOR_EXPORT int
   1.192 -razor_atomic_create_dir(struct razor_atomic *atomic, const char *dirname,
   1.193 +razor_atomic_create_dir(struct razor_atomic *atomic, const char *uri,
   1.194  			mode_t mode)
   1.195  {
   1.196 +	struct razor_error *tmp_error = NULL;
   1.197 +	char *dirname;
   1.198  	wchar_t *buf;
   1.199  	DWORD err;
   1.200  	WIN32_FILE_ATTRIBUTE_DATA fa;
   1.201 @@ -332,8 +426,16 @@
   1.202  	if (razor_atomic_in_error_state(atomic))
   1.203  		return -1;
   1.204  
   1.205 +	dirname = razor_path_from_uri(uri, &tmp_error);
   1.206 +	if (!dirname) {
   1.207 +		razor_atomic_propagate_error(atomic, tmp_error, NULL);
   1.208 +		return -1;
   1.209 +	}
   1.210 +
   1.211  	buf = razor_utf8_to_utf16(dirname, -1);
   1.212  
   1.213 +	free(dirname);
   1.214 +
   1.215  	if (!CreateDirectoryTransactedW(NULL, buf, NULL, atomic->transaction)) {
   1.216  		err = GetLastError();
   1.217  		if (err != ERROR_FILE_EXISTS && err != ERROR_ALREADY_EXISTS) {
   1.218 @@ -367,7 +469,7 @@
   1.219  
   1.220  RAZOR_EXPORT int
   1.221  razor_atomic_create_symlink(struct razor_atomic *atomic, const char *target,
   1.222 -			    const char *path)
   1.223 +			    const char *uri)
   1.224  {
   1.225  	if (razor_atomic_in_error_state(atomic))
   1.226  		return -1;
   1.227 @@ -385,9 +487,11 @@
   1.228  }
   1.229  
   1.230  RAZOR_EXPORT int
   1.231 -razor_atomic_create_file(struct razor_atomic *atomic, const char *filename,
   1.232 +razor_atomic_create_file(struct razor_atomic *atomic, const char *uri,
   1.233  			 mode_t mode)
   1.234  {
   1.235 +	struct razor_error *tmp_error = NULL;
   1.236 +	char *filename;
   1.237  	DWORD attribs;
   1.238  	struct razor_atomic_file *files;
   1.239  	int i = atomic->n_files;
   1.240 @@ -395,11 +499,18 @@
   1.241  	if (razor_atomic_in_error_state(atomic))
   1.242  		return -1;
   1.243  
   1.244 +	filename = razor_path_from_uri(uri, &tmp_error);
   1.245 +	if (!filename) {
   1.246 +		razor_atomic_propagate_error(atomic, tmp_error, NULL);
   1.247 +		return -1;
   1.248 +	}
   1.249 +
   1.250  	files = realloc(atomic->files,
   1.251  			(atomic->n_files+1) * sizeof(struct razor_atomic_file));
   1.252  	if (!files) {
   1.253  		razor_set_error(&atomic->error, RAZOR_POSIX_ERROR, ENOMEM, NULL,
   1.254  				"Not enough memory");
   1.255 +		free(filename);
   1.256  		return -1;
   1.257  	}
   1.258  	atomic->n_files++;
   1.259 @@ -407,6 +518,8 @@
   1.260  
   1.261  	files[i].path = razor_utf8_to_utf16(filename, -1);
   1.262  
   1.263 +	free(filename);
   1.264 +
   1.265  	/*
   1.266  	 * Passing CREATE_ALWAYS to CreateFileTransacted() will cover
   1.267  	 * every case we care about _except_ replacing an empty directory