From: J. Ali Harlow Date: Tue, 27 Mar 2012 20:32:46 +0000 (+0100) Subject: Don't assume the current directory is writable X-Git-Tag: 0.5.6 X-Git-Url: http://project.juiblex.co.uk/git/?a=commitdiff_plain;h=1e38842bbf7986bdc913c8ef0ccec1c4aed58418;p=razor2.git%2F.git Don't assume the current directory is writable --- diff --git a/librazor/atomic-emulate.c b/librazor/atomic-emulate.c index a467626..1ba8f96 100644 --- a/librazor/atomic-emulate.c +++ b/librazor/atomic-emulate.c @@ -77,13 +77,6 @@ RAZOR_EXPORT struct razor_atomic *razor_atomic_open(const char *description) atomic = zalloc(sizeof *atomic); - atomic->toplevel = strdup(".atomic-XXXXXX"); - if (!mkdtemp(atomic->toplevel)) { - free(atomic->toplevel); - free(atomic); - return NULL; - } - atomic->description = strdup(description); return atomic; @@ -126,12 +119,107 @@ RAZOR_EXPORT void razor_atomic_destroy(struct razor_atomic *atomic) free(atomic); } +/* + * We need a toplevel directory in which to hold temporary files + * before they are committed. Since we can generally assume that + * we have write permissions anywhere on the disk in question, + * the best location is in the relevant root directory. The most + * common case where this assumption fails is when testing, when + * the current directory is a good choice. + * It might be even better to find a mount point above path instead + * but this is hard to do, and probably not worth the effort. + */ + +static int +razor_atomic_set_toplevel_from_path(struct razor_atomic *atomic, + const char *path) +{ + if (razor_atomic_in_error_state(atomic)) + return -1; + + if (atomic->toplevel) + return 0; + +#ifdef MSWIN_API + if (path[0]=='\\' && path[1]=='\\' && path[2] && path[2]!='\\' + && strchr(path+3,'\\')) { + /* We have a UNC path: \\servername\sharename... */ + const char *sharename, *root; + int disklen; + + sharename = strchr(path+3,'\\')+1; + root = strchr(sharename,'\\'); + if (root) + disklen = root - path; + else + disklen = strlen(path); + + atomic->toplevel = + malloc(disklen + strlen("\\atomic-XXXXXX") + 1); + memcpy(atomic->toplevel, path, disklen); + strcpy(atomic->toplevel + disklen, "\\atomic-XXXXXX"); + } else if ((*path>='A' && *path<='Z' || *path>='a' && *path<='z') && + path[1]==':') { + atomic->toplevel = strdup("X:\\atomic-XXXXXX"); + *atomic->toplevel = *path; + } else { + DWORD n; + wchar_t *buf; + char *dir; + + n = GetCurrentDirectoryW(0, NULL); + buf = malloc(n * sizeof(wchar_t)); + + if (GetCurrentDirectoryW(n, buf)) { + dir = razor_utf16_to_utf8(buf, n - 1); + razor_atomic_set_toplevel_from_path(atomic, dir); + + free(dir); + free(buf); + return; + } else + atomic->toplevel = strdup("C:\\atomic-XXXXXX"); + + free(buf); + } +#else + atomic->toplevel = strdup("/.atomic-XXXXXX"); +#endif + + if (!mkdtemp(atomic->toplevel)) { + int err = errno; + +#ifdef EACCES + if (err == EACCES) { + char *s = strdup("atomic-XXXXXX"); + + if (mkdtemp(s)) { + free(atomic->toplevel); + atomic->toplevel = s; + return 0; + } else + free(s); + } +#endif + + atomic->error = razor_error_new_str(atomic->toplevel, + strerror(err)); + + free(atomic->toplevel); + atomic->toplevel = NULL; + } + + return !atomic->toplevel; +} + RAZOR_EXPORT int razor_atomic_make_dirs(struct razor_atomic *atomic, const char *root, const char *path) { struct atomic_action *a; + razor_atomic_set_toplevel_from_path(atomic, *root ? root : path); + if (razor_atomic_in_error_state(atomic)) return -1; @@ -148,6 +236,8 @@ razor_atomic_remove(struct razor_atomic *atomic, const char *path) { struct atomic_action *a; + razor_atomic_set_toplevel_from_path(atomic, path); + if (razor_atomic_in_error_state(atomic)) return -1; @@ -164,6 +254,8 @@ razor_atomic_rename_file(struct razor_atomic *atomic, const char *oldpath, { struct atomic_action *a; + razor_atomic_set_toplevel_from_path(atomic, newpath); + if (razor_atomic_in_error_state(atomic)) return -1; @@ -181,6 +273,8 @@ razor_atomic_create_dir(struct razor_atomic *atomic, const char *dirname, { struct atomic_action *a; + razor_atomic_set_toplevel_from_path(atomic, dirname); + if (razor_atomic_in_error_state(atomic)) return -1; @@ -198,6 +292,8 @@ razor_atomic_create_symlink(struct razor_atomic *atomic, const char *target, { #if HAVE_SYMLINK struct atomic_action *a; + + razor_atomic_set_toplevel_from_path(atomic, path); #endif if (razor_atomic_in_error_state(atomic)) @@ -227,6 +323,8 @@ razor_atomic_create_file(struct razor_atomic *atomic, const char *filename, struct atomic_action *a; char *tmpnam; + razor_atomic_set_toplevel_from_path(atomic, filename); + if (razor_atomic_in_error_state(atomic)) return -1;