diff --git a/common/source/c/compile_linux_amd64.sh b/common/source/c/compile_linux_amd64.sh new file mode 100755 index 0000000000000000000000000000000000000000..daaeae5788ce2753a1e6bcb7533f09ca1f93f2e5 --- /dev/null +++ b/common/source/c/compile_linux_amd64.sh @@ -0,0 +1,3 @@ +#! /bin/bash + +gcc -shared -fPIC unixlink.c -o ../../../libraries/filelink/amd64-Linux/jlink.so diff --git a/common/source/c/compile_linux_i386.sh b/common/source/c/compile_linux_i386.sh new file mode 100755 index 0000000000000000000000000000000000000000..ed19e175b686bf6e8d1c91064c28de0eb12886df --- /dev/null +++ b/common/source/c/compile_linux_i386.sh @@ -0,0 +1,3 @@ +#! /bin/bash + +gcc -shared unixlink.c -I/usr/java/jdk1.5.0_13/include -I/usr/java/jdk1.5.0_13/include/linux -o ../../../libraries/filelink/i386-Linux/jlink.so diff --git a/common/source/c/compile_macosx.sh b/common/source/c/compile_macosx.sh new file mode 100755 index 0000000000000000000000000000000000000000..b8a4feb326ec798432f2689742375facadd75ea5 --- /dev/null +++ b/common/source/c/compile_macosx.sh @@ -0,0 +1,4 @@ +#! /bin/bash + +gcc -bundle unixlink.c -I/System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers -o "../../../libraries/filelink/i386-Mac OS X/jlink.so" + diff --git a/common/source/c/unixlink.c b/common/source/c/unixlink.c new file mode 100644 index 0000000000000000000000000000000000000000..bbb3c031ee64f51f4a76eff8afa32c6c595d577e --- /dev/null +++ b/common/source/c/unixlink.c @@ -0,0 +1,54 @@ +#include <unistd.h> +#include <errno.h> +#include <string.h> +#include <jni.h> + +JNIEXPORT jint JNICALL Java_ch_systemsx_cisd_common_utilities_FileLinkUtilities_hardlink + (JNIEnv *env, jclass clss, jstring filename, jstring linktarget) +{ + const char* pfilename; + const char* plinktarget; + jboolean isCopy; + int retval; + + pfilename = (char *)(*env)->GetStringUTFChars(env, filename, &isCopy); + plinktarget = (char *)(*env)->GetStringUTFChars(env, linktarget, &isCopy); + + retval = link(pfilename, plinktarget); + if (retval < 0) + { + retval = errno; + } + + (*env)->ReleaseStringUTFChars(env, filename, pfilename); + (*env)->ReleaseStringUTFChars(env, linktarget, plinktarget); + + return retval; +} + +JNIEXPORT jint JNICALL Java_ch_systemsx_cisd_common_utilities_FileLinkUtilities_symlink + (JNIEnv *env, jclass clss, jstring filename, jstring linktarget) +{ + const char* pfilename; + const char* plinktarget; + jboolean isCopy; + int retval; + + pfilename = (char *)(*env)->GetStringUTFChars(env, filename, &isCopy); + plinktarget = (char *)(*env)->GetStringUTFChars(env, linktarget, &isCopy); + + retval = symlink(pfilename, plinktarget); + if (retval < 0) { + retval = errno; + } + + (*env)->ReleaseStringUTFChars(env, filename, pfilename); + (*env)->ReleaseStringUTFChars(env, linktarget, plinktarget); + + return retval; +} + +JNIEXPORT jstring JNICALL Java_ch_systemsx_cisd_common_utilities_FileLinkUtilities_strerror(JNIEnv *env, jclass clss, jint errnum) +{ + return (*env)->NewStringUTF(env, strerror(errnum)); +} diff --git a/common/source/java/ch/systemsx/cisd/common/utilities/FileLinkUtilities.java b/common/source/java/ch/systemsx/cisd/common/utilities/FileLinkUtilities.java new file mode 100644 index 0000000000000000000000000000000000000000..de9f554cee33f039ddba27f87263fa93bd644e81 --- /dev/null +++ b/common/source/java/ch/systemsx/cisd/common/utilities/FileLinkUtilities.java @@ -0,0 +1,118 @@ +/* + * Copyright 2008 ETH Zuerich, CISD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.systemsx.cisd.common.utilities; + +import java.io.File; + +/** + * A utility class that provides access to hard link and symbolic link creation on Unix platforms. + * + * @author Bernd Rinn + */ +public class FileLinkUtilities +{ + + private static boolean operational = false; + + static + { + final String filename = + FileUtilities.tryCopyResourceToTempFile("/" + OSUtilities.getComputerPlatform() + + "/jlink.so", "jlink", ".so"); + + if (filename != null) + { + final File linkLib = new File(filename); + if (linkLib.exists() && linkLib.canRead() && linkLib.isFile()) + { + try + { + System.load(filename); + operational = true; + } catch (final Throwable err) + { + System.err.printf("Native Link library '%s' failed to load:\n", filename); + err.printStackTrace(); + } + } + } + } + + /** An exception that indicates that creating a link failed. */ + public static final class FileLinkException extends RuntimeException + { + private static final long serialVersionUID = 1L; + + private FileLinkException(String type, String source, String target, String errorMessage) + { + super(String.format("Creating %s link '%s' -> '%s': %s", type, source, target, + errorMessage)); + } + } + + // + // The wrappers for the native function calls. + // + + private static native int hardlink(String filename, String linktarget); + + private static native int symlink(String filename, String linktarget); + + private static native String strerror(int errnum); + + /** + * Returns <code>true</code>, if the native library has been loaded successfully and the link + * utilities are operational, <code>false</code> otherwise. + */ + public static final boolean isOperational() + { + return operational; + } + + /** + * Creates a hard link from <var>filename</var> to <var>linktarget</var>. + * + * @throws FileLinkException If the underlying system call fails, e.g. because <var>filename</var> + * does not exist or because <var>linktarget</var> already exists. + */ + public static final void createHardLink(String filename, String linktarget) + throws FileLinkException + { + final int result = hardlink(filename, linktarget); + if (result != 0) + { + throw new FileLinkException("hard", linktarget, filename, strerror(result)); + } + } + + /** + * Creates a symbolic link from <var>filename</var> to <var>linktarget</var>. + * + * @throws FileLinkException If the underlying system call fails, e.g. because <var>filename</var> + * does not exist or because <var>linktarget</var> already exists. + */ + public static final void createSymbolicLink(String filename, String linktarget) + throws FileLinkException + { + final int result = symlink(filename, linktarget); + if (result != 0) + { + throw new FileLinkException("symbolic", linktarget, filename, strerror(result)); + } + } + +}