[med-svn] [Git][med-team/libsis-base-java][upstream] New upstream version 18.09~pre1+git20180827.fe4953e+dfsg
Andreas Tille
gitlab at salsa.debian.org
Wed Sep 26 08:50:30 BST 2018
Andreas Tille pushed to branch upstream at Debian Med / libsis-base-java
Commits:
e42bd7e6 by Andreas Tille at 2018-09-26T07:08:47Z
New upstream version 18.09~pre1+git20180827.fe4953e+dfsg
- - - - -
16 changed files:
- source/c/compile_windows_x64.mak → source/c/Makefile_Win64.mak
- source/c/compile_linux_amd64.sh
- source/c/compile_linux_arm.sh
- − source/c/compile_linux_i386.sh
- − source/c/compile_macosx_i386.sh
- source/c/compile_macosx_x86_64.sh
- − source/c/compile_solaris_amd64.sh
- − source/c/compile_solaris_sparc.sh
- − source/c/compile_solaris_sparcv9.sh
- − source/c/compile_solaris_x86.sh
- − source/c/compile_windows_i386.mak
- source/c/unix.c
- source/java/ch/systemsx/cisd/base/unix/Unix.java
- sourceTest/java/ch/systemsx/cisd/base/AllTests.java
- + sourceTest/java/ch/systemsx/cisd/base/unix/UnixRootTests.java
- sourceTest/java/ch/systemsx/cisd/base/unix/UnixTests.java
Changes:
=====================================
source/c/compile_windows_x64.mak → source/c/Makefile_Win64.mak
=====================================
@@ -6,13 +6,13 @@
#============================================================================
# Visual C++ directory, for example
-VCPPDIR=C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC
+VCPPDIR=C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC
# Directory where JDK is installed (We require JDK 1.6)
-JAVADIR=C:\Program Files\Java\jdk1.6.0_37
+JAVADIR=C:\Program Files\Java\jdk1.8.0_181
# Common parent directory
-PARENTDIR=C:\nativeData
+PARENTDIR=F:\base
# Directory of the HDF Java Products, for example
SRCDIR=$(PARENTDIR)\c\
=====================================
source/c/compile_linux_amd64.sh
=====================================
@@ -1,6 +1,7 @@
#! /bin/bash
-gcc -shared -O3 -fPIC unix.c -I/usr/java/jdk1.6.0/include -I/usr/java/jdk1.6.0/include/linux -o libunix.so
+JAVA_INCLUDE=/usr/lib/jvm/java-1.8.0/include
+gcc -shared -O3 -fPIC unix.c -I$JAVA_INCLUDE -I$JAVA_INCLUDE/linux -o libunix.so
# MACHINE_BYTE_ORDER=1 corresponds to 'little endian'
-gcc -shared -O3 -fPIC -DMACHINE_BYTE_ORDER=1 copy*.c -I/usr/java/jdk1.6.0/include -I/usr/java/jdk1.6.0/include/linux -o libnativedata.so
+gcc -shared -O3 -fPIC -DMACHINE_BYTE_ORDER=1 copy*.c -I$JAVA_INCLUDE -I$JAVA_INCLUDE/linux -o libnativedata.so
=====================================
source/c/compile_linux_arm.sh
=====================================
@@ -1,6 +1,6 @@
#! /bin/bash
-gcc -shared -O3 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE -D_LARGEFILE_SOURCE -I/usr/java/jdk1.7.0/include -I/usr/java/jdk1.7.0/include/linux unix.c -o libunix.so
+gcc -shared -O3 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE -D_LARGEFILE_SOURCE -I/usr/java/jdk1.8.0/include -I/usr/java/jdk1.8.0/include/linux unix.c -o libunix.so
# MACHINE_BYTE_ORDER=1 corresponds to 'little endian'
-gcc -shared -O3 -fPIC -DMACHINE_BYTE_ORDER=1 copy*.c -I/usr/java/jdk1.7.0/include -I/usr/java/jdk1.7.0/include/linux -o libnativedata.so
+gcc -shared -O3 -fPIC -DMACHINE_BYTE_ORDER=1 copy*.c -I/usr/java/jdk1.8.0/include -I/usr/java/jdk1.8.0/include/linux -o libnativedata.so
=====================================
source/c/compile_linux_i386.sh deleted
=====================================
@@ -1,6 +0,0 @@
-#! /bin/bash
-
-gcc -m32 -shared -O3 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE -D_LARGEFILE_SOURCE -I/usr/java/jdk1.6.0/include -I/usr/java/jdk1.6.0/include/linux unix.c -o libunix.so
-
-# MACHINE_BYTE_ORDER=1 corresponds to 'little endian'
-gcc -m32 -shared -O3 -fPIC -DMACHINE_BYTE_ORDER=1 copy*.c -I/usr/java/jdk1.6.0/include -I/usr/java/jdk1.6.0/include/linux -o libnativedata.so
=====================================
source/c/compile_macosx_i386.sh deleted
=====================================
@@ -1,6 +0,0 @@
-#! /bin/bash
-
-gcc -m32 -mmacosx-version-min=10.6 -bundle -O3 unix.c -I/System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers -o libunix.jnilib
-
-# MACHINE_BYTE_ORDER=1 corresponds to 'little endian'
-gcc -m32 -mmacosx-version-min=10.6 -bundle -O3 -DMACHINE_BYTE_ORDER=1 copy*.c -I/System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers -o libnativedata.jnilib
=====================================
source/c/compile_macosx_x86_64.sh
=====================================
@@ -1,6 +1,6 @@
#! /bin/bash
-gcc -m64 -mmacosx-version-min=10.6 -dynamiclib -D_DARWIN_USE_64_BIT_INODE -O3 unix.c -I/System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers -o libunix.jnilib
+gcc -m64 -mmacosx-version-min=10.11 -dynamiclib -D_DARWIN_USE_64_BIT_INODE -O3 unix.c -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers -o libunix.jnilib
# MACHINE_BYTE_ORDER=1 corresponds to 'little endian'
-gcc -m64 -mmacosx-version-min=10.6 -dynamiclib -O3 -DMACHINE_BYTE_ORDER=1 copy*.c -I/System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers -o libnativedata.jnilib
+gcc -m64 -mmacosx-version-min=10.11 -dynamiclib -O3 -DMACHINE_BYTE_ORDER=1 copy*.c -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers -o libnativedata.jnilib
=====================================
source/c/compile_solaris_amd64.sh deleted
=====================================
@@ -1,6 +0,0 @@
-#! /bin/bash
-
-cc -G -KPIC -fast -m64 -I/usr/java/include -I/usr/java/include/solaris unix.c -o libunix.so
-
-# MACHINE_BYTE_ORDER=1 corresponds to 'little endian'
-cc -G -KPIC -fast -m64 -DMACHINE_BYTE_ORDER=1 copy*.c -I/usr/java/include -I/usr/java/include/solaris -o libnativedata.so
=====================================
source/c/compile_solaris_sparc.sh deleted
=====================================
@@ -1,6 +0,0 @@
-#! /bin/bash
-
-cc -G -KPIC -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE -D_LARGEFILE_SOURCE -I/usr/java/include -I/usr/java/include/solaris unix.c -o libunix.so
-
-# MACHINE_BYTE_ORDER=2 corresponds to 'big endian'
-cc -G -KPIC -DMACHINE_BYTE_ORDER=2 copy*.c -I/usr/java/include -I/usr/java/include/solaris -o libnativedata.so
=====================================
source/c/compile_solaris_sparcv9.sh deleted
=====================================
@@ -1,6 +0,0 @@
-#! /bin/bash
-
-cc -G -KPIC -fast -m64 -I/usr/java/include -I/usr/java/include/solaris unix.c -o libunix.so
-
-# MACHINE_BYTE_ORDER=2 corresponds to 'big endian'
-cc -G -KPIC -fast -m64 -DMACHINE_BYTE_ORDER=2 copy*.c -I/usr/java/include -I/usr/java/include/solaris -o libnativedata.so
=====================================
source/c/compile_solaris_x86.sh deleted
=====================================
@@ -1,6 +0,0 @@
-#! /bin/bash
-
-cc -G -KPIC -fast -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE -D_LARGEFILE_SOURCE -I/usr/java/include -I/usr/java/include/solaris unix.c -o libunix.so
-
-# MACHINE_BYTE_ORDER=1 corresponds to 'little endian'
-cc -G -KPIC -fast -DMACHINE_BYTE_ORDER=1 copy*.c -I/usr/java/include -I/usr/java/include/solaris -o libnativedata.so
=====================================
source/c/compile_windows_i386.mak deleted
=====================================
@@ -1,181 +0,0 @@
-#============================================================================
-#
-# Makefile to compile the 'nativedata' native library
-# Usage: nmake /f compile_windows_i386.mak
-#
-#============================================================================
-
-# Visual C++ directory, for example
-VCPPDIR=C:\Program Files\Microsoft Visual Studio 9.0\VC
-
-# Directory where JDK is installed (We require JDK 1.6)
-JAVADIR=C:\Program Files\Java\jdk1.6.0_37
-
-# Common parent directory
-PARENTDIR=C:\nativeData
-
-# Directory of the HDF Java Products, for example
-SRCDIR=$(PARENTDIR)\c\
-
-#===========================================================================
-# Do not make any change below this line unless you know what you do
-#===========================================================================
-PATH=$(PATH);$(VCPPDIR)\BIN
-SRCDIR=$(SRCDIR)
-
-VALID_PATH_SET=YES
-#-------------------------------------------------------
-# Test if all path is valid
-
-!IF EXISTS("$(VCPPDIR)")
-!ELSE
-!MESSAGE ERROR: Visual C++ directory $(VCPPDIR) does not exist
-VALID_PATH_SET=NO
-!ENDIF
-
-!IF EXISTS("$(JAVADIR)")
-!ELSE
-!MESSAGE ERROR: JDK directory $(JAVADIR) does not exist
-VALID_PATH_SET=NO
-!ENDIF
-
-!IF EXISTS("$(SRCDIR)")
-!ELSE
-!MESSAGE ERROR: C source directory $(SRCDIR) does not exist
-VALID_PATH_SET=NO
-!ENDIF
-
-#-------------------------------------------------------
-
-
-!IF "$(VALID_PATH_SET)" == "YES"
-
-!IF "$(OS)" == "Windows_NT"
-NULL=
-!ELSE
-NULL=nul
-!ENDIF
-
-INTDIR=.\nativedata\Release
-OUTDIR=$(SRCDIR)\lib\win
-
-INCLUDES = \
- "$(JAVADIR)\include\jni.h" \
- "$(JAVADIR)\include\win32\jni_md.h"
-
-
-ALL : "$(OUTDIR)\nativedata.dll"
-
-"$(INTDIR)" :
- if not exist "$(INTDIR)/$(NULL)" mkdir "$(INTDIR)"
-
-"$(OUTDIR)" :
- if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
-
-CPP=cl.exe
-CPP_PROJ=/nologo /W3 /EHsc /O2 /I "$(JAVADIR)\include" /I "$(JAVADIR)\include\win32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "MACHINE_BYTE_ORDER=1" /Fp"$(INTDIR)\nativedata.pch" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
-
-.c{$(INTDIR)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(INTDIR)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(INTDIR)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.c{$(INTDIR)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(INTDIR)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(INTDIR)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-MTL=midl.exe
-MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
-RSC=rc.exe
-BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(INTDIR)\nativedata.bsc"
-BSC32_SBRS= \
-
-LINK=link.exe
-LINK_FLAGS=/nologo /dll /nodefaultlib:msvcrt /incremental:no /pdb:"$(INTDIR)\nativedata.pdb" /machine:I386 /out:"$(OUTDIR)\nativedata.dll" /implib:"$(INTDIR)\nativedata.lib"
-LINK_OBJS= \
- "$(INTDIR)\copyCommon.obj" \
- "$(INTDIR)\copyByteDouble.obj" \
- "$(INTDIR)\copyByteFloat.obj" \
- "$(INTDIR)\copyByteInt.obj" \
- "$(INTDIR)\copyByteLong.obj" \
- "$(INTDIR)\copyByteShort.obj" \
- "$(INTDIR)\copyByteChar.obj"
-
-"$(OUTDIR)\nativedata.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK_OBJS)
- $(LINK) @<<
- $(LINK_FLAGS) $(LINK_OBJS)
-<<
-
-
-SOURCE=$(SRCDIR)\copyCommon.c
-
-"$(INTDIR)\copyCommon.obj" : $(SOURCE) $(INCLUDES) "$(INTDIR)"
- $(CPP) $(CPP_PROJ) $(SOURCE)
-
-
-SOURCE=$(SRCDIR)\copyByteDouble.c
-
-"$(INTDIR)\copyByteDouble.obj" : $(SOURCE) $(INCLUDES) "$(INTDIR)"
- $(CPP) $(CPP_PROJ) $(SOURCE)
-
-SOURCE=$(SRCDIR)\copyByteFloat.c
-
-"$(INTDIR)\copyByteFloat.obj" : $(SOURCE) $(INCLUDES) "$(INTDIR)"
- $(CPP) $(CPP_PROJ) $(SOURCE)
-
-SOURCE=$(SRCDIR)\copyByteInt.c
-
-"$(INTDIR)\copyByteInt.obj" : $(SOURCE) $(INCLUDES) "$(INTDIR)"
- $(CPP) $(CPP_PROJ) $(SOURCE)
-
-SOURCE=$(SRCDIR)\copyByteLong.c
-
-"$(INTDIR)\copyByteLong.obj" : $(SOURCE) $(INCLUDES) "$(INTDIR)"
- $(CPP) $(CPP_PROJ) $(SOURCE)
-
-SOURCE=$(SRCDIR)\copyByteShort.c
-
-"$(INTDIR)\copyByteShort.obj" : $(SOURCE) $(INCLUDES) "$(INTDIR)"
- $(CPP) $(CPP_PROJ) $(SOURCE)
-
-SOURCE=$(SRCDIR)\copyByteChar.c
-
-"$(INTDIR)\copyByteChar.obj" : $(SOURCE) $(INCLUDES) "$(INTDIR)"
- $(CPP) $(CPP_PROJ) $(SOURCE)
-
-CLEAN :
- - at erase "$(INTDIR)\copyCommon.obj"
- - at erase "$(INTDIR)\copyByteDouble.obj"
- - at erase "$(INTDIR)\copyByteFloat.obj"
- - at erase "$(INTDIR)\copyByteInt.obj"
- - at erase "$(INTDIR)\copyByteLong.obj"
- - at erase "$(INTDIR)\copyByteShort.obj"
- - at erase "$(INTDIR)\copyByteChar.obj"
- - at erase "$(INTDIR)\vc90.idb"
- - at erase "$(INTDIR)\nativedata.exp"
- - at erase "$(INTDIR)\nativedata.lib"
- - at erase "$(OUTDIR)\nativedata.dll"
-
-!ENDIF
=====================================
source/c/unix.c
=====================================
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#include <time.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
@@ -20,6 +21,7 @@
#include <grp.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/time.h>
#include <jni.h>
/* Types of links. Keep in sync with Java enum. */
@@ -28,6 +30,17 @@
#define SYMLINK 2
#define OTHER 3
+/* Field name for nano second precission of file stat times. */
+#ifdef __MACH__
+#define ST_ATIME_NANO st_atimespec.tv_nsec
+#define ST_MTIME_NANO st_mtimespec.tv_nsec
+#define ST_CTIME_NANO st_ctimespec.tv_nsec
+#else
+#define ST_ATIME_NANO st_atim.tv_nsec
+#define ST_MTIME_NANO st_mtim.tv_nsec
+#define ST_CTIME_NANO st_ctim.tv_nsec
+#endif
+
#ifndef __STAT
#define __STAT stat
#endif
@@ -44,6 +57,82 @@ jclass groupClass;
jmethodID groupConstructorID;
jclass statClass;
jmethodID statConstructorID;
+jboolean statConstructorHasNanos;
+
+/*
+ * Error and Exception Handling
+ */
+
+#define THROWEXCEPTION(className,args) { \
+ jclass jc; \
+ jmethodID jm; \
+ jobject ex; \
+ jc = (*env)->FindClass(env, (className)); \
+ if (jc == NULL) { \
+ return JNI_FALSE; \
+ } \
+ jm = (*env)->GetMethodID(env, jc, "<init>", "(Ljava/lang/String;)V"); \
+ if (jm == NULL) { \
+ printf("THROWEXCEPTION FATAL ERROR: GetMethodID failed\n"); \
+ return JNI_FALSE; \
+ } \
+ ex = (*env)->NewObjectA (env, jc, jm, (jvalue*)(args)); \
+ if (ex == NULL) { \
+ printf("THROWEXCEPTION FATAL ERROR: %s: Creation failed\n", (className)); \
+ return JNI_FALSE; \
+ } \
+ if ((*env)->Throw(env, (jthrowable)ex) < 0) { \
+ printf("THROWEXCEPTION FATAL ERROR: %s: Throw failed\n", (className)); \
+ return JNI_FALSE; \
+ } \
+ return JNI_TRUE; \
+}
+
+/*
+ * Routine to raise particular Java exceptions from C
+ */
+static jboolean
+jni_error_class
+ (JNIEnv *env, const char *message, const char *className)
+{
+ char *args[2];
+ jstring str = (*env)->NewStringUTF(env, message);
+ args[0] = (char *)str;
+ args[1] = 0;
+
+ THROWEXCEPTION(className, args);
+} /* end jni_error_class() */
+
+/*
+ * A NULL argument in an HDF5 call
+ * Create and throw an 'NullPointerException'
+ *
+ * Note: This routine never returns from the 'throw',
+ * and the Java native method immediately raises the
+ * exception.
+ */
+jboolean null_pointer_exception(JNIEnv *env, const char *functName)
+{
+ return jni_error_class(env, functName, "java/lang/NullPointerException");
+} /* end null_pointer_exception() */
+
+/*
+ * A fatal error in a JNI call
+ * Create and throw an 'InternalError'
+ *
+ * Note: This routine never returns from the 'throw',
+ * and the Java native method immediately raises the
+ * exception.
+ */
+jboolean internal_error(JNIEnv *env, const char *functName)
+{
+ return jni_error_class(env, functName, "java/lang/InternalError");
+} /* end iternal_error() */
+
+
+/*
+ * End Error and Exception Handling
+ */
JNIEXPORT jint JNICALL Java_ch_systemsx_cisd_base_unix_Unix_init
(JNIEnv *env, jclass clss)
@@ -82,11 +171,18 @@ JNIEXPORT jint JNICALL Java_ch_systemsx_cisd_base_unix_Unix_init
return -1;
}
statClass = (*env)->NewGlobalRef(env, statClass);
- statConstructorID = (*env)->GetMethodID(env, statClass, "<init>", "(JJSBIIIJJJJJI)V");
- if (groupConstructorID == NULL) /* Really shouldn't happen, will throw NoSuchMethodError. */
- {
- return -1;
- }
+ statConstructorHasNanos = JNI_TRUE;
+ statConstructorID = (*env)->GetMethodID(env, statClass, "<init>", "(JJSBIIIJJJJJJJJI)V");
+ if (statConstructorID == NULL) /* We have an old Java class without the "microsecond constructor". */
+ {
+ (*env)->ExceptionClear(env);
+ statConstructorHasNanos = JNI_FALSE;
+ statConstructorID = (*env)->GetMethodID(env, statClass, "<init>", "(JJSBIIIJJJJJI)V");
+ if (statConstructorID == NULL) /* Really shouldn't happen, will throw NoSuchMethodError. */
+ {
+ return -1;
+ }
+ }
return 0;
}
@@ -165,10 +261,20 @@ jobject call_stat(JNIEnv *env, jclass clss, jstring filename, stat_func_ptr stat
{
type = OTHER;
}
- result = (*env)->NewObject(env, statClass, statConstructorID, (jlong) s.st_dev, (jlong) s.st_ino,
- (jshort) (s.st_mode & 07777), (jbyte) type, (jint) s.st_nlink,
- (jint) s.st_uid, (jint) s.st_gid, (jlong) s.st_atime, (jlong) s.st_mtime,
- (jlong) s.st_ctime, (jlong) s.st_size, (jlong) s.st_blocks, (jint) s.st_blksize);
+ if (statConstructorHasNanos)
+ {
+ result = (*env)->NewObject(env, statClass, statConstructorID, (jlong) s.st_dev, (jlong) s.st_ino,
+ (jshort) (s.st_mode & 07777), (jbyte) type, (jint) s.st_nlink,
+ (jint) s.st_uid, (jint) s.st_gid, (jlong) s.st_atime, (jlong) s.ST_ATIME_NANO,
+ (jlong) s.st_mtime, (jlong) s.ST_MTIME_NANO, (jlong) s.st_ctime, (jlong) s.ST_CTIME_NANO,
+ (jlong) s.st_size, (jlong) s.st_blocks, (jint) s.st_blksize);
+ } else
+ {
+ result = (*env)->NewObject(env, statClass, statConstructorID, (jlong) s.st_dev, (jlong) s.st_ino,
+ (jshort) (s.st_mode & 07777), (jbyte) type, (jint) s.st_nlink,
+ (jint) s.st_uid, (jint) s.st_gid, (jlong) s.st_atime, (jlong) s.st_mtime,
+ (jlong) s.st_ctime, (jlong) s.st_size, (jlong) s.st_blocks, (jint) s.st_blksize);
+ }
return result;
}
}
@@ -236,6 +342,23 @@ JNIEXPORT jint JNICALL Java_ch_systemsx_cisd_base_unix_Unix_chown(JNIEnv *env, j
}
}
+JNIEXPORT jint JNICALL Java_ch_systemsx_cisd_base_unix_Unix_lchown(JNIEnv *env, jclass clss, jstring linkname, jint uid, jint gid)
+{
+ const char* plinkname;
+ int retval;
+
+ plinkname = (char *)(*env)->GetStringUTFChars(env, linkname, NULL);
+ retval = lchown(plinkname, uid, gid);
+ (*env)->ReleaseStringUTFChars(env, linkname, plinkname);
+ if (retval < 0)
+ {
+ return -errno;
+ } else
+ {
+ return 0;
+ }
+}
+
JNIEXPORT jstring JNICALL Java_ch_systemsx_cisd_base_unix_Unix_getuser(JNIEnv *env, jclass clss, jint uid)
{
struct passwd *pw;
@@ -444,3 +567,133 @@ JNIEXPORT jstring JNICALL Java_ch_systemsx_cisd_base_unix_Unix_strerror__(JNIEnv
{
return (*env)->NewStringUTF(env, strerror(errno));
}
+
+JNIEXPORT jint JNICALL Java_ch_systemsx_cisd_base_unix_Unix_lutimes
+ (JNIEnv *env, jclass clss, jstring filename, jlong accessTimeSecs, jlong accessTimeMicroSecs, jlong modificationTimeSecs, jlong modificationTimeMicroSecs)
+{
+ const char* pfilename;
+ struct timeval times[2];
+ int retval;
+
+ pfilename = (char *)(*env)->GetStringUTFChars(env, filename, NULL);
+ times[0].tv_sec = accessTimeSecs;
+ times[0].tv_usec = accessTimeMicroSecs;
+ times[1].tv_sec = modificationTimeSecs;
+ times[1].tv_usec = modificationTimeMicroSecs;
+
+ retval = lutimes(pfilename, times);
+ if (retval < 0)
+ {
+ retval = -errno;
+ }
+
+ (*env)->ReleaseStringUTFChars(env, filename, pfilename);
+
+ return retval;
+}
+
+JNIEXPORT jint JNICALL Java_ch_systemsx_cisd_base_unix_Unix_utimes
+ (JNIEnv *env, jclass clss, jstring filename, jlong accessTimeSecs, jlong accessTimeMicroSecs, jlong modificationTimeSecs, jlong modificationTimeMicroSecs)
+{
+ const char* pfilename;
+ struct timeval times[2];
+ int retval;
+
+ pfilename = (char *)(*env)->GetStringUTFChars(env, filename, NULL);
+ times[0].tv_sec = accessTimeSecs;
+ times[0].tv_usec = accessTimeMicroSecs;
+ times[1].tv_sec = modificationTimeSecs;
+ times[1].tv_usec = modificationTimeMicroSecs;
+
+ retval = utimes(pfilename, times);
+ if (retval < 0)
+ {
+ retval = -errno;
+ }
+
+ (*env)->ReleaseStringUTFChars(env, filename, pfilename);
+
+ return retval;
+}
+
+JNIEXPORT jint JNICALL Java_ch_systemsx_cisd_base_unix_Unix_clock_1gettime
+ (JNIEnv *env, jclass clss, jlongArray time)
+{
+ struct timespec spec;
+ jlong *timeP;
+ jboolean isCopy;
+ int retval;
+
+ if (time == NULL)
+ {
+ null_pointer_exception(env, "clock_gettime: time is NULL");
+ } /* end if */
+ timeP = (jlong*)(*env)->GetPrimitiveArrayCritical(env, time, &isCopy);
+ if (timeP == NULL)
+ {
+ internal_error(env, "clock_gettime: time not pinned");
+ } /* end if */
+
+
+ retval = clock_gettime(CLOCK_REALTIME, &spec);
+ if (retval < 0)
+ {
+ retval = -errno;
+ } else
+ {
+ timeP[0] = spec.tv_sec;
+ timeP[1] = spec.tv_nsec;
+ }
+
+ (*env)->ReleasePrimitiveArrayCritical(env, time, timeP, 0);
+
+ return retval;
+}
+
+int clock_gettime2(int clk_id, struct timespec* t) {
+ struct timeval now;
+
+ int rv = gettimeofday(&now, NULL);
+ if (rv)
+ {
+ return rv;
+ }
+ t->tv_sec = now.tv_sec;
+ t->tv_nsec = now.tv_usec * 1000;
+
+ return 0;
+}
+
+JNIEXPORT jint JNICALL Java_ch_systemsx_cisd_base_unix_Unix_clock_1gettime2
+ (JNIEnv *env, jclass clss, jlongArray time)
+{
+ struct timespec spec;
+ jlong *timeP;
+ jboolean isCopy;
+ int retval;
+
+ if (time == NULL)
+ {
+ null_pointer_exception(env, "clock_gettime: time is NULL");
+ } /* end if */
+ timeP = (jlong*)(*env)->GetPrimitiveArrayCritical(env, time, &isCopy);
+ if (timeP == NULL)
+ {
+ internal_error(env, "clock_gettime: time not pinned");
+ } /* end if */
+
+
+ retval = clock_gettime2(CLOCK_REALTIME, &spec);
+ if (retval < 0)
+ {
+ retval = -errno;
+ } else
+ {
+ timeP[0] = spec.tv_sec;
+ timeP[1] = spec.tv_nsec;
+ }
+
+ (*env)->ReleasePrimitiveArrayCritical(env, time, timeP, 0);
+
+ return retval;
+}
=====================================
source/java/ch/systemsx/cisd/base/unix/Unix.java
=====================================
@@ -25,26 +25,45 @@ import ch.systemsx.cisd.base.exceptions.IOExceptionUnchecked;
import ch.systemsx.cisd.base.utilities.NativeLibraryUtilities;
/**
- * A utility class that provides access to common Unix system calls. Obviously, this will only work
- * on Unix platforms and it requires a native library to be loaded.
+ * A utility class that provides access to common Unix system calls. Obviously, this will only work on Unix platforms and it requires a native library
+ * to be loaded.
* <p>
- * <i>Check with {@link #isOperational()} if this class is operational and only call the other
- * methods if <code>Unix.isOperational() == true</code>.</i>
+ * <i>Check with {@link #isOperational()} if this class is operational and only call the other methods if
+ * <code>Unix.isOperational() == true</code>.</i>
*
* @author Bernd Rinn
*/
public final class Unix
{
+ /**
+ * Method how processes are detected on this host.
+ *
+ */
private enum ProcessDetection
{
- PROCFS, PS, NONE
+ /**
+ * Process detection via <code>procfs</code> (Linux only).
+ */
+ PROCFS,
+
+ /**
+ * Process detection via the command line tool <code>ps</code>.
+ */
+ PS,
+
+ /**
+ * No working process detection found.
+ */
+ NONE
}
private final static boolean operational;
-
+
private final static ProcessDetection processDetection;
+ private static volatile boolean useUnixRealtimeTimer = false;
+
static
{
operational = NativeLibraryUtilities.loadNativeLibrary("unix");
@@ -66,6 +85,7 @@ public final class Unix
{
processDetection = ProcessDetection.NONE;
}
+ useUnixRealtimeTimer = Boolean.getBoolean("unix.realtime.timer");
}
/** set user ID on execution */
@@ -104,6 +124,103 @@ public final class Unix
/** execute/search by others */
public static final short S_IXOTH = 00001;
+ /**
+ * A class to represent a Unix <code>struct timespec</code> that holds a system time in nano-second resolution.
+ */
+ public static final class Time
+ {
+ private final long secs;
+
+ private final long nanos;
+
+ private Time(long secs, long nanos)
+ {
+ this.secs = secs;
+ this.nanos = nanos;
+ }
+
+ public long getSecs()
+ {
+ return secs;
+ }
+
+ public long getNanoSecPart()
+ {
+ return nanos;
+ }
+
+ public long getMicroSecPart()
+ {
+ if (nanos % 1000 >= 500)
+ {
+ return nanos / 1_000 + 1;
+ } else
+ {
+ return nanos / 1_000;
+ }
+ }
+
+ public long getMilliSecPart()
+ {
+ if (nanos % 1000000 >= 500000)
+ {
+ return nanos / 1_000_000 + 1;
+ } else
+ {
+ return nanos / 1_000_000;
+ }
+ }
+
+ public long getMillis()
+ {
+ return secs * 1_000 + getMilliSecPart();
+ }
+
+ @Override
+ public String toString()
+ {
+ return "Time [secs=" + secs + ", nanos=" + nanos + "]";
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + (int) (nanos ^ (nanos >>> 32));
+ result = prime * result + (int) (secs ^ (secs >>> 32));
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (obj == null)
+ {
+ return false;
+ }
+ if (getClass() != obj.getClass())
+ {
+ return false;
+ }
+ final Time other = (Time) obj;
+ if (nanos != other.nanos)
+ {
+ return false;
+ }
+ if (secs != other.secs)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ }
+
/**
* A class representing the Unix <code>stat</code> structure.
*/
@@ -125,11 +242,11 @@ public final class Unix
private final int gid;
- private final long lastAccess;
+ private final Time lastAccess;
- private final long lastModified;
+ private final Time lastModified;
- private final long lastStatusChange;
+ private final Time lastStatusChange;
private final long size;
@@ -140,6 +257,16 @@ public final class Unix
Stat(long deviceId, long inode, short permissions, byte linkType, int numberOfHardLinks,
int uid, int gid, long lastAccess, long lastModified, long lastStatusChange,
long size, long numberOfBlocks, int blockSize)
+ {
+ this(deviceId, inode, permissions, linkType, numberOfHardLinks, uid, gid,
+ lastAccess, 0, lastModified, 0, lastStatusChange, 0, size, numberOfBlocks, blockSize);
+ }
+
+ Stat(long deviceId, long inode, short permissions, byte linkType, int numberOfHardLinks,
+ int uid, int gid, long lastAccess, long lastAccessNanos,
+ long lastModified, long lastModifiedNanos,
+ long lastStatusChange, long lastStatusChangeNanos,
+ long size, long numberOfBlocks, int blockSize)
{
this.deviceId = deviceId;
this.inode = inode;
@@ -148,9 +275,9 @@ public final class Unix
this.numberOfHardLinks = numberOfHardLinks;
this.uid = uid;
this.gid = gid;
- this.lastAccess = lastAccess;
- this.lastModified = lastModified;
- this.lastStatusChange = lastStatusChange;
+ this.lastAccess = new Time(lastAccess, lastAccessNanos);
+ this.lastModified = new Time(lastModified, lastModifiedNanos);
+ this.lastStatusChange = new Time(lastStatusChange, lastStatusChangeNanos);
this.size = size;
this.numberOfBlocks = numberOfBlocks;
this.blockSize = blockSize;
@@ -161,6 +288,9 @@ public final class Unix
this.symbolicLinkOrNull = symbolicLinkOrNull;
}
+ /**
+ * Get link target of the symbolic link or <code>null</code>, if this is not a link or the link target has not been read.
+ */
public String tryGetSymbolicLink()
{
return symbolicLinkOrNull;
@@ -171,6 +301,9 @@ public final class Unix
return deviceId;
}
+ /**
+ * Returns the inode.
+ */
public long getInode()
{
return inode;
@@ -194,6 +327,11 @@ public final class Unix
return FileLinkType.SYMLINK == linkType;
}
+ /**
+ * Returns the number of hard links for the <var>linkName</var>. Does not dereference a symbolic link.
+ *
+ * @throws IOExceptionUnchecked If the information could not be obtained, e.g. because the link does not exist.
+ */
public int getNumberOfHardLinks()
{
return numberOfHardLinks;
@@ -209,21 +347,78 @@ public final class Unix
return gid;
}
- public long getLastAccess()
+ /**
+ * Time when file data last accessed.
+ * <p>
+ * Changed by the mknod(2), utimes(2) and read(2) system calls.
+ *
+ * @return {@link Time} object containing seconds (to nano-second resolution) since the epoch.
+ */
+ public Time getLastAccessTime()
{
return lastAccess;
}
- public long getLastModified()
+ /**
+ * Time when file data last accessed.
+ * <p>
+ * Changed by the mknod(2), utimes(2) and read(2) system calls.
+ *
+ * @return Seconds since the epoch.
+ */
+ public long getLastAccess()
+ {
+ return lastAccess.getSecs();
+ }
+
+ /**
+ * Time when file data last modified.
+ * <p>
+ * Changed by the mknod(2), utimes(2) and write(2) system calls.
+ *
+ * @return {@link Time} object containing seconds (to nano-second resolution) since the epoch.
+ */
+ public Time getLastModifiedTime()
{
return lastModified;
}
- public long getLastStatusChange()
+ /**
+ * Time when file data last modified.
+ * <p>
+ * Changed by the mknod(2), utimes(2) and write(2) system calls.
+ *
+ * @return Seconds since the epoch.
+ */
+ public long getLastModified()
+ {
+ return lastModified.getSecs();
+ }
+
+ /**
+ * Time when file status was last changed (inode data modification).
+ * <p>
+ * Changed by the chmod(2), chown(2), link(2), mknod(2), rename(2), unlink(2), utimes(2) and write(2) system calls.
+ *
+ * @return {@link Time} object containing seconds (to nano-second resolution) since the epoch.
+ */
+ public Time getLastStatusChangeTime()
{
return lastStatusChange;
}
+ /**
+ * Time when file status was last changed (inode data modification).
+ * <p>
+ * Changed by the chmod(2), chown(2), link(2), mknod(2), rename(2), unlink(2), utimes(2) and write(2) system calls.
+ *
+ * @return Seconds since the epoch.
+ */
+ public long getLastStatusChange()
+ {
+ return lastStatusChange.getSecs();
+ }
+
public long getSize()
{
return size;
@@ -369,8 +564,31 @@ public final class Unix
operation, filename, errorMessage)));
}
+ private static void throwRuntimeException(String operation, String errorMessage)
+ {
+ throw new RuntimeException(String.format("Error on %s: %s", operation, errorMessage));
+ }
+
private static native int init();
+ public static boolean isUseUnixRealtimeTimer()
+ {
+ return useUnixRealtimeTimer;
+ }
+
+ /**
+ * Sets whether to use the Unix realttime timer.
+ * <p>
+ * <i>Note that old versions of Linux and MacOSX do not yet support this and will terminate the Java program when
+ * this flag is set to <code>true</code> and {@link #getSystemTime()} is called!</i>
+ * @param useUnixRealTimeTimer if <code>true</code>, the realtime timer (nano-second resolution) will be used,
+ * otherwise the regular timer (micro-second resolution) will be used.
+ */
+ public static void setUseUnixRealtimeTimer(boolean useUnixRealTimeTimer)
+ {
+ Unix.useUnixRealtimeTimer = useUnixRealTimeTimer;
+ }
+
private static native int getpid();
private static native int getuid();
@@ -395,6 +613,20 @@ public final class Unix
private static native int chown(String filename, int uid, int gid);
+ private static native int lchown(String filename, int uid, int gid);
+
+ private static native int clock_gettime(final long[] time);
+
+ private static native int clock_gettime2(final long[] time);
+
+ private static native int lutimes(String filename,
+ long accessTimeSecs, long accessTimeMicroSecs,
+ long modificationTimeSecs, long modificationTimeMicroSecs);
+
+ private static native int utimes(String filename,
+ long accessTimeSecs, long accessTimeMicroSecs,
+ long modificationTimeSecs, long modificationTimeMicroSecs);
+
private static native String getuser(int uid);
private static native String getgroup(int gid);
@@ -414,7 +646,7 @@ public final class Unix
private static native String strerror(int errnum);
private static native String strerror();
-
+
@Private
static boolean isProcessRunningProcFS(int pid)
{
@@ -426,8 +658,7 @@ public final class Unix
{
try
{
- return Runtime.getRuntime().exec(new String[]
- { "ps", "-p", Integer.toString(pid) }).waitFor() == 0;
+ return Runtime.getRuntime().exec(new String[] { "ps", "-p", Integer.toString(pid) }).waitFor() == 0;
} catch (IOException ex)
{
return false;
@@ -442,8 +673,8 @@ public final class Unix
//
/**
- * Returns <code>true</code>, if the native library has been loaded successfully and the link
- * utilities are operational, <code>false</code> otherwise.
+ * 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()
{
@@ -459,9 +690,8 @@ public final class Unix
}
/**
- * Returns the last error that occurred in this class. Use this to find out what went wrong
- * after {@link #tryGetLinkInfo(String)} or {@link #tryGetFileInfo(String)} returned
- * <code>null</code>.
+ * Returns the last error that occurred in this class. Use this to find out what went wrong after {@link #tryGetLinkInfo(String)} or
+ * {@link #tryGetFileInfo(String)} returned <code>null</code>.
*/
public static String getLastError()
{
@@ -481,9 +711,8 @@ public final class Unix
}
/**
- * Returns <code>true</code>, if the process with <var>pid</var> is currently running and
- * <code>false</code>, if it is not running or if process detection is not available (
- * {@link #canDetectProcesses()} <code>== false</code>).
+ * Returns <code>true</code>, if the process with <var>pid</var> is currently running and <code>false</code>, if it is not running or if process
+ * detection is not available ( {@link #canDetectProcesses()} <code>== false</code>).
*/
public static boolean isProcessRunning(int pid)
{
@@ -530,6 +759,37 @@ public final class Unix
return getegid();
}
+ //
+ // Time functions
+ //
+
+ /**
+ * Gets the current system time.
+ *
+ * @return the system time as <i>seconds since the epoch</i> and, in addition,
+ * nano-seconds since the current second.
+ */
+ public static final Time getSystemTime()
+ {
+ final long[] time = new long[2];
+ final int result = useUnixRealtimeTimer ? clock_gettime(time) : clock_gettime2(time);
+ if (result < 0)
+ {
+ throwRuntimeException("get system time", strerror(result));
+ }
+ return new Time(time[0], time[1]);
+ }
+
+ /**
+ * Gets the current system time.
+ *
+ * @return the system time as <i>milli-seconds since the epoch</i>.
+ */
+ public static final long getSystemTimeMillis()
+ {
+ return getSystemTime().getMillis();
+ }
+
//
// File functions
//
@@ -537,8 +797,8 @@ public final class Unix
/**
* Creates a hard link <var>linkName</var> that points to <var>fileName</var>.
*
- * @throws IOExceptionUnchecked If the underlying system call fails, e.g. because
- * <var>linkName</var> already exists or <var>fileName</var> does not exist.
+ * @throws IOExceptionUnchecked If the underlying system call fails, e.g. because <var>linkName</var> already exists or <var>fileName</var> does
+ * not exist.
*/
public static final void createHardLink(String fileName, String linkName)
throws IOExceptionUnchecked
@@ -561,8 +821,7 @@ public final class Unix
/**
* Creates a symbolic link <var>linkName</var> that points to <var>fileName</var>.
*
- * @throws IOExceptionUnchecked If the underlying system call fails, e.g. because
- * <var>linkName</var> already exists.
+ * @throws IOExceptionUnchecked If the underlying system call fails, e.g. because <var>linkName</var> already exists.
*/
public static final void createSymbolicLink(String fileName, String linkName)
throws IOExceptionUnchecked
@@ -629,45 +888,45 @@ public final class Unix
}
/**
- * Returns the inode for the <var>fileName</var>.
+ * Returns the inode for the <var>fileName</var>. Does not dereference a symbolic link.
+ *
+ * @throws IOExceptionUnchecked If the information could not be obtained, e.g. because the link does not exist.
*
- * @throws IOExceptionUnchecked If the information could not be obtained, e.g. because the link
- * does not exist.
+ * @deprecated Use method {@link Stat#getInode(String)} from {@link #getLinkInfo(String)} instead.
*/
- public static final long getInode(String fileName) throws IOExceptionUnchecked
+ @Deprecated
+ public static final long getInode(String linkName) throws IOExceptionUnchecked
{
- return getLStat(fileName).getInode();
+ return getLStat(linkName).getInode();
}
/**
- * Returns the number of hard links for the <var>fileName</var>.
+ * Returns the number of hard links for the <var>linkName</var>. Does not dereference a symbolic link.
*
- * @throws IOExceptionUnchecked If the information could not be obtained, e.g. because the link
- * does not exist.
+ * @throws IOExceptionUnchecked If the information could not be obtained, e.g. because the link does not exist.
+ *
+ * @deprecated Use method {@link Stat#getNumberOfHardLinks(String)} from {@link #getLinkInfo(String)} instead.
*/
- public static final int getNumberOfHardLinks(String fileName) throws IOExceptionUnchecked
+ @Deprecated
+ public static final int getNumberOfHardLinks(String linkName) throws IOExceptionUnchecked
{
- return getLStat(fileName).getNumberOfHardLinks();
+ return getLStat(linkName).getNumberOfHardLinks();
}
/**
- * Returns <code>true</code> if <var>fileName</var> is a symbolic link and <code>false</code>
- * otherwise.
+ * Returns <code>true</code> if <var>linkName</var> is a symbolic link and <code>false</code> otherwise.
*
- * @throws IOExceptionUnchecked If the information could not be obtained, e.g. because the link
- * does not exist.
+ * @throws IOExceptionUnchecked If the information could not be obtained, e.g. because the link does not exist.
*/
- public static final boolean isSymbolicLink(String fileName) throws IOExceptionUnchecked
+ public static final boolean isSymbolicLink(String linkName) throws IOExceptionUnchecked
{
- return getLStat(fileName).isSymbolicLink();
+ return getLStat(linkName).isSymbolicLink();
}
/**
- * Returns the value of the symbolik link <var>linkName</var>, or <code>null</code>, if
- * <var>linkName</var> is not a symbolic link.
+ * Returns the value of the symbolik link <var>linkName</var>, or <code>null</code>, if <var>linkName</var> is not a symbolic link.
*
- * @throws IOExceptionUnchecked If the information could not be obtained, e.g. because the link
- * does not exist.
+ * @throws IOExceptionUnchecked If the information could not be obtained, e.g. because the link does not exist.
*/
public static final String tryReadSymbolicLink(String linkName) throws IOExceptionUnchecked
{
@@ -678,8 +937,7 @@ public final class Unix
/**
* Returns the information about <var>fileName</var>.
*
- * @throws IOExceptionUnchecked If the information could not be obtained, e.g. because the file
- * does not exist.
+ * @throws IOExceptionUnchecked If the information could not be obtained, e.g. because the file does not exist.
*/
public static final Stat getFileInfo(String fileName) throws IOExceptionUnchecked
{
@@ -687,9 +945,8 @@ public final class Unix
}
/**
- * Returns the information about <var>fileName</var>, or {@link NullPointerException}, if the
- * information could not be obtained, e.g. because the file does not exist (call
- * {@link #getLastError()} to find out what went wrong).
+ * Returns the information about <var>fileName</var>, or {@link NullPointerException}, if the information could not be obtained, e.g. because the
+ * file does not exist (call {@link #getLastError()} to find out what went wrong).
*/
public static final Stat tryGetFileInfo(String fileName) throws IOExceptionUnchecked
{
@@ -699,8 +956,7 @@ public final class Unix
/**
* Returns the information about <var>linkName</var>.
*
- * @throws IOExceptionUnchecked If the information could not be obtained, e.g. because the link
- * does not exist.
+ * @throws IOExceptionUnchecked If the information could not be obtained, e.g. because the link does not exist.
*/
public static final Stat getLinkInfo(String linkName) throws IOExceptionUnchecked
{
@@ -708,12 +964,10 @@ public final class Unix
}
/**
- * Returns the information about <var>linkName</var>. If
- * <code>readSymbolicLinkTarget == true</code>, then the symbolic link target is read when
+ * Returns the information about <var>linkName</var>. If <code>readSymbolicLinkTarget == true</code>, then the symbolic link target is read when
* <var>linkName</var> is a symbolic link.
*
- * @throws IOExceptionUnchecked If the information could not be obtained, e.g. because the link
- * does not exist.
+ * @throws IOExceptionUnchecked If the information could not be obtained, e.g. because the link does not exist.
*/
public static final Stat getLinkInfo(String linkName, boolean readSymbolicLinkTarget)
throws IOExceptionUnchecked
@@ -727,9 +981,8 @@ public final class Unix
}
/**
- * Returns the information about <var>linkName</var>, or {@link NullPointerException}, if the
- * information could not be obtained, e.g. because the link does not exist (call
- * {@link #getLastError()} to find out what went wrong).
+ * Returns the information about <var>linkName</var>, or {@link NullPointerException}, if the information could not be obtained, e.g. because the
+ * link does not exist (call {@link #getLastError()} to find out what went wrong).
*/
public static final Stat tryGetLinkInfo(String linkName) throws IOExceptionUnchecked
{
@@ -737,10 +990,9 @@ public final class Unix
}
/**
- * Returns the information about <var>linkName</var>, or <code>null</code> if the information
- * can not be obtained, e.g. because the link does not exist (call {@link #getLastError()} to
- * find out what went wrong). If <code>readSymbolicLinkTarget == true</code>, then the symbolic
- * link target is read when <var>linkName</var> is a symbolic link.
+ * Returns the information about <var>linkName</var>, or <code>null</code> if the information can not be obtained, e.g. because the link does not
+ * exist (call {@link #getLastError()} to find out what went wrong). If <code>readSymbolicLinkTarget == true</code>, then the symbolic link target
+ * is read when <var>linkName</var> is a symbolic link.
*/
public static final Stat tryGetLinkInfo(String linkName, boolean readSymbolicLinkTarget)
throws IOExceptionUnchecked
@@ -759,6 +1011,7 @@ public final class Unix
/**
* Sets the access mode of <var>filename</var> to the specified <var>mode</var> value.
+ * Dereferences a symbolic link.
*/
public static final void setAccessMode(String fileName, short mode) throws IOExceptionUnchecked
{
@@ -774,8 +1027,8 @@ public final class Unix
}
/**
- * Sets the owner of <var>filename</var> to the specified <var>uid</var> and <var>gid</var>
- * values.
+ * Sets the owner of <var>fileName</var> to the specified <var>uid</var> and <var>gid</var> values.
+ * Dereferences a symbolic link.
*/
public static final void setOwner(String fileName, int uid, int gid)
throws IOExceptionUnchecked
@@ -791,6 +1044,186 @@ public final class Unix
}
}
+ /**
+ * Sets the owner of <var>fileName</var> to the <var>uid</var> and <var>gid</var> of the specified <code>user</code>.
+ * Dereferences a symbolic link.
+ */
+ public static final void setOwner(String fileName, Password user)
+ throws IOExceptionUnchecked
+ {
+ if (fileName == null)
+ {
+ throw new NullPointerException("fileName");
+ }
+ final int result = chown(fileName, user.getUid(), user.getGid());
+ if (result < 0)
+ {
+ throwFileException("set owner", fileName, strerror(result));
+ }
+ }
+
+ /**
+ * Sets the owner of <var>linkName</var> to the specified <var>uid</var> and <var>gid</var> values.
+ * Does not dereference a symbolic link.
+ */
+ public static final void setLinkOwner(String linkName, int uid, int gid)
+ throws IOExceptionUnchecked
+ {
+ if (linkName == null)
+ {
+ throw new NullPointerException("linkName");
+ }
+ final int result = lchown(linkName, uid, gid);
+ if (result < 0)
+ {
+ throwFileException("set link owner", linkName, strerror(result));
+ }
+ }
+
+ /**
+ * Sets the owner of <var>linkName</var> to the <var>uid</var> and <var>gid</var> of the specified <code>user</code>.
+ * Does not dereference a symbolic link.
+ */
+ public static final void setLinkOwner(String linkName, Password user)
+ throws IOExceptionUnchecked
+ {
+ if (linkName == null)
+ {
+ throw new NullPointerException("linkName");
+ }
+ final int result = lchown(linkName, user.getUid(), user.getGid());
+ if (result < 0)
+ {
+ throwFileException("set owner", linkName, strerror(result));
+ }
+ }
+
+ /**
+ * Change link timestamps of a file, directory or link. Does not dereference a symbolic link.
+ *
+ * @param fileName The name of the file or link to change the timestamp of.
+ * @param accessTimeSecs The new access time in seconds since start of the epoch.
+ * @param accessTimeMicroSecs The micro-second part of the new access time.
+ * @param modificationTimeSecs The new modification time in seconds since start of the epoch.
+ * @param modificationTimeMicroSecs The micro-second part of the new modification time.
+ */
+ public static void setLinkTimestamps(String fileName,
+ long accessTimeSecs, long accessTimeMicroSecs,
+ long modificationTimeSecs, long modificationTimeMicroSecs) throws IOExceptionUnchecked
+ {
+ final int result = lutimes(fileName, accessTimeSecs, accessTimeMicroSecs,
+ modificationTimeSecs, modificationTimeMicroSecs);
+ if (result < 0)
+ {
+ throwFileException("set file timestamps", fileName, strerror(result));
+ }
+ }
+
+ /**
+ * Change file timestamps of a file, directory or link. Does not dereference a symbolic link.
+ *
+ * @param fileName The name of the file or link to change the timestamp of.
+ * @param accessTimeSecs The new access time in seconds since start of the epoch.
+ * @param modificationTimeSecs The new modification time in seconds since start of the epoch.
+ */
+ public static void setLinkTimestamps(String fileName,
+ long accessTimeSecs, long modificationTimeSecs) throws IOExceptionUnchecked
+ {
+ setLinkTimestamps(fileName, accessTimeSecs, 0, modificationTimeSecs, 0);
+ }
+
+ /**
+ * Change file timestamps of a file, directory or link. Does not dereference a symbolic link.
+ *
+ * @param fileName The name of the file or link to change the timestamp of.
+ * @param accessTime The new access time as {@link Time} object.
+ * @param modificationTime The new modification time as {@link Time} object.
+ */
+ public static void setLinkTimestamps(String fileName,
+ Time accessTime, Time modificationTime) throws IOExceptionUnchecked
+ {
+ setLinkTimestamps(fileName, accessTime.getSecs(), accessTime.getMicroSecPart(),
+ modificationTime.getSecs(), modificationTime.getMicroSecPart());
+ }
+
+ /**
+ * Change file timestamps of a file, directory or link to the current time. Does not dereference a symbolic link.
+ *
+ * @param fileName The name of the file or link to change the timestamp of.
+ */
+ public static void setLinkTimestamps(String fileName) throws IOExceptionUnchecked
+ {
+ final Time now = getSystemTime();
+ final int result = lutimes(fileName, now.getSecs(), now.getMicroSecPart(), now.getSecs(), now.getMicroSecPart());
+ if (result < 0)
+ {
+ throwFileException("set file timestamps", fileName, strerror(result));
+ }
+ }
+
+ /**
+ * Change file timestamps of a file, directory or link. Dereferences a symbolic link.
+ *
+ * @param fileName The name of the file or link to change the timestamp of.
+ * @param accessTimeSecs The new access time in seconds since start of the epoch.
+ * @param accessTimeMicroSecs The micro-second part of the new access time.
+ * @param modificationTimeSecs The new modification time in seconds since start of the epoch.
+ * @param modificationTimeMicroSecs The micro-second part of the new modification time.
+ */
+ public static void setFileTimestamps(String fileName,
+ long accessTimeSecs, long accessTimeMicroSecs,
+ long modificationTimeSecs, long modificationTimeMicroSecs) throws IOExceptionUnchecked
+ {
+ final int result = utimes(fileName, accessTimeSecs, accessTimeMicroSecs,
+ modificationTimeSecs, modificationTimeMicroSecs);
+ if (result < 0)
+ {
+ throwFileException("set file timestamps", fileName, strerror(result));
+ }
+ }
+
+ /**
+ * Change file timestamps of a file, directory or link. Does not dereference a symbolic link.
+ *
+ * @param fileName The name of the file or link to change the timestamp of.
+ * @param accessTimeSecs The new access time in seconds since start of the epoch.
+ * @param modificationTimeSecs The new modification time in seconds since start of the epoch.
+ */
+ public static void setFileTimestamps(String fileName,
+ long accessTimeSecs, long modificationTimeSecs) throws IOExceptionUnchecked
+ {
+ setFileTimestamps(fileName, accessTimeSecs, 0, modificationTimeSecs, 0);
+ }
+
+ /**
+ * Change file timestamps of a file, directory or link. Does not dereference a symbolic link.
+ *
+ * @param fileName The name of the file or link to change the timestamp of.
+ * @param accessTime The new access time as {@link Time} object.
+ * @param modificationTime The new modification time as {@link Time} object.
+ */
+ public static void setFileTimestamps(String fileName,
+ Time accessTime, Time modificationTime) throws IOExceptionUnchecked
+ {
+ setFileTimestamps(fileName, accessTime.getSecs(), accessTime.getMicroSecPart(),
+ modificationTime.getSecs(), modificationTime.getMicroSecPart());
+ }
+
+ /**
+ * Change file timestamps of a file, directory or link to the current time. Does not dereference a symbolic link.
+ *
+ * @param fileName The name of the file or link to change the timestamp of.
+ */
+ public static void setFileTimestamps(String fileName) throws IOExceptionUnchecked
+ {
+ final Time now = getSystemTime();
+ final int result = utimes(fileName, now.getSecs(), now.getMicroSecPart(), now.getSecs(), now.getMicroSecPart());
+ if (result < 0)
+ {
+ throwFileException("set file timestamps", fileName, strerror(result));
+ }
+ }
+
//
// User functions
//
@@ -804,8 +1237,7 @@ public final class Unix
}
/**
- * Returns the uid of the <var>userName</var>, or <code>-1</code>, if no user with this name
- * exists.
+ * Returns the uid of the <var>userName</var>, or <code>-1</code>, if no user with this name exists.
*/
public static final int getUidForUserName(String userName)
{
@@ -817,8 +1249,7 @@ public final class Unix
}
/**
- * Returns the {@link Password} for the given <var>userName</var>, or <code>null</code>, if no
- * user with that name exists.
+ * Returns the {@link Password} for the given <var>userName</var>, or <code>null</code>, if no user with that name exists.
*/
public static final Password tryGetUserByName(String userName)
{
@@ -830,8 +1261,7 @@ public final class Unix
}
/**
- * Returns the {@link Password} for the given <var>userName</var>, or <code>null</code>, if no
- * user with that name exists.
+ * Returns the {@link Password} for the given <var>userName</var>, or <code>null</code>, if no user with that name exists.
*/
public static final Password tryGetUserByUid(int uid)
{
@@ -843,8 +1273,7 @@ public final class Unix
//
/**
- * Returns the name of the group identified by <var>gid</var>, or <code>null</code>, if no group
- * with that <var>gid</var> exists.
+ * Returns the name of the group identified by <var>gid</var>, or <code>null</code>, if no group with that <var>gid</var> exists.
*/
public static final String tryGetGroupNameForGid(int gid)
{
@@ -852,8 +1281,7 @@ public final class Unix
}
/**
- * Returns the gid of the <var>groupName</var>, or <code>-1</code>, if no group with this name
- * exists.
+ * Returns the gid of the <var>groupName</var>, or <code>-1</code>, if no group with this name exists.
*/
public static final int getGidForGroupName(String groupName)
{
@@ -865,8 +1293,7 @@ public final class Unix
}
/**
- * Returns the {@link Group} for the given <var>groupName</var>, or <code>null</code>, if no
- * group with that name exists.
+ * Returns the {@link Group} for the given <var>groupName</var>, or <code>null</code>, if no group with that name exists.
*/
public static final Group tryGetGroupByName(String groupName)
{
@@ -878,8 +1305,7 @@ public final class Unix
}
/**
- * Returns the {@link Group} for the given <var>gid</var>, or <code>null</code>, if no group
- * with that gid exists.
+ * Returns the {@link Group} for the given <var>gid</var>, or <code>null</code>, if no group with that gid exists.
*/
public static final Group tryGetGroupByGid(int gid)
{
=====================================
sourceTest/java/ch/systemsx/cisd/base/AllTests.java
=====================================
@@ -24,6 +24,7 @@ import ch.systemsx.cisd.base.io.RandomAccessFileImplTests;
import ch.systemsx.cisd.base.mdarray.MDArrayTests;
import ch.systemsx.cisd.base.namedthread.NamingThreadPoolExecutorTest;
import ch.systemsx.cisd.base.unix.Unix;
+import ch.systemsx.cisd.base.unix.UnixRootTests;
import ch.systemsx.cisd.base.unix.UnixTests;
/**
@@ -53,6 +54,7 @@ public class AllTests
if (Unix.isOperational())
{
UnixTests.main(args);
+ UnixRootTests.main(args);
} else
{
System.err.println("No unix library found.");
=====================================
sourceTest/java/ch/systemsx/cisd/base/unix/UnixRootTests.java
=====================================
@@ -0,0 +1,108 @@
+package ch.systemsx.cisd.base.unix;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.nio.charset.Charset;
+
+import org.apache.commons.io.FileUtils;
+import org.testng.annotations.Test;
+
+import ch.systemsx.cisd.base.BuildAndEnvironmentInfo;
+import ch.systemsx.cisd.base.tests.AbstractFileSystemTestCase;
+import ch.systemsx.cisd.base.unix.Unix.Stat;
+
+/**
+ * Tests of the {@link Unix} class that can only be performed as user root.
+ */
+public class UnixRootTests extends AbstractFileSystemTestCase
+{
+ @Test(groups =
+ { "requires_unix" })
+ public void testChown() throws IOException
+ {
+ if (Unix.getUid() != 0)
+ {
+ System.out.println("Skipping test as we are not root.");
+ return;
+ }
+ final short accessMode = (short) 0777;
+ final String content = "someText\n";
+ final File f = new File(workingDirectory, "someFile");
+ final File s = new File(workingDirectory, "MyLink");
+ FileUtils.writeStringToFile(f, content, Charset.defaultCharset());
+ Unix.setAccessMode(f.getAbsolutePath(), accessMode);
+ final Stat info = Unix.getLinkInfo(f.getAbsolutePath());
+ Unix.setOwner(f.getAbsolutePath(), info.getUid(), info.getGid());
+ assertEquals(1, info.getNumberOfHardLinks());
+ assertEquals(content.length(), info.getSize());
+ assertEquals(accessMode, info.getPermissions());
+ final Unix.Password nobody = Unix.tryGetUserByName("nobody");
+ assertNotNull(nobody);
+ final Unix.Password daemon = Unix.tryGetUserByName("daemon");
+ assertNotNull(daemon);
+ Unix.setOwner(f.getAbsolutePath(), nobody);
+ Unix.createSymbolicLink(f.getAbsolutePath(), s.getAbsolutePath());
+ Unix.setLinkOwner(s.getAbsolutePath(), daemon);
+
+ final Unix.Stat fileInfo = Unix.getFileInfo(s.getAbsolutePath());
+ assertEquals(nobody.getUid(), fileInfo.getUid());
+ assertEquals(nobody.getGid(), fileInfo.getGid());
+
+ final Unix.Stat linkInfo = Unix.getLinkInfo(s.getAbsolutePath());
+ assertEquals(daemon.getUid(), linkInfo.getUid());
+ assertEquals(daemon.getGid(), linkInfo.getGid());
+ }
+
+ public static void main(String[] args) throws Throwable
+ {
+ System.out.println(BuildAndEnvironmentInfo.INSTANCE);
+ System.out.println("Test class: " + UnixRootTests.class.getSimpleName());
+ System.out.println();
+ if (Unix.isOperational() == false)
+ {
+ System.err.println("No unix library found.");
+ System.exit(1);
+ }
+ final UnixRootTests test = new UnixRootTests();
+ try
+ {
+ for (Method m : UnixRootTests.class.getMethods())
+ {
+ final Test testAnnotation = m.getAnnotation(Test.class);
+ if (testAnnotation == null)
+ {
+ continue;
+ }
+ System.out.println("Running " + m.getName());
+ test.setUp();
+ try
+ {
+ m.invoke(test);
+ } catch (InvocationTargetException wrapperThrowable)
+ {
+ final Throwable th = wrapperThrowable.getCause();
+ boolean exceptionFound = false;
+ for (Class<?> expectedExClazz : testAnnotation.expectedExceptions())
+ {
+ if (expectedExClazz == th.getClass())
+ {
+ exceptionFound = true;
+ break;
+ }
+ }
+ if (exceptionFound == false)
+ {
+ throw th;
+ }
+ }
+ }
+ System.out.println("Tests OK!");
+ } finally
+ {
+ test.afterClass();
+ }
+ }
+
+}
=====================================
sourceTest/java/ch/systemsx/cisd/base/unix/UnixTests.java
=====================================
@@ -16,6 +16,8 @@
package ch.systemsx.cisd.base.unix;
+import static org.testng.Assert.assertNotEquals;
+
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
@@ -40,6 +42,15 @@ import ch.systemsx.cisd.base.unix.Unix.Stat;
@Friend(toClasses = Unix.class)
public class UnixTests extends AbstractFileSystemTestCase
{
+ private UnixTests()
+ {
+ super();
+ }
+
+ private UnixTests(boolean cleanAfterMethod)
+ {
+ super(cleanAfterMethod);
+ }
@Test(groups =
{ "requires_unix" })
@@ -58,7 +69,7 @@ public class UnixTests extends AbstractFileSystemTestCase
assertEquals("root", Unix.tryGetUserNameForUid(0));
assertEquals(FileLinkType.REGULAR_FILE, info.getLinkType());
assertFalse(info.isSymbolicLink());
- assertEquals(f.lastModified(), 1000 * info.getLastModified());
+ assertEquals(f.lastModified()/1000, info.getLastModified());
}
@Test(groups =
@@ -105,6 +116,124 @@ public class UnixTests extends AbstractFileSystemTestCase
assertNull(info2.tryGetSymbolicLink());
}
+ @Test(groups =
+ { "requires_unix" })
+ public void testTouchSymLinkAndFileRealtimeTimer() throws IOException, InterruptedException
+ {
+ if (BuildAndEnvironmentInfo.INSTANCE.getOS().contains("2.6.32"))
+ {
+ System.out.println(" ...skipping as CentOS6 does not yet support the realtime timer.");
+ return;
+ }
+ Unix.setUseUnixRealtimeTimer(true);
+ final File f = new File(workingDirectory, "someOtherFile");
+ final String content = "someMoreText\n";
+ FileUtils.writeStringToFile(f, content, Charset.defaultCharset());
+ final File s = new File(workingDirectory, "someLink");
+ Unix.createSymbolicLink(f.getAbsolutePath(), s.getAbsolutePath());
+ final Stat info = Unix.getLinkInfo(s.getAbsolutePath());
+ assertEquals(1, info.getNumberOfHardLinks());
+ assertEquals(FileLinkType.SYMLINK, info.getLinkType());
+ assertTrue(info.isSymbolicLink());
+ assertEquals(f.getAbsolutePath(), info.tryGetSymbolicLink());
+ assertEquals(f.getAbsolutePath(), Unix.tryReadSymbolicLink(s.getAbsolutePath()));
+ assertNull(Unix.getLinkInfo(s.getAbsolutePath(), false).tryGetSymbolicLink());
+ final long lastMicros = info.getLastModifiedTime().getMicroSecPart();
+ final long newLastModifiedLink = info.getLastModifiedTime().getSecs() - 24 * 3600;
+ Unix.setLinkTimestamps(s.getAbsolutePath(), newLastModifiedLink, lastMicros, newLastModifiedLink, lastMicros);
+
+ final long newLastModifiedFile = info.getLastModifiedTime().getSecs() - 2 * 24 * 3600;
+ Unix.setFileTimestamps(f.getAbsolutePath(), newLastModifiedFile, lastMicros, newLastModifiedFile, lastMicros);
+
+ final Stat info2l = Unix.getLinkInfo(s.getAbsolutePath(), false);
+ assertEquals(newLastModifiedLink, info2l.getLastModifiedTime().getSecs());
+ assertEquals(lastMicros, info2l.getLastModifiedTime().getMicroSecPart());
+ assertEquals(newLastModifiedLink, info2l.getLastAccessTime().getSecs());
+ assertEquals(lastMicros, info2l.getLastAccessTime().getMicroSecPart());
+
+ final Stat info2f = Unix.getFileInfo(s.getAbsolutePath());
+ final Stat info2f2 = Unix.getLinkInfo(f.getAbsolutePath());
+ assertNotEquals(info2l.getLastModifiedTime(), info2f2.getLastModifiedTime());
+ assertEquals(info2f2.getLastModifiedTime(), info2f.getLastModifiedTime());
+ assertEquals(newLastModifiedFile, info2f.getLastModifiedTime().getSecs());
+ assertEquals(lastMicros, info2f.getLastModifiedTime().getMicroSecPart());
+ assertEquals(newLastModifiedFile, info2f.getLastAccessTime().getSecs());
+ assertEquals(lastMicros, info2f.getLastAccessTime().getMicroSecPart());
+
+ Thread.sleep(10);
+
+ final Unix.Time now1 = Unix.getSystemTime();
+ assertNotEquals(0, now1.getNanoSecPart() % 1_000);
+ Unix.setLinkTimestamps(s.getAbsolutePath());
+ final Unix.Time now2 = Unix.getSystemTime();
+ final Stat info3 = Unix.getLinkInfo(s.getAbsolutePath());
+
+ assertTrue(now1.getSecs() <= info3.getLastModified() && info3.getLastModified() <= now2.getSecs());
+ assertTrue(now1.getMicroSecPart() <= info3.getLastModifiedTime().getMicroSecPart() && info.getLastModifiedTime().getMilliSecPart() <= now2.getMicroSecPart());
+ assertTrue(now1.getSecs() <= info3.getLastAccess() && info3.getLastAccess() <= now2.getSecs());
+ assertTrue(now1.getMicroSecPart() <= info3.getLastAccessTime().getMicroSecPart() && info.getLastAccessTime().getMilliSecPart() <= now2.getMicroSecPart());
+ assertNotEquals(lastMicros, info3.getLastModifiedTime().getMicroSecPart());
+ assertNotEquals(lastMicros, info3.getLastAccessTime().getMicroSecPart());
+
+ }
+
+ @Test(groups =
+ { "requires_unix" })
+ public void testTouchSymLinkAndFile() throws IOException, InterruptedException
+ {
+ Unix.setUseUnixRealtimeTimer(false);
+ final File f = new File(workingDirectory, "someOtherFile");
+ final String content = "someMoreText\n";
+ FileUtils.writeStringToFile(f, content, Charset.defaultCharset());
+ final File s = new File(workingDirectory, "someLink");
+ Unix.createSymbolicLink(f.getAbsolutePath(), s.getAbsolutePath());
+ final Stat info = Unix.getLinkInfo(s.getAbsolutePath());
+ assertEquals(1, info.getNumberOfHardLinks());
+ assertEquals(FileLinkType.SYMLINK, info.getLinkType());
+ assertTrue(info.isSymbolicLink());
+ assertEquals(f.getAbsolutePath(), info.tryGetSymbolicLink());
+ assertEquals(f.getAbsolutePath(), Unix.tryReadSymbolicLink(s.getAbsolutePath()));
+ assertNull(Unix.getLinkInfo(s.getAbsolutePath(), false).tryGetSymbolicLink());
+ final long lastMicros = info.getLastModifiedTime().getMicroSecPart();
+ final long newLastModifiedLink = info.getLastModifiedTime().getSecs() - 24 * 3600;
+ Unix.setLinkTimestamps(s.getAbsolutePath(), newLastModifiedLink, lastMicros, newLastModifiedLink, lastMicros);
+
+ final long newLastModifiedFile = info.getLastModifiedTime().getSecs() - 2 * 24 * 3600;
+ Unix.setFileTimestamps(f.getAbsolutePath(), newLastModifiedFile, lastMicros, newLastModifiedFile, lastMicros);
+
+ final Stat info2l = Unix.getLinkInfo(s.getAbsolutePath(), false);
+ assertEquals(newLastModifiedLink, info2l.getLastModifiedTime().getSecs());
+ assertEquals(lastMicros, info2l.getLastModifiedTime().getMicroSecPart());
+ assertEquals(newLastModifiedLink, info2l.getLastAccessTime().getSecs());
+ assertEquals(lastMicros, info2l.getLastAccessTime().getMicroSecPart());
+
+ final Stat info2f = Unix.getFileInfo(s.getAbsolutePath());
+ final Stat info2f2 = Unix.getLinkInfo(f.getAbsolutePath());
+ assertNotEquals(info2l.getLastModifiedTime(), info2f2.getLastModifiedTime());
+ assertEquals(info2f2.getLastModifiedTime(), info2f.getLastModifiedTime());
+ assertEquals(newLastModifiedFile, info2f.getLastModifiedTime().getSecs());
+ assertEquals(lastMicros, info2f.getLastModifiedTime().getMicroSecPart());
+ assertEquals(newLastModifiedFile, info2f.getLastAccessTime().getSecs());
+ assertEquals(lastMicros, info2f.getLastAccessTime().getMicroSecPart());
+
+
+ Thread.sleep(10);
+
+ final Unix.Time now1 = Unix.getSystemTime();
+ assertEquals(0, now1.getNanoSecPart() % 1_000);
+ Unix.setLinkTimestamps(s.getAbsolutePath());
+ final Unix.Time now2 = Unix.getSystemTime();
+ final Stat info3 = Unix.getLinkInfo(s.getAbsolutePath());
+
+ assertTrue(now1.getSecs() <= info3.getLastModified() && info3.getLastModified() <= now2.getSecs());
+ assertTrue(now1.getMicroSecPart() <= info3.getLastModifiedTime().getMicroSecPart() && info.getLastModifiedTime().getMilliSecPart() <= now2.getMicroSecPart());
+ assertTrue(now1.getSecs() <= info3.getLastAccess() && info3.getLastAccess() <= now2.getSecs());
+ assertTrue(now1.getMicroSecPart() <= info3.getLastAccessTime().getMicroSecPart() && info.getLastAccessTime().getMilliSecPart() <= now2.getMicroSecPart());
+ assertNotEquals(lastMicros, info3.getLastModifiedTime().getMicroSecPart());
+ assertNotEquals(lastMicros, info3.getLastAccessTime().getMicroSecPart());
+
+ }
+
@Test(groups =
{ "requires_unix" })
public void testGetLinkInfoSymLinkDanglingLink() throws IOException
@@ -167,14 +296,14 @@ public class UnixTests extends AbstractFileSystemTestCase
{ "requires_unix" })
public void testGetUid()
{
- assertTrue(Unix.getUid() > 0);
+ assertTrue(Unix.getUid() >= 0);
}
@Test(groups =
{ "requires_unix" })
public void testGetEuid()
{
- assertTrue(Unix.getEuid() > 0);
+ assertTrue(Unix.getEuid() >= 0);
assertEquals(Unix.getUid(), Unix.getEuid());
}
@@ -182,14 +311,14 @@ public class UnixTests extends AbstractFileSystemTestCase
{ "requires_unix" })
public void testGetGid()
{
- assertTrue(Unix.getGid() > 0);
+ assertTrue(Unix.getGid() >= 0);
}
@Test(groups =
{ "requires_unix" })
public void testGetEgid()
{
- assertTrue(Unix.getEgid() > 0);
+ assertTrue(Unix.getEgid() >= 0);
assertEquals(Unix.getGid(), Unix.getEgid());
}
@@ -309,6 +438,8 @@ public class UnixTests extends AbstractFileSystemTestCase
System.err.println("No unix library found.");
System.exit(1);
}
+ boolean stopOnError = args.length > 0 && "stopOnError".equalsIgnoreCase(args[0]);
+ int failed = 0;
final UnixTests test = new UnixTests();
try
{
@@ -338,14 +469,29 @@ public class UnixTests extends AbstractFileSystemTestCase
}
if (exceptionFound == false)
{
- throw th;
+ ++failed;
+ System.out.println("Caught exception in method " + m.getName());
+ th.printStackTrace();
+ if (stopOnError)
+ {
+ System.exit(1);
+ }
}
}
}
- System.out.println("Tests OK!");
+ if (failed == 0)
+ {
+ System.out.println("Tests OK!");
+ } else
+ {
+ System.out.printf("%d tests FAILED!\n", failed);
+ }
} finally
{
- test.afterClass();
+ if (failed == 0)
+ {
+ test.afterClass();
+ }
}
}
View it on GitLab: https://salsa.debian.org/med-team/libsis-base-java/commit/e42bd7e6bfdb4d5c3a828f104a750d1794dd0905
--
View it on GitLab: https://salsa.debian.org/med-team/libsis-base-java/commit/e42bd7e6bfdb4d5c3a828f104a750d1794dd0905
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20180926/838b7c57/attachment-0001.html>
More information about the debian-med-commit
mailing list