Don't assume the current directory is writable 0.5.6
authorJ. Ali Harlow <ali@juiblex.co.uk>
Tue Mar 27 21:32:46 2012 +0100 (2012-03-27)
changeset 435275a4428c13b
parent 434 2c25dc58c6d2
child 436 e21194f5bd9c
child 437 b9cc58992572
Don't assume the current directory is writable
librazor/atomic-emulate.c
     1.1 --- a/librazor/atomic-emulate.c	Tue Mar 27 21:29:53 2012 +0100
     1.2 +++ b/librazor/atomic-emulate.c	Tue Mar 27 21:32:46 2012 +0100
     1.3 @@ -77,13 +77,6 @@
     1.4  
     1.5  	atomic = zalloc(sizeof *atomic);
     1.6  
     1.7 -	atomic->toplevel = strdup(".atomic-XXXXXX");
     1.8 -	if (!mkdtemp(atomic->toplevel)) {
     1.9 -		free(atomic->toplevel);
    1.10 -		free(atomic);
    1.11 -		return NULL;
    1.12 -	}
    1.13 -
    1.14  	atomic->description = strdup(description);
    1.15  
    1.16  	return atomic;
    1.17 @@ -126,12 +119,107 @@
    1.18  	free(atomic);
    1.19  }
    1.20  
    1.21 +/*
    1.22 + * We need a toplevel directory in which to hold temporary files
    1.23 + * before they are committed. Since we can generally assume that
    1.24 + * we have write permissions anywhere on the disk in question,
    1.25 + * the best location is in the relevant root directory. The most
    1.26 + * common case where this assumption fails is when testing, when
    1.27 + * the current directory is a good choice.
    1.28 + * It might be even better to find a mount point above path instead
    1.29 + * but this is hard to do, and probably not worth the effort.
    1.30 + */
    1.31 +
    1.32 +static int
    1.33 +razor_atomic_set_toplevel_from_path(struct razor_atomic *atomic,
    1.34 +				    const char *path)
    1.35 +{
    1.36 +	if (razor_atomic_in_error_state(atomic))
    1.37 +		return -1;
    1.38 +
    1.39 +	if (atomic->toplevel)
    1.40 +		return 0;
    1.41 +
    1.42 +#ifdef MSWIN_API
    1.43 +	if (path[0]=='\\' && path[1]=='\\' && path[2] && path[2]!='\\'
    1.44 +	    && strchr(path+3,'\\')) {
    1.45 +		/* We have a UNC path: \\servername\sharename... */
    1.46 +		const char *sharename, *root;
    1.47 +		int disklen;
    1.48 +
    1.49 +		sharename = strchr(path+3,'\\')+1;
    1.50 +		root = strchr(sharename,'\\');
    1.51 +		if (root)
    1.52 +		    disklen = root - path;
    1.53 +		else
    1.54 +		    disklen = strlen(path);
    1.55 +
    1.56 +		atomic->toplevel =
    1.57 +		  malloc(disklen + strlen("\\atomic-XXXXXX") + 1);
    1.58 +		memcpy(atomic->toplevel, path, disklen);
    1.59 +		strcpy(atomic->toplevel + disklen, "\\atomic-XXXXXX");
    1.60 +	} else if ((*path>='A' && *path<='Z' || *path>='a' && *path<='z') &&
    1.61 +		    path[1]==':') {
    1.62 +		atomic->toplevel = strdup("X:\\atomic-XXXXXX");
    1.63 +		*atomic->toplevel = *path;
    1.64 +	} else {
    1.65 +		DWORD n;
    1.66 +		wchar_t *buf;
    1.67 +		char *dir;
    1.68 +
    1.69 +		n = GetCurrentDirectoryW(0, NULL);
    1.70 +		buf = malloc(n * sizeof(wchar_t));
    1.71 +
    1.72 +		if (GetCurrentDirectoryW(n, buf)) {
    1.73 +			dir = razor_utf16_to_utf8(buf, n - 1);
    1.74 +			razor_atomic_set_toplevel_from_path(atomic, dir);
    1.75 +
    1.76 +			free(dir);
    1.77 +			free(buf);
    1.78 +			return;
    1.79 +		} else
    1.80 +			atomic->toplevel = strdup("C:\\atomic-XXXXXX");
    1.81 +
    1.82 +		free(buf);
    1.83 +	}
    1.84 +#else
    1.85 +	atomic->toplevel = strdup("/.atomic-XXXXXX");
    1.86 +#endif
    1.87 +
    1.88 +	if (!mkdtemp(atomic->toplevel)) {
    1.89 +		int err = errno;
    1.90 +
    1.91 +#ifdef EACCES
    1.92 +		if (err == EACCES) {
    1.93 +			char *s = strdup("atomic-XXXXXX");
    1.94 +
    1.95 +			if (mkdtemp(s)) {
    1.96 +				free(atomic->toplevel);
    1.97 +				atomic->toplevel = s;
    1.98 +				return 0;
    1.99 +			} else
   1.100 +				free(s);
   1.101 +		}
   1.102 +#endif
   1.103 +
   1.104 +		atomic->error = razor_error_new_str(atomic->toplevel,
   1.105 +						    strerror(err));
   1.106 +
   1.107 +		free(atomic->toplevel);
   1.108 +		atomic->toplevel = NULL;
   1.109 +	}
   1.110 +
   1.111 +	return !atomic->toplevel;
   1.112 +}
   1.113 +
   1.114  RAZOR_EXPORT int
   1.115  razor_atomic_make_dirs(struct razor_atomic *atomic, const char *root,
   1.116  		       const char *path)
   1.117  {
   1.118  	struct atomic_action *a;
   1.119  
   1.120 +	razor_atomic_set_toplevel_from_path(atomic, *root ? root : path);
   1.121 +
   1.122  	if (razor_atomic_in_error_state(atomic))
   1.123  		return -1;
   1.124  
   1.125 @@ -148,6 +236,8 @@
   1.126  {
   1.127  	struct atomic_action *a;
   1.128  
   1.129 +	razor_atomic_set_toplevel_from_path(atomic, path);
   1.130 +
   1.131  	if (razor_atomic_in_error_state(atomic))
   1.132  		return -1;
   1.133  
   1.134 @@ -164,6 +254,8 @@
   1.135  {
   1.136  	struct atomic_action *a;
   1.137  
   1.138 +	razor_atomic_set_toplevel_from_path(atomic, newpath);
   1.139 +
   1.140  	if (razor_atomic_in_error_state(atomic))
   1.141  		return -1;
   1.142  
   1.143 @@ -181,6 +273,8 @@
   1.144  {
   1.145  	struct atomic_action *a;
   1.146  
   1.147 +	razor_atomic_set_toplevel_from_path(atomic, dirname);
   1.148 +
   1.149  	if (razor_atomic_in_error_state(atomic))
   1.150  		return -1;
   1.151  
   1.152 @@ -198,6 +292,8 @@
   1.153  {
   1.154  #if HAVE_SYMLINK
   1.155  	struct atomic_action *a;
   1.156 +
   1.157 +	razor_atomic_set_toplevel_from_path(atomic, path);
   1.158  #endif
   1.159  
   1.160  	if (razor_atomic_in_error_state(atomic))
   1.161 @@ -227,6 +323,8 @@
   1.162  	struct atomic_action *a;
   1.163  	char *tmpnam;
   1.164  
   1.165 +	razor_atomic_set_toplevel_from_path(atomic, filename);
   1.166 +
   1.167  	if (razor_atomic_in_error_state(atomic))
   1.168  		return -1;
   1.169