The following patch has been submitted to Bugzilla as bug # 44841. It creates
an APR wrapper for
the link(2) function in Unix, which corresponds to the CreateHardLink() function in Win32.
Regards,
- Mark
diff -x '*.lo' -x '*.mk' -x 'config.*' -ur
../apr.20080417222010/file_io/unix/copy.c ./file_io/unix/copy.c
--- ../apr.20080417222010/file_io/unix/copy.c 2008-04-17 21:01:23.000000000
-0400
+++ ./file_io/unix/copy.c 2008-04-18 18:22:22.000000000 -0400
@@ -110,3 +110,13 @@
perms,
pool);
}
+
+APR_DECLARE(apr_status_t) apr_file_link(const char *from_path,
+ const char *to_path)
+{
+ if (link(from_path, to_path) == -1) {
+ return errno;
+ }
+
+ return APR_SUCCESS;
+}
diff -x '*.lo' -x '*.mk' -x 'config.*' -ur
../apr.20080417222010/file_io/win32/open.c ./file_io/win32/open.c
--- ../apr.20080417222010/file_io/win32/open.c 2008-04-17 21:01:23.000000000
-0400
+++ ./file_io/win32/open.c 2008-04-18 18:21:36.000000000 -0400
@@ -578,6 +578,36 @@
return apr_get_os_error();
}
+APR_DECLARE(apr_status_t) apr_file_link(const char *from_path,
+ const char *to_path)
+{
+ apr_status_t rv;
+
+#if APR_HAS_UNICODE_FS
+ IF_WIN_OS_IS_UNICODE
+ {
+ apr_wchar_t wfrom_path[APR_PATH_MAX];
+ apr_wchar_t wto_path[APR_PATH_MAX];
+
+ if (rv = utf8_to_unicode_path(wfrom_path, sizeof(wfrom_path)
+ / sizeof(apr_wchar_t), from_path))
+ return rv;
+ if (rv = utf8_to_unicode_path(wto_path, sizeof(wto_path)
+ / sizeof(apr_wchar_t), to_path))
+ return rv;
+
+ if (!CreateHardLinkW(wto_path, wfrom_path))
+ return apr_get_os_error()
+ }
+#endif
+#if APR_HAS_ANSI_FS
+ ELSE_WIN_OS_IS_ANSI {
+ if (!CreateHardLinkA(wto_path, wfrom_path))
+ return apr_get_os_error()
+ }
+#endif
+}
+
APR_DECLARE(apr_status_t) apr_os_file_get(apr_os_file_t *thefile,
apr_file_t *file)
{
diff -x '*.lo' -x '*.mk' -x 'config.*' -ur
../apr.20080417222010/include/apr_file_io.h ./include/apr_file_io.h
--- ../apr.20080417222010/include/apr_file_io.h 2008-04-17 21:01:23.000000000
-0400
+++ ./include/apr_file_io.h 2008-04-18 18:23:13.000000000 -0400
@@ -265,6 +265,15 @@
apr_pool_t *pool);
/**
+ * Create a hard link to the specified file.
+ * @param from_path The full path to the original file (using / on all systems)
+ * @param to_path The full path to the new file (using / on all systems)
+ * @remark Both files must reside on the same device.
+ */
+APR_DECLARE(apr_status_t) apr_file_link(const char *from_path,
+ const char *to_path);
+
+/**
* Copy the specified file to another file.
* @param from_path The full path to the original file (using / on all systems)
* @param to_path The full path to the new file (using / on all systems)
diff -x '*.lo' -x '*.mk' -x 'config.*' -ur
../apr.20080417222010/test/testfilecopy.c ./test/testfilecopy.c
--- ../apr.20080417222010/test/testfilecopy.c 2008-04-17 21:01:23.000000000
-0400
+++ ./test/testfilecopy.c 2008-04-18 19:53:33.000000000 -0400
@@ -123,6 +123,23 @@
APR_ASSERT_SUCCESS(tc, "Couldn't remove copy file", rv);
}
+static void link_existing(abts_case *tc, void *data)
+{
+ apr_status_t rv;
+
+ rv = apr_file_link("data/file_datafile.txt", "data/file_datafile2.txt");
+ apr_file_remove("data/file_datafile2.txt", p);
+ ABTS_ASSERT(tc, "Couldn't create hardlink to file", rv == APR_SUCCESS);
+}
+
+static void link_nonexisting(abts_case *tc, void *data)
+{
+ apr_status_t rv;
+
+ rv = apr_file_link("data/does_not_exist.txt", "data/fake.txt");
+ ABTS_ASSERT(tc, "", rv != APR_SUCCESS);
+}
+
abts_suite *testfilecopy(abts_suite *suite)
{
suite = ADD_SUITE(suite)
@@ -133,6 +150,9 @@
abts_run_test(suite, append_nonexist, NULL);
abts_run_test(suite, append_exist, NULL);
+ abts_run_test(suite, link_existing, NULL);
+ abts_run_test(suite, link_nonexisting, NULL);
+
return suite;
}