1.1 --- a/librazor/atomic-emulate.c Sat Feb 11 23:50:26 2012 +0000
1.2 +++ b/librazor/atomic-emulate.c Sat Aug 23 11:13:48 2014 +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