You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by mt...@apache.org on 2009/04/21 08:39:32 UTC
svn commit: r767011 - in /commons/sandbox/runtime/trunk/src:
main/java/org/apache/commons/runtime/io/File.java
main/native/include/arch/windows/acr_arch.h main/native/os/unix/file.c
main/native/os/win32/file.c test/org/apache/commons/runtime/TestFile.java
Author: mturk
Date: Tue Apr 21 06:39:32 2009
New Revision: 767011
URL: http://svn.apache.org/viewvc?rev=767011&view=rev
Log:
Add support for hard links
Modified:
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/File.java
commons/sandbox/runtime/trunk/src/main/native/include/arch/windows/acr_arch.h
commons/sandbox/runtime/trunk/src/main/native/os/unix/file.c
commons/sandbox/runtime/trunk/src/main/native/os/win32/file.c
commons/sandbox/runtime/trunk/src/test/org/apache/commons/runtime/TestFile.java
Modified: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/File.java
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/File.java?rev=767011&r1=767010&r2=767011&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/File.java (original)
+++ commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/File.java Tue Apr 21 06:39:32 2009
@@ -36,9 +36,10 @@
private static native boolean mkslink0(String target, String link)
throws IOException, SecurityException,
UnsupportedOperationException;
+ private static native boolean mkhlink0(String target, String link)
+ throws IOException, SecurityException;
private static native String target0(String link)
- throws IOException, SecurityException,
- UnsupportedOperationException;
+ throws IOException, SecurityException;
// Catched FileType Enum integer value.
private int fileType = -1;
@@ -285,18 +286,75 @@
}
/**
+ * Creates a hard link named {@code link} which contains the string
+ * {@code target}.
+ * <p>
+ * This new name may be used exactly as the old one for any operation;
+ * both names refer to the same file (and so
+ * have the same permissions and ownership) and it is impossible to
+ * tell which name was the <em>original</em>.
+ * On some operating systems like
+ * {@code Microsoft Windows} this operation is only supported on the
+ * {@code NTFS} file system, and only for files, not directories.
+ * </p>
+ *
+ * @param target The abstract pathname of the existinf file.
+ * @param link The link name.
+ * @return {@code true} if hard link was created, false if it already
+ * exists.
+ * @throws IOException in case of error.
+ * @throws SecurityException if Write access to the directory containing
+ * {@code link} is denied, or one of the directories in the
+ * path prefix of {@code link} did not allow search permission.
+ */
+ public static boolean createHardLink(String target, String link)
+ throws IOException, SecurityException
+ {
+ return mkhlink0(target, link);
+ }
+
+ /**
+ * Creates a new abstract {@code File} hard link instance with
+ * the path {@code link} which contains the string of this {@code File}
+ * isnstance pathname.
+ * <p>
+ * This new name may be used exactly as the old one for any operation;
+ * both names refer to the same file (and so
+ * have the same permissions and ownership) and it is impossible to
+ * tell which name was the <em>original</em>.
+ * On some operating systems like
+ * {@code Microsoft Windows} this operation is only supported on the
+ * {@code NTFS} file system, and only for files, not directories.
+ * </p>
+ *
+ * @param link The link name.
+ * @return New {@code File} instance containing hard link to this
+ * file instance.
+ * @throws IOException in case of error.
+ * @throws SecurityException if Write access to the directory containing
+ * {@code link} is denied, or one of the directories in the
+ * path prefix of {@code link} did not allow search permission.
+ */
+ public File createHardLink(String link)
+ throws IOException, SecurityException
+ {
+ // False means EEXIST, so just consider it opened
+ // Check is made wather it points to the same target
+ mkhlink0(getPath(), link);
+ return new File(link, fileType);
+ }
+
+ /**
* Return target pathname of this abstract {@code File} instance.
*
* @return Pathname this {@code File} points to.
- * @throws IOException if this {@code File} is not symbolic link
+ * @throws IOException if this {@code File} is not symbolic or hard link
* or an I/O error occured.
* @throws SecurityException if search permission is denied for a
* component of this abstract {@code File} pathname prefix.
- * @throws UnsupportedOperationException if the operating system doesn't
- * support symbolic links.
*/
public String getTargetPath()
- throws IOException, SecurityException, UnsupportedOperationException
+ throws IOException, SecurityException
{
return target0(getPath());
}
@@ -306,15 +364,13 @@
* abstract {@code File} instance.
*
* @return New {@code File} instance this {@code File} points to.
- * @throws IOException if this {@code File} is not symbolic link
+ * @throws IOException if this {@code File} is not symbolic or hard link
* or an I/O error occured.
* @throws SecurityException if search permission is denied for a
* component of this abstract {@code File} pathname prefix.
- * @throws UnsupportedOperationException if the operating system doesn't
- * support symbolic links.
*/
public File getTargetFile()
- throws IOException, SecurityException, UnsupportedOperationException
+ throws IOException, SecurityException
{
return new File(getTargetPath());
}
Modified: commons/sandbox/runtime/trunk/src/main/native/include/arch/windows/acr_arch.h
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/include/arch/windows/acr_arch.h?rev=767011&r1=767010&r2=767011&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/include/arch/windows/acr_arch.h (original)
+++ commons/sandbox/runtime/trunk/src/main/native/include/arch/windows/acr_arch.h Tue Apr 21 06:39:32 2009
@@ -96,8 +96,11 @@
#pragma warning( default : 4201 )
#endif
+#ifndef IO_REPARSE_TAG_MOUNT_POINT
+#define IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L)
+#endif
#ifndef IO_REPARSE_TAG_SYMLINK
-#define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
+#define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
#endif
/*
Modified: commons/sandbox/runtime/trunk/src/main/native/os/unix/file.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/unix/file.c?rev=767011&r1=767010&r2=767011&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/unix/file.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/os/unix/file.c Tue Apr 21 06:39:32 2009
@@ -131,10 +131,38 @@
WITH_CSTR(target) {
WITH_CSTR(lnkname) {
if (symlink(J2S(target), J2S(lnkname))) {
- if (errno == EACCES)
+ int err = ACR_GET_OS_ERROR();
+ if (ACR_STATUS_IS_EACCES(err)) {
ACR_ThrowException(_E, THROW_NMARK, ACR_EX_ESECURITY, 0);
- else if (errno != EEXIST) {
- ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EIO, errno);
+ }
+ else if (!ACR_STATUS_IS_EEXIST(err)) {
+ ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EIO, err);
+ }
+ }
+ else
+ rc = JNI_TRUE;
+ } END_WITH_CSTR(lnkname);
+ } END_WITH_CSTR(target);
+
+ return rc;
+}
+
+ACR_JNI_EXPORT_DECLARE(jboolean, io_File, mkhlink0)(ACR_JNISTDARGS,
+ jstring target,
+ jstring lnkname)
+{
+ jboolean rc = JNI_FALSE;
+
+ UNREFERENCED_O;
+ WITH_CSTR(target) {
+ WITH_CSTR(lnkname) {
+ if (link(J2S(target), J2S(lnkname))) {
+ int err = ACR_GET_OS_ERROR();
+ if (ACR_STATUS_IS_EACCES(err)) {
+ ACR_ThrowException(_E, THROW_NMARK, ACR_EX_ESECURITY, 0);
+ }
+ else if (!ACR_STATUS_IS_EEXIST(err)) {
+ ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EIO, err);
}
}
else
Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/file.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/file.c?rev=767011&r1=767010&r2=767011&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/win32/file.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/os/win32/file.c Tue Apr 21 06:39:32 2009
@@ -116,12 +116,40 @@
WITH_WSTR(target) {
WITH_WSTR(lnkname) {
DWORD dwFlags = 0;
- if (J2W(target)[wcslen(J2W(target))] == L'\\')
+ size_t tlen = wcslen(J2W(target));
+ if (tlen > 0 && J2W(target)[tlen - 1] == L'\\')
dwFlags = SYMBOLIC_LINK_FLAG_DIRECTORORY;
if (!CreateSymbolicLinkW(J2W(lnkname), J2W(target), dwFlags)) {
int err = ACR_GET_OS_ERROR();
- if (ACR_STATUS_IS_EACCES(err))
+ if (ACR_STATUS_IS_EACCES(err)) {
ACR_ThrowException(_E, THROW_NMARK, ACR_EX_ESECURITY, 0);
+ }
+ else if (!ACR_STATUS_IS_EEXIST(err)) {
+ ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EIO, err);
+ }
+ }
+ else
+ rc = JNI_TRUE;
+ } END_WITH_WSTR(lnkname);
+ } END_WITH_WSTR(target);
+
+ return rc;
+}
+
+ACR_JNI_EXPORT_DECLARE(jboolean, io_File, mkhlink0)(ACR_JNISTDARGS,
+ jstring target,
+ jstring lnkname)
+{
+ jboolean rc = JNI_FALSE;
+
+ UNREFERENCED_O;
+ WITH_WSTR(target) {
+ WITH_WSTR(lnkname) {
+ if (!CreateHardLinkW(J2W(lnkname), J2W(target), NULL)) {
+ int err = ACR_GET_OS_ERROR();
+ if (ACR_STATUS_IS_EACCES(err)) {
+ ACR_ThrowException(_E, THROW_NMARK, ACR_EX_ESECURITY, 0);
+ }
else if (!ACR_STATUS_IS_EEXIST(err)) {
ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EIO, err);
}
@@ -140,10 +168,6 @@
jstring rv = NULL;
UNREFERENCED_O;
- if (!ACR_HAVE_LATE_DLL_FUNC(CreateSymbolicLinkW)) {
- ACR_ThrowException(_E, THROW_NMARK, ACR_EX_ENOTIMPL, 0);
- return JNI_FALSE;
- }
WITH_WSTR(lnkname) {
void *buf = ACR_Calloc(_E, THROW_FMARK, MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
if (buf) {
@@ -153,10 +177,11 @@
NULL,
OPEN_EXISTING,
FILE_FLAG_OPEN_REPARSE_POINT,
- NULL);
+ NULL);
if (sh != INVALID_HANDLE_VALUE) {
DWORD dl;
PREPARSE_DATA_BUFFER repb;
+ char *pb;
DeviceIoControl(sh,
FSCTL_GET_REPARSE_POINT,
NULL,
@@ -166,10 +191,17 @@
&dl,
NULL);
repb = (PREPARSE_DATA_BUFFER)buf;
- if (repb->ReparseTag == IO_REPARSE_TAG_SYMLINK) {
- char *pb = (char *)repb->SymbolicLinkReparseBuffer.PathBuffer;
- rv = (*_E)->NewString(_E, (const jchar *)(pb + repb->SymbolicLinkReparseBuffer.PrintNameOffset),
- repb->SymbolicLinkReparseBuffer.PrintNameLength >> 1);
+ switch (repb->ReparseTag) {
+ case IO_REPARSE_TAG_MOUNT_POINT:
+ char *pb = (char *)repb->MountPointReparseBuffer.PathBuffer;
+ rv = (*_E)->NewString(_E, (const jchar *)(pb + repb->MountPointReparseBuffer.SubstituteNameOffset),
+ repb->MountPointReparseBuffer.SubstituteNameLength / sizeof(WCHAR));
+ break;
+ case IO_REPARSE_TAG_SYMLINK:
+ pb = (char *)repb->SymbolicLinkReparseBuffer.PathBuffer;
+ rv = (*_E)->NewString(_E, (const jchar *)(pb + repb->SymbolicLinkReparseBuffer.SubstituteNameOffset),
+ repb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(WCHAR));
+ break;
}
CloseHandle(sh);
}
Modified: commons/sandbox/runtime/trunk/src/test/org/apache/commons/runtime/TestFile.java
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/test/org/apache/commons/runtime/TestFile.java?rev=767011&r1=767010&r2=767011&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/test/org/apache/commons/runtime/TestFile.java (original)
+++ commons/sandbox/runtime/trunk/src/test/org/apache/commons/runtime/TestFile.java Tue Apr 21 06:39:32 2009
@@ -145,4 +145,22 @@
}
+ public void testMakeHardlink()
+ throws Exception
+ {
+ try {
+ boolean rc;
+ File target = new File("hfoo");
+ rc = target.createNewFile();
+ File hrdlnk = target.createHardLink("hbar");
+ FileType t = hrdlnk.getFileType();
+ assertEquals("Name", "hbar", hrdlnk.getPath());
+ assertEquals("Type", FileType.REG, t);
+ hrdlnk.delete();
+ target.delete();
+ } catch (UnsupportedOperationException u) {
+ // fail("Unsupported Operating system");
+ }
+ }
+
}