From 6c55425a7de23a71d0abc3137f0015e878188bae Mon Sep 17 00:00:00 2001 From: Stef Walter Date: Sun, 3 Mar 2013 10:03:40 +0100 Subject: Windows doesn't support symlinks, chmod, or atomic renames * Don't create symlinks on windows * No atomic renames, so delete and then rename * Make sure to close files before unlinking on windows * No chmod permissions on windows --- tools/extract-openssl.c | 14 +++++++++++++- tools/save.c | 44 ++++++++++++++++++++++++++++++++++++++++++-- tools/save.h | 4 ++++ tools/tests/test-openssl.c | 7 ++++++- tools/tests/test-save.c | 26 ++++++++++++++++++++++++-- tools/tests/test.c | 4 ++++ tools/tests/test.h | 8 ++++++++ 7 files changed, 101 insertions(+), 6 deletions(-) diff --git a/tools/extract-openssl.c b/tools/extract-openssl.c index ae1bc27..c2cdeab 100644 --- a/tools/extract-openssl.c +++ b/tools/extract-openssl.c @@ -506,6 +506,8 @@ p11_openssl_canon_name_der (p11_dict *asn1_defs, return !failed; } +#ifdef OS_UNIX + static char * symlink_for_subject_hash (p11_extract_info *ex) { @@ -564,6 +566,8 @@ symlink_for_subject_old_hash (p11_extract_info *ex) return linkname; } +#endif /* OS_UNIX */ + bool p11_extract_openssl_directory (P11KitIter *iter, p11_extract_info *ex) @@ -573,12 +577,15 @@ p11_extract_openssl_directory (P11KitIter *iter, p11_save_dir *dir; p11_buffer buf; bool ret = true; - char *linkname; char *name; size_t length; char *pem; CK_RV rv; +#ifdef OS_UNIX + char *linkname; +#endif + dir = p11_save_open_directory (ex->destination, ex->flags); if (dir == NULL) return false; @@ -611,9 +618,13 @@ p11_extract_openssl_directory (P11KitIter *iter, * * The trailing number is incremented p11_save_symlink_in() if it * conflicts with something we've already written out. + * + * On Windows no symlinks. */ ret = true; + +#ifdef OS_UNIX linkname = symlink_for_subject_hash (ex); if (file && linkname) { ret = p11_save_symlink_in (dir, linkname, ".0", filename); @@ -625,6 +636,7 @@ p11_extract_openssl_directory (P11KitIter *iter, ret = p11_save_symlink_in (dir, linkname, ".0", filename); free (linkname); } +#endif /* OS_UNIX */ if (ret) ret = p11_save_write_and_finish (file, pem, length); diff --git a/tools/save.c b/tools/save.c index 695c1fc..34caca1 100644 --- a/tools/save.c +++ b/tools/save.c @@ -171,12 +171,13 @@ p11_save_finish_file (p11_save_file *file, return false; if (!commit) { - unlink (file->temp); close (file->fd); + unlink (file->temp); filo_free (file); return true; } +#ifdef OS_UNIX /* Set the mode of the file */ if (chmod (file->temp, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) < 0) { p11_message ("couldn't set file permissions: %s: %s", @@ -184,11 +185,16 @@ p11_save_finish_file (p11_save_file *file, close (file->fd); ret = false; - } else if (close (file->fd) < 0) { + } else +#endif /* OS_UNIX */ + + if (close (file->fd) < 0) { p11_message ("couldn't write file: %s: %s", file->temp, strerror (errno)); ret = false; +#ifdef OS_UNIX + /* Atomically rename the tempfile over the filename */ } else if (file->flags & P11_SAVE_OVERWRITE) { if (rename (file->temp, file->path) < 0) { @@ -207,6 +213,30 @@ p11_save_finish_file (p11_save_file *file, ret = false; } unlink (file->temp); + +#else /* OS_WIN32 */ + + /* Windows does not do atomic renames, so delete original file first */ + } else { + if (file->flags & P11_SAVE_OVERWRITE) { + if (unlink (file->path) < 0 && errno != ENOENT) { + p11_message ("couldn't remove original file: %s: %s", + file->path, strerror (errno)); + ret = false; + } + } + + if (ret == true) { + if (rename (file->temp, file->path) < 0) { + p11_message ("couldn't complete writing file: %s: %s", + file->path, strerror (errno)); + ret = false; + } + } + + unlink (file->temp); + +#endif /* OS_WIN32 */ } filo_free (file); @@ -217,12 +247,18 @@ p11_save_dir * p11_save_open_directory (const char *path, int flags) { +#ifdef OS_UNIX mode_t mode = S_IRWXU | S_IXGRP | S_IRGRP | S_IROTH | S_IXOTH; +#endif p11_save_dir *dir; return_val_if_fail (path != NULL, NULL); +#ifdef OS_UNIX if (mkdir (path, mode) < 0) { +#else /* OS_WIN32 */ + if (mkdir (path) < 0) { +#endif if (!(flags & P11_SAVE_OVERWRITE) || errno != EEXIST) { p11_message ("directory already exists: %s", path); return NULL; @@ -334,6 +370,8 @@ p11_save_open_file_in (p11_save_dir *dir, return file; } +#ifdef OS_UNIX + bool p11_save_symlink_in (p11_save_dir *dir, const char *linkname, @@ -373,6 +411,8 @@ p11_save_symlink_in (p11_save_dir *dir, return ret; } +#endif /* OS_UNIX */ + static bool cleanup_directory (const char *directory, p11_dict *cache) diff --git a/tools/save.h b/tools/save.h index 3e877ae..bfa0990 100644 --- a/tools/save.h +++ b/tools/save.h @@ -68,11 +68,15 @@ p11_save_file * p11_save_open_file_in (p11_save_dir *directory, const char *extension, const char **filename); +#ifdef OS_UNIX + bool p11_save_symlink_in (p11_save_dir *dir, const char *linkname, const char *extension, const char *destination); +#endif /* OS_UNIX */ + bool p11_save_finish_directory (p11_save_dir *dir, bool commit); diff --git a/tools/tests/test-openssl.c b/tools/tests/test-openssl.c index d242b50..bce9be6 100644 --- a/tools/tests/test-openssl.c +++ b/tools/tests/test-openssl.c @@ -599,15 +599,20 @@ test_directory (CuTest *tc) CuAssertIntEquals (tc, true, ret); test_check_directory (tc, test.directory, ("Custom_Label.pem", "Custom_Label.1.pem", - "e5662767.1", "e5662767.0", "590d426f.1", "590d426f.0", NULL)); +#ifdef OS_UNIX + "e5662767.1", "e5662767.0", "590d426f.1", "590d426f.0", +#endif + NULL)); test_check_file (tc, test.directory, "Custom_Label.pem", SRCDIR "/files/cacert3-trusted-client-server-alias.pem"); test_check_file (tc, test.directory, "Custom_Label.1.pem", SRCDIR "/files/cacert3-trusted-alias.pem"); +#ifdef OS_UNIX test_check_symlink (tc, test.directory, "e5662767.0", "Custom_Label.pem"); test_check_symlink (tc, test.directory, "e5662767.1", "Custom_Label.1.pem"); test_check_symlink (tc, test.directory, "590d426f.0", "Custom_Label.pem"); test_check_symlink (tc, test.directory, "590d426f.1", "Custom_Label.1.pem"); +#endif teardown (tc); } diff --git a/tools/tests/test-save.c b/tools/tests/test-save.c index 743ba88..4ceb4a8 100644 --- a/tools/tests/test-save.c +++ b/tools/tests/test-save.c @@ -71,7 +71,7 @@ static void teardown (CuTest *tc) { if (rmdir (test.directory) < 0) - CuFail (tc, "rmdir() failed"); + CuFail (tc, strerror (errno)); free (test.directory); } @@ -288,16 +288,24 @@ test_directory_files (CuTest *tc) CuAssertIntEquals (tc, true, ret); CuAssertStrEquals (tc, "file.txt", filename); +#ifdef OS_UNIX ret = p11_save_symlink_in (dir, "link", ".ext", "/the/destination"); CuAssertIntEquals (tc, true, ret); +#endif ret = p11_save_finish_directory (dir, true); CuAssertIntEquals (tc, true, ret); - test_check_directory (tc, subdir, ("blah.cer", "file.txt", "link.ext", NULL)); + test_check_directory (tc, subdir, ("blah.cer", "file.txt", +#ifdef OS_UNIX + "link.ext", +#endif + NULL)); test_check_file (tc, subdir, "blah.cer", SRCDIR "/files/cacert3.der"); test_check_data (tc, subdir, "file.txt", test_text, strlen (test_text)); +#ifdef OS_UNIX test_check_symlink (tc, subdir, "link.ext", "/the/destination"); +#endif rmdir (subdir); free (subdir); @@ -351,11 +359,13 @@ test_directory_dups (CuTest *tc) test_text, 15); CuAssertIntEquals (tc, true, ret); +#ifdef OS_UNIX ret = p11_save_symlink_in (dir, "link", ".0", "/destination1"); CuAssertIntEquals (tc, true, ret); ret = p11_save_symlink_in (dir, "link", ".0", "/destination2"); CuAssertIntEquals (tc, true, ret); +#endif ret = p11_save_finish_directory (dir, true); CuAssertIntEquals (tc, true, ret); @@ -363,7 +373,9 @@ test_directory_dups (CuTest *tc) test_check_directory (tc, subdir, ("file.txt", "file.1.txt", "file.2.txt", "no-ext", "no-ext.1", "with-num.0", "with-num.1", +#ifdef OS_UNIX "link.0", "link.1", +#endif NULL)); test_check_data (tc, subdir, "file.txt", test_text, 5); test_check_data (tc, subdir, "file.1.txt", test_text, 10); @@ -372,8 +384,10 @@ test_directory_dups (CuTest *tc) test_check_data (tc, subdir, "no-ext.1", test_text, 16); test_check_data (tc, subdir, "with-num.0", test_text, 14); test_check_data (tc, subdir, "with-num.1", test_text, 15); +#ifdef OS_UNIX test_check_symlink (tc, subdir, "link.0", "/destination1"); test_check_symlink (tc, subdir, "link.1", "/destination2"); +#endif rmdir (subdir); free (subdir); @@ -392,7 +406,11 @@ test_directory_exists (CuTest *tc) if (asprintf (&subdir, "%s/%s", test.directory, "extract-dir") < 0) CuFail (tc, "asprintf() failed"); +#ifdef OS_UNIX if (mkdir (subdir, S_IRWXU) < 0) +#else + if (mkdir (subdir) < 0) +#endif CuFail (tc, "mkdir() failed"); p11_message_quiet (); @@ -421,7 +439,11 @@ test_directory_overwrite (CuTest *tc) if (asprintf (&subdir, "%s/%s", test.directory, "extract-dir") < 0) CuFail (tc, "asprintf() failed"); +#ifdef OS_UNIX if (mkdir (subdir, S_IRWXU) < 0) +#else + if (mkdir (subdir) < 0) +#endif CuFail (tc, "mkdir() failed"); /* Some initial files into this directory, which get overwritten */ diff --git a/tools/tests/test.c b/tools/tests/test.c index 61fda83..56e65cd 100644 --- a/tools/tests/test.c +++ b/tools/tests/test.c @@ -121,6 +121,8 @@ test_check_data_msg (CuTest *tc, free (filedata); } +#ifdef OS_UNIX + void test_check_symlink_msg (CuTest *tc, const char *file, @@ -144,6 +146,8 @@ test_check_symlink_msg (CuTest *tc, free (filename); } +#endif /* OS_UNIX */ + p11_dict * test_check_directory_files (const char *file, ...) diff --git a/tools/tests/test.h b/tools/tests/test.h index 7cf2492..82b8b2c 100644 --- a/tools/tests/test.h +++ b/tools/tests/test.h @@ -221,6 +221,8 @@ void test_check_data_msg (CuTest *tc, const void *refdata, long reflen); +#ifdef OS_UNIX + void test_check_symlink_msg (CuTest *tc, const char *file, int line, @@ -228,6 +230,8 @@ void test_check_symlink_msg (CuTest *tc, const char *name, const char *destination); +#endif /* OS_UNIX */ + p11_dict * test_check_directory_files (const char *file, ...) GNUC_NULL_TERMINATED; @@ -243,9 +247,13 @@ void test_check_directory_msg (CuTest *tc, #define test_check_data(tc, directory, name, data, length) \ (test_check_data_msg (tc, __FILE__, __LINE__, directory, name, data, length)) +#ifdef OS_UNIX + #define test_check_symlink(tc, directory, name, destination) \ (test_check_symlink_msg (tc, __FILE__, __LINE__, directory, name, destination)) +#endif /* OS_UNIX */ + #define test_check_directory(tc, directory, files) \ (test_check_directory_msg (tc, __FILE__, __LINE__, directory, \ test_check_directory_files files)) -- cgit v1.1