Process process = Runtime.getRuntime().exec( new String[] { "ln", "-s", oldName, newname } );
process.waitFor();
process.destroy();The disadvantage of this method is the overhead for creating the new process. This can be a serious downgrade in performance if you have to execute this code frequently.
Here is an alternative solution that can vastly improve speed.
First you write a small program in C, say it symlinkcreator.c. This is the actual worker:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
int main()
{
char st[1024];
char oldpath[1024];
int count = 0;
while (fgets(st,sizeof(st),stdin) != NULL)
{
for (char *cp = st; *cp; cp++)
if (*cp == '\n' || *cp == '\r') *cp = '\0';
if (count++ % 2)
symlink(oldpath,st);
else
strcpy(oldpath,st);
}
}You can compile the program by running this command:
# gcc symlinkcreator.c -o symlinkcreator -std=c99This will give you the symlinkcreator executable file.
Then you going to need an elegant wrapper class that will call the C program:
import java.io.IOException;
import java.io.PrintWriter;
public class SymlinkCreator
{
private Process process;
private PrintWriter out;
public SymlinkCreator( String path ) throws IOException
{
process = Runtime.getRuntime().exec(path);
out = new PrintWriter(process.getOutputStream());
}
public void link( String oldpath, String newpath )
{
out.println(oldpath);
out.println(newpath);
out.flush();
}
public void terminate() throws InterruptedException
{
out.close();
process.waitFor();
process.destroy();
}
}Have done these, you can then easily create symbolic links from you code, like this:
// You only need one single SymlinkCreator object (just a single unix process is created)
SymlinkCreator symlinkCreator = new SymlinkCreator("/path/to/symlinkcreator");
...
// Create as many symbolic links as you want using the same process
symlinkCreator.link(oldName,newName);
...
// Terminate the symbolic creator process and release resources when done.
symlinkCreator.terminate();Downloads:
symlinkcreator.c
SymlinkCreator.java
Alternatively, you can use native methods to eliminate the hassle of inter-process communication between two separate processes.
First create a Symlink class that defines the signatures of the native mathod. This class will act as an interface to the actual C functions:
public class Symlink
{
public native static void create( String oldpath, String newpath );
}Then you will need to generate a header file for this class using the javah utility:
# javah -classpath /path/to/your/classes SymlinkThis will generate a header file that looks like this:
Symlink.h
#include <jni.h>
/* Header for class Symlink */
#ifndef _Included_Symlink
#define _Included_Symlink
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: Symlink
* Method: create
* Signature: (Ljava/lang/String;Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_Symlink_create
(JNIEnv *, jclass, jstring, jstring);
#ifdef __cplusplus
}
#endif
#endifThen you will have to write a small C file that will define the implemtation of the function:
Symlink.c
#include <unistd.h>
#include <jni.h>
#include "Symlink.h"
JNIEXPORT void JNICALL Java_Symlink_create
(JNIEnv *env, jclass obj, jstring oldpath, jstring newpath)
{
const char *nativeOldpath = (*env)→GetStringUTFChars(env, oldpath, 0);
const char *nativeNewpath = (*env)→GetStringUTFChars(env, newpath, 0);
symlink(nativeOldpath,nativeNewpath);
(*env)→ReleaseStringUTFChars(env, oldpath, nativeOldpath);
(*env)→ReleaseStringUTFChars(env, newpath, nativeNewpath);
}Then you have to compile the C file as a shared library:
# gcc -shared -o Symlink.so Symlink.c -I /path/to/jdk/include -I /path/to/jdk/include/linuxYou will have to load this shared library at the runtime of your java program.
Finally you can write a small test program to see that everything works:
public class TestSymlink
{
public static void main( String[] args )
{
System.load("/path/to/Symlink.so");
Symlink.create("/home/giannis/test1", "/home/giannis/test2");
}
}



