From 02084fb40bebb15ee0b2db30260cf53205d89921 Mon Sep 17 00:00:00 2001 From: juanf <juanf@ethz.ch> Date: Mon, 12 Jun 2023 09:59:13 +0200 Subject: [PATCH] SSDM-13521: moving posix functionality to original unix class --- .../java/ch/systemsx/cisd/base/unix/Unix.java | 1566 ++++++----------- .../cisd/base/unix/UnixRootTests.java | 108 -- .../ch/systemsx/cisd/base/unix/UnixTests.java | 340 +--- .../ch/systemsx/cisd/common/io/Posix.java | 71 +- .../ch/systemsx/cisd/common/io/PosixTest.java | 117 -- 5 files changed, 578 insertions(+), 1624 deletions(-) delete mode 100644 lib-base/sourceTest/java/ch/systemsx/cisd/base/unix/UnixRootTests.java diff --git a/lib-base/source/java/ch/systemsx/cisd/base/unix/Unix.java b/lib-base/source/java/ch/systemsx/cisd/base/unix/Unix.java index 7c65aa9a551..63ad45b0968 100644 --- a/lib-base/source/java/ch/systemsx/cisd/base/unix/Unix.java +++ b/lib-base/source/java/ch/systemsx/cisd/base/unix/Unix.java @@ -16,123 +16,319 @@ package ch.systemsx.cisd.base.unix; +import ch.systemsx.cisd.base.exceptions.IOExceptionUnchecked; + +import java.io.BufferedReader; import java.io.File; import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.file.Files; +import java.nio.file.LinkOption; +import java.nio.file.Path; +import java.nio.file.attribute.FileTime; +import java.nio.file.attribute.PosixFileAttributes; +import java.nio.file.attribute.PosixFilePermission; +import java.time.Instant; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; -import ch.rinn.restrictions.Private; -import ch.systemsx.cisd.base.exceptions.CheckedExceptionTunnel; -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. - * <p> - * <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 { + // Make constructor private to make clear is a utility class + private Unix() { - /** - * Method how processes are detected on this host. - * - */ - private enum ProcessDetection + } + + public static boolean isOperational() { + return File.separatorChar == '/'; //On Posix systems the value of this field is '/' + } + + // + // User related methods + // + + private static Integer gid = null; + + public static int getGid() { - /** - * 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 + if (gid == null) + { + try + { + Process process = Runtime.getRuntime().exec("id -g -r"); + BufferedReader reader = + new BufferedReader(new InputStreamReader(process.getInputStream())); + String output = reader.readLine(); + reader.close(); + gid = Integer.parseInt(output); + } catch (IOException e) + { + throw new IOExceptionUnchecked(e); + } + } + return gid; } - private final static boolean operational; - - private final static ProcessDetection processDetection; + private static Integer uid = null; + + public static int getUid() throws IOExceptionUnchecked + { + if (uid == null) + { + try + { + Process process = Runtime.getRuntime().exec("id -u -r"); + BufferedReader reader = + new BufferedReader(new InputStreamReader(process.getInputStream())); + String output = reader.readLine(); + reader.close(); + uid = Integer.parseInt(output); + } catch (IOException e) + { + throw new IOExceptionUnchecked(e); + } + } + return uid; + } - private static volatile boolean useUnixRealtimeTimer = false; + private static Map<String, Integer> uidByUserName = new HashMap<>(); - static + /** + * 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) { - operational = NativeLibraryUtilities.loadNativeLibrary("unix"); - if (operational) + if (userName == null) + { + throw new NullPointerException("userName"); + } + + if (uidByUserName.get(userName) == null) { - init(); - final int myPid = getPid(); - if (isProcessRunningProcFS(myPid)) + try { - processDetection = ProcessDetection.PROCFS; - } else if (isProcessRunningPS(myPid)) + Process process = Runtime.getRuntime().exec("id -u " + userName); + BufferedReader reader = + new BufferedReader(new InputStreamReader(process.getInputStream())); + String output = reader.readLine(); + reader.close(); + int uid = Integer.parseInt(output); + uidByUserName.put(userName, uid); + } catch (IOException e) { - processDetection = ProcessDetection.PS; - } else + throw new IOExceptionUnchecked(e); + } + } + + return uidByUserName.get(userName); + } + + private static Map<String, Integer> gidByGroupName = new HashMap<>(); + + /** + * 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) + { + if (groupName == null) + { + throw new NullPointerException("groupName"); + } + + if (gidByGroupName.get(groupName) == null) + { + try + { + Process process = Runtime.getRuntime().exec("id -g " + groupName); + BufferedReader reader = + new BufferedReader(new InputStreamReader(process.getInputStream())); + String output = reader.readLine(); + reader.close(); + int uid = Integer.parseInt(output); + gidByGroupName.put(groupName, uid); + } catch (IOException e) { - processDetection = ProcessDetection.NONE; + throw new IOExceptionUnchecked(e); } - } else + } + + return gidByGroupName.get(groupName); + } + + private static Integer euid = null; + + public static int getEuid() + { + if (euid == null) { - processDetection = ProcessDetection.NONE; + try + { + Process process = Runtime.getRuntime().exec("id -u"); + BufferedReader reader = + new BufferedReader(new InputStreamReader(process.getInputStream())); + String output = reader.readLine(); + reader.close(); + euid = Integer.parseInt(output); + } catch (IOException e) + { + throw new IOExceptionUnchecked(e); + } } - useUnixRealtimeTimer = Boolean.getBoolean("unix.realtime.timer"); + return euid; + } + + /** + * Returns the effective gid that determines the permissions of this process. + */ + public static final int getEgid() + { + return getGid(); } - /** set user ID on execution */ - public static final short S_ISUID = 04000; + /** + * Sets the owner of <var>fileName</var> to the specified <var>uid</var> and <var>gid</var> values. + * Dereferences a symbolic link. + */ + public static void setOwner(String path, int userId, int groupId) + { + try + { + Files.setAttribute(Path.of(path), "unix:uid", userId); + Files.setAttribute(Path.of(path), "unix:gid", groupId); + } catch (IOException e) + { + throw new IOExceptionUnchecked(e); + } + } - /** set group ID on execution */ - public static final short S_ISGID = 02000; + public static int getUid(String path, boolean followLinks) + { + try + { + if (followLinks) + { + return (int) Files.getAttribute(Path.of(path), "unix:uid"); + } else { + return (int) Files.getAttribute(Path.of(path), "unix:uid", LinkOption.NOFOLLOW_LINKS); + } + } catch (IOException e) + { + throw new IOExceptionUnchecked(e); + } + } - /** sticky bit */ - public static final short S_ISVTX = 01000; + public static int getUid(String path) + { + return getUid(path, true); + } - /** read by owner */ - public static final short S_IRUSR = 00400; + public static int getGid(String path, boolean followLinks) + { + try + { + if (followLinks) + { + return (int) Files.getAttribute(Path.of(path), "unix:gid"); + } else { + return (int) Files.getAttribute(Path.of(path), "unix:gid", LinkOption.NOFOLLOW_LINKS); + } + } catch (IOException e) + { + throw new IOExceptionUnchecked(e); + } + } - /** write by owner */ - public static final short S_IWUSR = 00200; + public static int getGid(String path) + { + return getGid(path, true); + } - /** execute/search by owner */ - public static final short S_IXUSR = 00100; + private static Map<Integer, String> userNameByUid = new HashMap<>(); - /** read by group */ - public static final short S_IRGRP = 00040; + public static String tryGetUserNameForUid(int uid) + { + if (userNameByUid.get(uid) == null) + { + try + { + Process process = Runtime.getRuntime().exec("id -un " + uid); + BufferedReader reader = + new BufferedReader(new InputStreamReader(process.getInputStream())); + String output = reader.readLine(); + reader.close(); + userNameByUid.put(uid, output); + uidByUserName.put(output, uid); + } catch (IOException e) + { + throw new IOExceptionUnchecked(e); + } + } + return userNameByUid.get(uid); + } - /** write by group */ - public static final short S_IWGRP = 00020; + private static Map<Integer, String> groupNameByGid = new HashMap<>(); - /** execute/search by group */ - public static final short S_IXGRP = 00010; + public static String tryGetGroupNameForGid(int gid) + { + if (groupNameByGid.get(gid) == null) + { + try + { + Process process = Runtime.getRuntime().exec("id -gn " + gid); + BufferedReader reader = + new BufferedReader(new InputStreamReader(process.getInputStream())); + String output = reader.readLine(); + reader.close(); + groupNameByGid.put(gid, output); + gidByGroupName.put(output, gid); + } catch (IOException e) + { + throw new IOExceptionUnchecked(e); + } + } + return groupNameByGid.get(gid); + } - /** read by others */ - public static final short S_IROTH = 00004; + public static Time getSystemTime() + { + return Time.getInstance(); + } - /** write by others */ - public static final short S_IWOTH = 00002; + public static String tryReadSymbolicLink(String absolutePath) + { + Stat stat = tryGetLinkInfo(absolutePath); + return stat.isSymbolicLink() ? stat.tryGetSymbolicLink() : null; + } - /** execute/search by others */ - public static final short S_IXOTH = 00001; + // + // File related methods + // /** - * A class to represent a Unix <code>struct timespec</code> that holds a system time in nano-second resolution. + * 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; + public static Time getInstance() { + Instant now = Instant.now(); + return new Time(now); + } + + private Time(Instant now) { + this(now.getEpochSecond(), now.getNano()); + } + + private Time(FileTime fileTime) + { + this(fileTime.toInstant().getEpochSecond(), fileTime.toInstant().getNano()); + } + private Time(long secs, long nanos) { this.secs = secs; @@ -170,7 +366,7 @@ public final class Unix return nanos / 1_000_000; } } - + public long getMillis() { return secs * 1_000 + getMilliSecPart(); @@ -220,121 +416,69 @@ public final class Unix } } - - /** - * A class representing the Unix <code>stat</code> structure. - */ - public static final class Stat - { - private final long deviceId; - private final long inode; + public static class Stat + { + private final Path path; private final short permissions; private final FileLinkType linkType; - private String symbolicLinkOrNull; + private final Time lastModified; - private final int numberOfHardLinks; + private final Time lastAccessed; private final int uid; private final int gid; - private final Time lastAccess; - - private final Time lastModified; - - private final Time lastStatusChange; + private final String symbolicLinkOrNull; private final long size; - private final long numberOfBlocks; - - private final int blockSize; - - 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) + public Stat(Path path, short permissions, FileLinkType linkType, FileTime lastModified, FileTime lastAccessed, int uid, int gid, + String symbolicLinkOrNull, long size) { - this.deviceId = deviceId; - this.inode = inode; + this.path = path; this.permissions = permissions; - this.linkType = FileLinkType.values()[linkType]; - this.numberOfHardLinks = numberOfHardLinks; + this.linkType = linkType; + this.lastModified = new Time(lastModified); + this.lastAccessed = new Time(lastAccessed); this.uid = uid; this.gid = gid; - 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; - } - - void setSymbolicLinkOrNull(String symbolicLinkOrNull) - { this.symbolicLinkOrNull = symbolicLinkOrNull; + this.size = size; } - /** - * 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; - } - - public long getDeviceId() + public short getPermissions() { - return deviceId; + return permissions; } - /** - * Returns the inode. - */ - public long getInode() + public FileLinkType getLinkType() { - return inode; + return linkType; } - public short getPermissions() + public long getLastAccess() { - return permissions; + return lastAccessed.getSecs(); } - public FileLinkType getLinkType() + public Time getLastAccessTime() { - return linkType; + return lastAccessed; } - /** - * Returns <code>true</code>, if this link is a symbolic link. - */ - public final boolean isSymbolicLink() + public long getLastModified() { - return FileLinkType.SYMLINK == linkType; + return lastModified.getSecs(); } - /** - * 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() + public Time getLastModifiedTime() { - return numberOfHardLinks; + return lastModified; } public int getUid() @@ -347,456 +491,306 @@ public final class Unix return gid; } - /** - * 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() + public String tryGetSymbolicLink() { - return lastAccess; + return symbolicLinkOrNull; } - /** - * 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(); + public long getSize() { + return size; } - /** - * 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() + public boolean isSymbolicLink() { - return lastModified; + return symbolicLinkOrNull != null; } /** - * Time when file data last modified. - * <p> - * Changed by the mknod(2), utimes(2) and write(2) system calls. - * - * @return Seconds since the epoch. + * 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 long getLastModified() - { - return lastModified.getSecs(); + public int getNumberOfHardLinks() throws IOException + { + Number count = (Number) Files.getAttribute(path, "unix:nlink", LinkOption.NOFOLLOW_LINKS); + return count.intValue(); + } + } + + private static short getNumericAccessMode(Set<PosixFilePermission> permissions) { + short posixPermissions = 0; + + for (PosixFilePermission permission : permissions) { + switch (permission) { + case OWNER_READ: + posixPermissions |= 0400; + break; + case OWNER_WRITE: + posixPermissions |= 0200; + break; + case OWNER_EXECUTE: + posixPermissions |= 0100; + break; + case GROUP_READ: + posixPermissions |= 0040; + break; + case GROUP_WRITE: + posixPermissions |= 0020; + break; + case GROUP_EXECUTE: + posixPermissions |= 0010; + break; + case OTHERS_READ: + posixPermissions |= 0004; + break; + case OTHERS_WRITE: + posixPermissions |= 0002; + break; + case OTHERS_EXECUTE: + posixPermissions |= 0001; + break; + } } - /** - * 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; - } + return posixPermissions; + } - /** - * 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(); - } + private static Set<PosixFilePermission> getFilePermissionsMode(short permissions) { + Set<PosixFilePermission> posixPermissions = new HashSet<>(); - public long getSize() - { - return size; + if ((permissions & 0400) != 0) { + posixPermissions.add(PosixFilePermission.OWNER_READ); } - - public long getNumberOfBlocks() - { - return numberOfBlocks; + if ((permissions & 0200) != 0) { + posixPermissions.add(PosixFilePermission.OWNER_WRITE); } - - public int getBlockSize() - { - return blockSize; + if ((permissions & 0100) != 0) { + posixPermissions.add(PosixFilePermission.OWNER_EXECUTE); + } + if ((permissions & 0040) != 0) { + posixPermissions.add(PosixFilePermission.GROUP_READ); + } + if ((permissions & 0020) != 0) { + posixPermissions.add(PosixFilePermission.GROUP_WRITE); + } + if ((permissions & 0010) != 0) { + posixPermissions.add(PosixFilePermission.GROUP_EXECUTE); + } + if ((permissions & 0004) != 0) { + posixPermissions.add(PosixFilePermission.OTHERS_READ); + } + if ((permissions & 0002) != 0) { + posixPermissions.add(PosixFilePermission.OTHERS_WRITE); + } + if ((permissions & 0001) != 0) { + posixPermissions.add(PosixFilePermission.OTHERS_EXECUTE); } + return posixPermissions; } /** - * A class representing the Unix <code>group</code> struct. + * Returns the information about <var>linkName</var>. + * + * @throws IOExceptionUnchecked If the information could not be obtained, e.g. because the link does not exist. */ - public static final class Group + public static Stat getLinkInfo(String absolutePath) { - private final String groupName; - - private final String groupPasswordHash; - - private final int gid; + return getLinkInfo(absolutePath, true); + } - private final String[] groupMembers; + /** + * 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. + */ + public static Stat getLinkInfo(String pathAsString, boolean readSymbolicLinkTarget) + { + try { + if (pathAsString == null) + { + throw new NullPointerException("linkName"); + } - Group(String groupName, String groupPasswordHash, int gid, String[] groupMembers) - { - this.groupName = groupName; - this.groupPasswordHash = groupPasswordHash; - this.gid = gid; - this.groupMembers = groupMembers; - } + Path path = Path.of(pathAsString); + if (Files.exists(path, LinkOption.NOFOLLOW_LINKS) == false) + { + return null; + } - public String getGroupName() - { - return groupName; - } - public String getGroupPasswordHash() - { - return groupPasswordHash; - } + PosixFileAttributes attrs = null; + FileLinkType linkType; + short permissions; + int uid; + int gid; + if(readSymbolicLinkTarget && Files.exists(path)) + { + permissions = getNumericAccessMode(Files.getPosixFilePermissions(path)); + attrs = Files.readAttributes(path, PosixFileAttributes.class); + if (Files.isSymbolicLink(path)) { + linkType = FileLinkType.SYMLINK; + } else if (Files.isDirectory(path)) { + linkType = FileLinkType.DIRECTORY; + } else if (Files.isRegularFile(path)) { + linkType = FileLinkType.REGULAR_FILE; + } else { + linkType = FileLinkType.OTHER; + } + uid = getUid(pathAsString); + gid = getGid(pathAsString); + } else { + permissions = getNumericAccessMode(Files.getPosixFilePermissions(path, LinkOption.NOFOLLOW_LINKS)); + attrs = Files.readAttributes(path, PosixFileAttributes.class, LinkOption.NOFOLLOW_LINKS); + if (Files.isSymbolicLink(path)) { + linkType = FileLinkType.SYMLINK; + } else if (Files.isDirectory(path, LinkOption.NOFOLLOW_LINKS)) { + linkType = FileLinkType.DIRECTORY; + } else if (Files.isRegularFile(path, LinkOption.NOFOLLOW_LINKS)) { + linkType = FileLinkType.REGULAR_FILE; + } else { + linkType = FileLinkType.OTHER; + } + uid = getUid(pathAsString, false); + gid = getGid(pathAsString, false); + } - public int getGid() - { - return gid; - } + FileTime lastModified = attrs.lastModifiedTime(); + FileTime lastAccessed = attrs.lastAccessTime(); - public String[] getGroupMembers() + String symbolicLinkOrNull = null; + if (linkType == FileLinkType.SYMLINK && readSymbolicLinkTarget) { + symbolicLinkOrNull = Files.readSymbolicLink(path).toString(); + } + long size = attrs.size(); + return new Stat(path, permissions, linkType, lastModified, lastAccessed, uid, gid, symbolicLinkOrNull, size); + } catch (IOException e) { - return groupMembers; + throw new IOExceptionUnchecked(e); } } /** - * A class representing the Unix <code>passwd</code> struct. + * 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. */ - public static final class Password - { - private final String userName; - - private final String passwordHash; - - private final int uid; - - private final int gid; - - private final String userFullName; - - private final String homeDirectory; - - private final String shell; - - Password(String userName, String passwordHash, int uid, int gid, String userFullName, - String homeDirectory, String shell) - { - this.userName = userName; - this.passwordHash = passwordHash; - this.uid = uid; - this.gid = gid; - this.userFullName = userFullName; - this.homeDirectory = homeDirectory; - this.shell = shell; - } - - public String getUserName() - { - return userName; - } - - public String getPasswordHash() - { - return passwordHash; - } - - public int getUid() - { - return uid; - } - - public int getGid() - { - return gid; - } - - public String getUserFullName() - { - return userFullName; - } - - public String getHomeDirectory() - { - return homeDirectory; - } - - public String getShell() - { - return shell; - } - } - - private static void throwLinkCreationException(String type, String source, String target, - String errorMessage) - { - throw new IOExceptionUnchecked(new IOException(String.format( - "Creating %s link '%s' -> '%s': %s", type, target, source, errorMessage))); - } - - private static void throwStatException(String filename, String errorMessage) - { - throw new IOExceptionUnchecked(new IOException(String.format( - "Cannot obtain inode info for file '%s': %s", filename, errorMessage))); - } - - private static void throwFileException(String operation, String filename, String errorMessage) - { - throw new IOExceptionUnchecked(new IOException(String.format("Cannot %s of file '%s': %s", - 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; + public static Stat tryGetLinkInfo(String pathAsString){ + return getLinkInfo(pathAsString, true); } /** - * 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(); - - private static native int geteuid(); - - private static native int getgid(); - - private static native int getegid(); - - private static native int link(String filename, String linktarget); - - private static native int symlink(String filename, String linktarget); - - private static native Stat stat(String filename); - - private static native Stat lstat(String filename); - - private static native String readlink(String filename, int linkvallen); - - private static native int chmod(String filename, short mode); - - 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); - - private static native int getuid(String user); - - private static native Password getpwnam(String user); - - private static native Password getpwuid(int uid); - - private static native int getgid(String group); - - private static native Group getgrnam(String group); - - private static native Group getgrgid(int gid); - - private static native String strerror(int errnum); - - private static native String strerror(); - - @Private - static boolean isProcessRunningProcFS(int pid) - { - return new File("/proc/" + pid).isDirectory(); - } - - @Private - static boolean isProcessRunningPS(int pid) - { - try - { - return Runtime.getRuntime().exec(new String[] { "ps", "-p", Integer.toString(pid) }).waitFor() == 0; - } catch (IOException ex) - { - return false; - } catch (InterruptedException ex) - { - throw CheckedExceptionTunnel.wrapIfNecessary(ex); - } - } - - // - // Public - // - - /** - * Returns <code>true</code>, if the native library has been loaded successfully and the link utilities are operational, <code>false</code> - * otherwise. + * 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. */ - public static final boolean isOperational() + public static Stat tryGetFileInfo(String absolutePath) { - return operational; + return getFileInfo(absolutePath, true); } /** - * Returns <code>true</code>, if process detection is available on this system. + * Returns the information about <var>fileName</var>. + * + * @throws IOExceptionUnchecked If the information could not be obtained, e.g. because the file does not exist. */ - public static boolean canDetectProcesses() + public static Stat getFileInfo(String pathAsString) { - return processDetection != ProcessDetection.NONE; + return getFileInfo(pathAsString, true); } /** - * 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 information about <var>fileName</var>. + * + * @throws IOExceptionUnchecked If the information could not be obtained, e.g. because the file does not exist. */ - public static String getLastError() + public static Stat getFileInfo(String pathAsString, boolean readSymbolicLinkTarget) + throws IOExceptionUnchecked { - return strerror(); - } + try { + if (pathAsString == null) + { + throw new NullPointerException("linkName"); + } - // - // Process functions - // + Path path = Path.of(pathAsString); + if (Files.exists(path) == false) + { + return null; + } - /** - * Returns the process identifier of the current process. - */ - public static int getPid() - { - return getpid(); - } + short permissions = getNumericAccessMode(Files.getPosixFilePermissions(path)); + PosixFileAttributes attrs = Files.readAttributes(path, PosixFileAttributes.class); + + FileLinkType linkType; + if (attrs.isSymbolicLink()) { + linkType = FileLinkType.SYMLINK; + } else if (attrs.isDirectory()) { + linkType = FileLinkType.DIRECTORY; + } else if (attrs.isRegularFile()) { + linkType = FileLinkType.REGULAR_FILE; + } else { + linkType = FileLinkType.OTHER; + } - /** - * 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) - { - switch (processDetection) + FileTime lastModified = attrs.lastModifiedTime(); + FileTime lastAccessed = attrs.lastAccessTime(); + int uid = getUid(pathAsString); + int gid = getGid(pathAsString); + String symbolicLinkOrNull = null; + if (linkType == FileLinkType.SYMLINK && readSymbolicLinkTarget) { + symbolicLinkOrNull = Files.readSymbolicLink(path).toString(); + } + long size = attrs.size(); + return new Stat(path, permissions, linkType, lastModified, lastAccessed, uid, gid, symbolicLinkOrNull, size); + } catch (IOException e) { - case PROCFS: - return isProcessRunningProcFS(pid); - case PS: - return isProcessRunningPS(pid); - default: - return false; + throw new IOExceptionUnchecked(e); } } - /** - * Returns the uid of the user that started this process. - */ - public static final int getUid() - { - return getuid(); - } - - /** - * Returns the effective uid that determines the permissions of this process. - */ - public static final int getEuid() - { - return geteuid(); + public static Set<PosixFilePermission> getPermissions(String path) throws IOExceptionUnchecked { + try + { + return Files.getPosixFilePermissions(Path.of(path)); + } catch (IOException e) + { + throw new IOExceptionUnchecked(e); + } } - /** - * Returns the gid of the user that started this process. - */ - public static final int getGid() - { - return getgid(); + public static void setAccessMode(String path, Set<PosixFilePermission> permissions) throws IOExceptionUnchecked { + try { + Files.setPosixFilePermissions(Path.of(path), permissions); + } catch (IOException e) { + throw new IOExceptionUnchecked(e); + } } /** - * Returns the effective gid that determines the permissions of this process. + * Sets the access mode of <var>filename</var> to the specified <var>mode</var> value. + * Dereferences a symbolic link. */ - public static final int getEgid() - { - return getegid(); + public static void setAccessMode(String path, short mode) throws IOExceptionUnchecked { + Set<PosixFilePermission> permissions = getFilePermissionsMode(mode); + setAccessMode(path, permissions); } - // - // 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)); + public static void setAccessMode777(String path) throws IOExceptionUnchecked { + try { + Files.setPosixFilePermissions(Path.of(path), Set.of(PosixFilePermission.values())); + } catch (IOException e) { + throw new IOExceptionUnchecked(e); } - 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(); + + public static boolean isSymbolicLink(String absolutePath) { + return Files.isSymbolicLink(Path.of(absolutePath)); } - - // - // File functions - // /** * 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. */ @@ -811,16 +805,12 @@ public final class Unix { throw new NullPointerException("linkName"); } - final int result = link(fileName, linkName); - if (result < 0) - { - throwLinkCreationException("hard", fileName, linkName, strerror(result)); - } + link(fileName, linkName); } /** * 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. */ public static final void createSymbolicLink(String fileName, String linkName) @@ -834,494 +824,34 @@ public final class Unix { throw new NullPointerException("linkName"); } - final int result = symlink(fileName, linkName); - if (result < 0) - { - throwLinkCreationException("symbolic", fileName, linkName, strerror(result)); - } - } - private static Stat tryGetStat(String fileName) throws IOExceptionUnchecked - { - if (fileName == null) - { - throw new NullPointerException("fileName"); - } - return stat(fileName); - } - - private static Stat getStat(String fileName) throws IOExceptionUnchecked - { - if (fileName == null) - { - throw new NullPointerException("fileName"); - } - final Stat result = stat(fileName); - if (result == null) - { - throwStatException(fileName, strerror()); - } - return result; - } - - private static Stat tryGetLStat(String linkName) throws IOExceptionUnchecked - { - if (linkName == null) - { - throw new NullPointerException("linkName"); - } - return lstat(linkName); - } - - private static Stat getLStat(String linkName) throws IOExceptionUnchecked - { - if (linkName == null) - { - throw new NullPointerException("linkName"); - } - final Stat result = lstat(linkName); - if (result == null) - { - throwStatException(linkName, strerror()); - } - return result; - } - - /** - * 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. - * - * @deprecated Use method {@link Stat#getInode(String)} from {@link #getLinkInfo(String)} instead. - */ - @Deprecated - public static final long getInode(String linkName) throws IOExceptionUnchecked - { - return getLStat(linkName).getInode(); + symlink(fileName, linkName); } - /** - * 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. - * - * @deprecated Use method {@link Stat#getNumberOfHardLinks(String)} from {@link #getLinkInfo(String)} instead. + /* + * This method manages symbolic link creation using NIO API. */ - @Deprecated - public static final int getNumberOfHardLinks(String linkName) throws IOExceptionUnchecked - { - return getLStat(linkName).getNumberOfHardLinks(); - } - - /** - * 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. - */ - public static final boolean isSymbolicLink(String linkName) throws IOExceptionUnchecked - { - 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. - * - * @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 - { - final Stat stat = getLStat(linkName); - return stat.isSymbolicLink() ? readlink(linkName, (int) stat.getSize()) : null; - } - - /** - * Returns the information about <var>fileName</var>. - * - * @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 - { - return getStat(fileName); - } - - /** - * 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 - { - return tryGetStat(fileName); - } - - /** - * Returns the information about <var>linkName</var>. - * - * @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 - { - return getLinkInfo(linkName, true); - } - - /** - * 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. - */ - public static final Stat getLinkInfo(String linkName, boolean readSymbolicLinkTarget) - throws IOExceptionUnchecked - { - final Stat stat = getLStat(linkName); - final String symbolicLinkOrNull = - (readSymbolicLinkTarget && stat.isSymbolicLink()) ? readlink(linkName, - (int) stat.getSize()) : null; - stat.setSymbolicLinkOrNull(symbolicLinkOrNull); - return stat; - } - - /** - * 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 - { - return tryGetLinkInfo(linkName, true); - } - - /** - * 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 - { - final Stat stat = tryGetLStat(linkName); - if (stat == null) - { - return null; - } - final String symbolicLinkOrNull = - (readSymbolicLinkTarget && stat.isSymbolicLink()) ? readlink(linkName, - (int) stat.getSize()) : null; - stat.setSymbolicLinkOrNull(symbolicLinkOrNull); - return stat; - } - - /** - * 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 - { - if (fileName == null) - { - throw new NullPointerException("fileName"); - } - final int result = chmod(fileName, mode); - if (result < 0) - { - throwFileException("set mode", fileName, strerror(result)); - } - } - - /** - * 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 - { - if (fileName == null) - { - throw new NullPointerException("fileName"); - } - final int result = chown(fileName, uid, gid); - if (result < 0) - { - throwFileException("set owner", fileName, strerror(result)); - } - } - - /** - * 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)); + public static final void symlink(String fileName, String linkName) throws IOExceptionUnchecked { + try { + Path file = Path.of(fileName); + Path link = Path.of(linkName); + Files.createSymbolicLink(link, file);// Creates the link + } catch (IOException exception) { + throw new IOExceptionUnchecked(exception); } } - /** - * 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. + /* + * This method manages link creation using NIO API. */ - 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)); + public static final void link(String fileName, String linkName) throws IOExceptionUnchecked { + try { + Path file = Path.of(fileName); + Path link = Path.of(linkName); + Files.createLink(link, file); // Creates the link + } catch (IOException exception) { + throw new IOExceptionUnchecked(exception); } } - /** - * 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 - // - - /** - * Returns the name of the user identified by <var>uid</var>. - */ - public static final String tryGetUserNameForUid(int uid) - { - return getuser(uid); - } - - /** - * 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) - { - if (userName == null) - { - throw new NullPointerException("userName"); - } - return getuid(userName); - } - - /** - * 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) - { - if (userName == null) - { - throw new NullPointerException("userName"); - } - return getpwnam(userName); - } - - /** - * 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) - { - return getpwuid(uid); - } - - // - // Group functions - // - - /** - * 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) - { - return getgroup(gid); - } - - /** - * 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) - { - if (groupName == null) - { - throw new NullPointerException("groupName"); - } - return getgid(groupName); - } - - /** - * 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) - { - if (groupName == null) - { - throw new NullPointerException("groupName"); - } - return getgrnam(groupName); - } - - /** - * 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) - { - return getgrgid(gid); - } - - // - // Error - // - - /** - * Returns the error string for the given <var>errnum</var>. - */ - public static final String getErrorString(int errnum) - { - return strerror(errnum); - } - } diff --git a/lib-base/sourceTest/java/ch/systemsx/cisd/base/unix/UnixRootTests.java b/lib-base/sourceTest/java/ch/systemsx/cisd/base/unix/UnixRootTests.java deleted file mode 100644 index a122ca813fa..00000000000 --- a/lib-base/sourceTest/java/ch/systemsx/cisd/base/unix/UnixRootTests.java +++ /dev/null @@ -1,108 +0,0 @@ -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(); - } - } - -} diff --git a/lib-base/sourceTest/java/ch/systemsx/cisd/base/unix/UnixTests.java b/lib-base/sourceTest/java/ch/systemsx/cisd/base/unix/UnixTests.java index 324c1fc59f6..9520db6a074 100644 --- a/lib-base/sourceTest/java/ch/systemsx/cisd/base/unix/UnixTests.java +++ b/lib-base/sourceTest/java/ch/systemsx/cisd/base/unix/UnixTests.java @@ -16,28 +16,21 @@ package ch.systemsx.cisd.base.unix; -import static org.testng.Assert.assertNotEquals; +import ch.rinn.restrictions.Friend; +import ch.systemsx.cisd.base.tests.AbstractFileSystemTestCase; +import org.apache.commons.io.FileUtils; +import org.testng.annotations.Test; 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.rinn.restrictions.Friend; -import ch.systemsx.cisd.base.BuildAndEnvironmentInfo; -import ch.systemsx.cisd.base.tests.AbstractFileSystemTestCase; -import ch.systemsx.cisd.base.unix.Unix.Group; -import ch.systemsx.cisd.base.unix.Unix.Password; -import ch.systemsx.cisd.base.unix.Unix.Stat; +import static ch.systemsx.cisd.base.unix.Unix.Stat; /** * Test cases for the {@link Unix} system calls. - * - * @author Bernd Rinn + * + * @author Juan Fuentes */ @Friend(toClasses = Unix.class) public class UnixTests extends AbstractFileSystemTestCase @@ -52,8 +45,7 @@ public class UnixTests extends AbstractFileSystemTestCase super(cleanAfterMethod); } - @Test(groups = - { "requires_unix" }) + @Test public void testGetLinkInfoRegularFile() throws IOException { final short accessMode = (short) 0777; @@ -72,15 +64,13 @@ public class UnixTests extends AbstractFileSystemTestCase assertEquals(f.lastModified()/1000, info.getLastModified()); } - @Test(groups = - { "requires_unix" }, expectedExceptions = NullPointerException.class) + @Test(expectedExceptions = NullPointerException.class) public void testGetLinkNull() throws IOException { Unix.getLinkInfo(null); } - @Test(groups = - { "requires_unix" }) + @Test public void testGetLinkInfoDirectory() throws IOException { final File d = new File(workingDirectory, "someDir"); @@ -91,8 +81,7 @@ public class UnixTests extends AbstractFileSystemTestCase assertFalse(info.isSymbolicLink()); } - @Test(groups = - { "requires_unix" }) + @Test public void testGetLinkInfoSymLink() throws IOException { final File f = new File(workingDirectory, "someOtherFile"); @@ -116,126 +105,7 @@ 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" }) + @Test public void testGetLinkInfoSymLinkDanglingLink() throws IOException { final File s = new File(workingDirectory, "someDanglingLink"); @@ -247,38 +117,34 @@ public class UnixTests extends AbstractFileSystemTestCase assertTrue(info.isSymbolicLink()); final Stat info2 = Unix.tryGetFileInfo(s.getAbsolutePath()); assertNull(info2); - assertEquals("No such file or directory", Unix.getLastError()); + // assertEquals("No such file or directory", Unix.getLastError()); } - @Test(groups = - { "requires_unix" }) + @Test public void testGetLinkInfoNonExistent() throws IOException { final File s = new File(workingDirectory, "nonExistent"); final Stat info = Unix.tryGetLinkInfo(s.getAbsolutePath()); assertNull(info); - assertEquals("No such file or directory", Unix.getLastError()); + // assertEquals("No such file or directory", Unix.getLastError()); final Stat info2 = Unix.tryGetFileInfo(s.getAbsolutePath()); assertNull(info2); - assertEquals("No such file or directory", Unix.getLastError()); + // assertEquals("No such file or directory", Unix.getLastError()); } - @Test(groups = - { "requires_unix" }, expectedExceptions = NullPointerException.class) + @Test(expectedExceptions = NullPointerException.class) public void testCreateSymbolicLinkNull() throws IOException { Unix.createSymbolicLink(null, null); } - @Test(groups = - { "requires_unix" }, expectedExceptions = NullPointerException.class) + @Test(expectedExceptions = NullPointerException.class) public void testCreateHardLinkNull() throws IOException { Unix.createHardLink(null, null); } - @Test(groups = - { "requires_unix" }) + @Test public void testGetLinkInfoHardLink() throws IOException { final File f = new File(workingDirectory, "someOtherFile"); @@ -292,52 +158,45 @@ public class UnixTests extends AbstractFileSystemTestCase assertNull(info.tryGetSymbolicLink()); } - @Test(groups = - { "requires_unix" }) + @Test public void testGetUid() { assertTrue(Unix.getUid() >= 0); } - @Test(groups = - { "requires_unix" }) + @Test public void testGetEuid() { assertTrue(Unix.getEuid() >= 0); assertEquals(Unix.getUid(), Unix.getEuid()); } - @Test(groups = - { "requires_unix" }) + @Test public void testGetGid() { assertTrue(Unix.getGid() >= 0); } - @Test(groups = - { "requires_unix" }) + @Test public void testGetEgid() { assertTrue(Unix.getEgid() >= 0); assertEquals(Unix.getGid(), Unix.getEgid()); } - @Test(groups = - { "requires_unix" }) + @Test public void testGetUidForUserName() { assertEquals(0, Unix.getUidForUserName("root")); } - @Test(groups = - { "requires_unix" }, expectedExceptions = NullPointerException.class) + @Test(expectedExceptions = NullPointerException.class) public void testGetUidForUserNameNull() throws IOException { Unix.getUidForUserName(null); } - @Test(groups = - { "requires_unix" }) + @Test public void testGetGidForGroupName() { final String rootGroup = Unix.tryGetGroupNameForGid(0); @@ -345,154 +204,9 @@ public class UnixTests extends AbstractFileSystemTestCase assertEquals(0, Unix.getGidForGroupName(rootGroup)); } - @Test(groups = - { "requires_unix" }, expectedExceptions = NullPointerException.class) + @Test(expectedExceptions = NullPointerException.class) public void testGetGidForGroupNameNull() throws IOException { Unix.getGidForGroupName(null); } - - @Test(groups = - { "requires_unix" }) - public void testTryGetGroupByName() - { - final String rootGroup = Unix.tryGetGroupNameForGid(0); - final Group group = Unix.tryGetGroupByName(rootGroup); - assertNotNull(group); - assertEquals(rootGroup, group.getGroupName()); - assertEquals(0, group.getGid()); - assertNotNull(group.getGroupMembers()); - } - - @Test(groups = - { "requires_unix" }, expectedExceptions = NullPointerException.class) - public void testTryGetGroupByNameNull() throws IOException - { - Unix.tryGetGroupByName(null); - } - - @Test(groups = - { "requires_unix" }) - public void testTryGetGroupByGid() - { - final Group group = Unix.tryGetGroupByGid(0); - assertNotNull(group); - final String rootGroup = group.getGroupName(); - assertTrue(rootGroup, "root".equals(rootGroup) || "wheel".equals(rootGroup)); - assertEquals(0, group.getGid()); - assertNotNull(group.getGroupMembers()); - } - - @Test(groups = - { "requires_unix" }) - public void testTryGetUserByName() - { - final Password user = Unix.tryGetUserByName("root"); - assertNotNull(user); - assertEquals("root", user.getUserName()); - assertEquals(0, user.getUid()); - assertEquals(0, user.getGid()); - assertNotNull(user.getUserFullName()); - assertNotNull(user.getHomeDirectory()); - assertNotNull(user.getShell()); - assertTrue(user.getShell().startsWith("/")); - } - - @Test(groups = - { "requires_unix" }, expectedExceptions = NullPointerException.class) - public void testTryGetUserByNameNull() throws IOException - { - Unix.tryGetUserByName(null); - } - - @Test(groups = - { "requires_unix" }) - public void testTryGetUserByUid() - { - final Password user = Unix.tryGetUserByUid(0); - assertNotNull(user); - assertEquals("root", user.getUserName()); - assertEquals(0, user.getUid()); - assertEquals(0, user.getGid()); - assertNotNull(user.getUserFullName()); - assertNotNull(user.getHomeDirectory()); - assertNotNull(user.getShell()); - assertTrue(user.getShell().startsWith("/")); - } - - @Test(groups = - { "requires_unix" }) - public void testDetectProcess() - { - assertTrue(Unix.canDetectProcesses()); - assertTrue(Unix.isProcessRunningPS(Unix.getPid())); - } - - public static void main(String[] args) throws Throwable - { - System.out.println(BuildAndEnvironmentInfo.INSTANCE); - System.out.println("Test class: " + UnixTests.class.getSimpleName()); - System.out.println(); - if (Unix.isOperational() == false) - { - 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 - { - for (Method m : UnixTests.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) - { - ++failed; - System.out.println("Caught exception in method " + m.getName()); - th.printStackTrace(); - if (stopOnError) - { - System.exit(1); - } - } - } - } - if (failed == 0) - { - System.out.println("Tests OK!"); - } else - { - System.out.printf("%d tests FAILED!\n", failed); - } - } finally - { - if (failed == 0) - { - test.afterClass(); - } - } - } - } diff --git a/lib-commonbase/source/java/ch/systemsx/cisd/common/io/Posix.java b/lib-commonbase/source/java/ch/systemsx/cisd/common/io/Posix.java index 248a13f7478..3a955314b0d 100644 --- a/lib-commonbase/source/java/ch/systemsx/cisd/common/io/Posix.java +++ b/lib-commonbase/source/java/ch/systemsx/cisd/common/io/Posix.java @@ -26,9 +26,10 @@ import java.io.InputStreamReader; import java.nio.file.Files; import java.nio.file.LinkOption; import java.nio.file.Path; -import java.nio.file.attribute.*; +import java.nio.file.attribute.FileTime; +import java.nio.file.attribute.PosixFileAttributes; +import java.nio.file.attribute.PosixFilePermission; import java.time.Instant; -import java.time.temporal.ChronoUnit; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -302,72 +303,6 @@ public final class Posix return stat.isSymbolicLink() ? stat.tryGetSymbolicLink() : null; } -// /** -// * 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) -// { -// try -// { -// Instant accessTimeInstant = Instant.ofEpochSecond(accessTimeSecs).plus(accessTimeMicroSecs, ChronoUnit.MICROS); -// FileTime accessTime = FileTime.from(accessTimeInstant); -// Instant modifiedTimeInstant = Instant.ofEpochSecond(modificationTimeSecs).plus(modificationTimeMicroSecs, ChronoUnit.MICROS); -// FileTime modifiedTime = FileTime.from(modifiedTimeInstant); -// Files.getFileAttributeView(Path.of(fileName), PosixFileAttributeView.class, LinkOption.NOFOLLOW_LINKS).setTimes(modifiedTime, accessTime, null); -// Files.getFileAttributeView(Path.of(fileName), PosixFileAttributeView.class).setTimes(modifiedTime, accessTime, null); -// } catch (IOException e) -// { -// throw new IOExceptionUnchecked(e); -// } -// } -// -// /** -// * 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 -// { -// Time time = Time.getInstance(); -// setLinkTimestamps(fileName, time.getSecs(), time.getMicroSecPart(), time.getSecs(), time.getMicroSecPart()); -// } -// -// /** -// * 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 -// { -// try -// { -// Instant accessTimeInstant = Instant.ofEpochSecond(accessTimeSecs).plus(accessTimeMicroSecs, ChronoUnit.MICROS); -// FileTime accessTime = FileTime.from(accessTimeInstant); -// Instant modifiedTimeInstant = Instant.ofEpochSecond(modificationTimeSecs).plus(modificationTimeMicroSecs, ChronoUnit.MICROS); -// FileTime modifiedTime = FileTime.from(modifiedTimeInstant); -// Files.getFileAttributeView(Path.of(fileName), PosixFileAttributeView.class).setTimes(modifiedTime, accessTime, null); -// } catch (IOException e) -// { -// throw new IOExceptionUnchecked(e); -// } -// } - // // File related methods // diff --git a/lib-commonbase/sourceTest/java/ch/systemsx/cisd/common/io/PosixTest.java b/lib-commonbase/sourceTest/java/ch/systemsx/cisd/common/io/PosixTest.java index f22ecb6e7ee..ee1bf76c81a 100644 --- a/lib-commonbase/sourceTest/java/ch/systemsx/cisd/common/io/PosixTest.java +++ b/lib-commonbase/sourceTest/java/ch/systemsx/cisd/common/io/PosixTest.java @@ -17,7 +17,6 @@ package ch.systemsx.cisd.common.io; import ch.rinn.restrictions.Friend; -import ch.systemsx.cisd.base.BuildAndEnvironmentInfo; import ch.systemsx.cisd.base.tests.AbstractFileSystemTestCase; import ch.systemsx.cisd.base.unix.FileLinkType; import org.apache.commons.io.FileUtils; @@ -27,7 +26,6 @@ import java.io.File; import java.io.IOException; import java.nio.charset.Charset; -import static org.testng.Assert.assertNotEquals; import static ch.systemsx.cisd.common.io.Posix.Stat; /** @@ -108,121 +106,6 @@ public class PosixTest extends AbstractFileSystemTestCase assertNull(info2.tryGetSymbolicLink()); } -// @Test -// 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; -// } -//// Posix.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"); -// Posix.createSymbolicLink(f.getAbsolutePath(), s.getAbsolutePath()); -// final Stat info = Posix.getLinkInfo(s.getAbsolutePath()); -// assertEquals(1, info.getNumberOfHardLinks()); -// assertEquals(FileLinkType.SYMLINK, info.getLinkType()); -// assertTrue(info.isSymbolicLink()); -// assertEquals(f.getAbsolutePath(), info.tryGetSymbolicLink()); -// assertEquals(f.getAbsolutePath(), Posix.tryReadSymbolicLink(s.getAbsolutePath())); -// assertNull(Posix.getLinkInfo(s.getAbsolutePath(), false).tryGetSymbolicLink()); -// final long lastMicros = info.getLastModifiedTime().getMicroSecPart(); -// final long newLastModifiedLink = info.getLastModifiedTime().getSecs() - 24 * 3600; -// Posix.setLinkTimestamps(s.getAbsolutePath(), newLastModifiedLink, lastMicros, newLastModifiedLink, lastMicros); -// -// final long newLastModifiedFile = info.getLastModifiedTime().getSecs() - 2 * 24 * 3600; -// Posix.setFileTimestamps(f.getAbsolutePath(), newLastModifiedFile, lastMicros, newLastModifiedFile, lastMicros); -// -// final Stat info2l = Posix.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 = Posix.getFileInfo(s.getAbsolutePath()); -// final Stat info2f2 = Posix.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 Posix.Time now1 = Posix.getSystemTime(); -// assertNotEquals(0, now1.getNanoSecPart() % 1_000); -// Posix.setLinkTimestamps(s.getAbsolutePath()); -// final Posix.Time now2 = Posix.getSystemTime(); -// final Stat info3 = Posix.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 -// public void testTouchSymLinkAndFile() throws IOException, InterruptedException -// { -//// Posix.setUseUnixRealtimeTimer(false); -// final File someFile = new File(workingDirectory, "someOtherFile"); -// final String content = "someMoreText\n"; -// FileUtils.writeStringToFile(someFile, content, Charset.defaultCharset()); -// final File someSymlink = new File(workingDirectory, "someLink"); -// Posix.createSymbolicLink(someFile.getAbsolutePath(), someSymlink.getAbsolutePath()); -// final Stat infoSymlink = Posix.getLinkInfo(someSymlink.getAbsolutePath()); -// assertEquals(1, infoSymlink.getNumberOfHardLinks()); -// assertEquals(FileLinkType.SYMLINK, infoSymlink.getLinkType()); -// assertTrue(infoSymlink.isSymbolicLink()); -// assertEquals(someFile.getAbsolutePath(), infoSymlink.tryGetSymbolicLink()); -// assertEquals(someFile.getAbsolutePath(), Posix.tryReadSymbolicLink(someSymlink.getAbsolutePath())); -// assertNull(Posix.getLinkInfo(someSymlink.getAbsolutePath(), false).tryGetSymbolicLink()); -// final long newLastModifiedLinkMicros = infoSymlink.getLastModifiedTime().getMicroSecPart(); -// final long newLastModifiedLinkSec = infoSymlink.getLastModifiedTime().getSecs() - 24 * 3600; -// Posix.setLinkTimestamps(someSymlink.getAbsolutePath(), newLastModifiedLinkSec, newLastModifiedLinkMicros, newLastModifiedLinkSec, newLastModifiedLinkMicros); -// -// final long newLastModifiedSecFile = infoSymlink.getLastModifiedTime().getSecs() - 2 * 24 * 3600; -// Posix.setFileTimestamps(someFile.getAbsolutePath(), newLastModifiedSecFile, newLastModifiedLinkMicros, newLastModifiedSecFile, newLastModifiedLinkMicros); -// -// final Stat infoSymlink2 = Posix.getLinkInfo(someSymlink.getAbsolutePath(), false); -// assertEquals(newLastModifiedLinkSec, infoSymlink2.getLastModifiedTime().getSecs()); -// assertEquals(newLastModifiedLinkMicros, infoSymlink2.getLastModifiedTime().getMicroSecPart()); -// assertEquals(newLastModifiedLinkSec, infoSymlink2.getLastAccessTime().getSecs()); -// assertEquals(newLastModifiedLinkMicros, infoSymlink2.getLastAccessTime().getMicroSecPart()); -// -// final Stat info2f = Posix.getFileInfo(someSymlink.getAbsolutePath()); -// final Stat info2f2 = Posix.getLinkInfo(someFile.getAbsolutePath()); -// assertNotEquals(infoSymlink2.getLastModifiedTime(), info2f2.getLastModifiedTime()); -// assertEquals(info2f2.getLastModifiedTime(), info2f.getLastModifiedTime()); -// assertEquals(newLastModifiedSecFile, info2f.getLastModifiedTime().getSecs()); -// assertEquals(newLastModifiedLinkMicros, info2f.getLastModifiedTime().getMicroSecPart()); -// assertEquals(newLastModifiedSecFile, info2f.getLastAccessTime().getSecs()); -// assertEquals(newLastModifiedLinkMicros, info2f.getLastAccessTime().getMicroSecPart()); -// -// -// Thread.sleep(10); -// -// final Posix.Time now1 = Posix.getSystemTime(); -// assertEquals(0, now1.getNanoSecPart() % 1_000); -// Posix.setLinkTimestamps(someSymlink.getAbsolutePath()); // Modifies the link, not the linked file -// final Posix.Time now2 = Posix.getSystemTime(); -// final Stat info3 = Posix.getLinkInfo(someSymlink.getAbsolutePath()); // Returns the linked file info -// -// assertTrue(now1.getSecs() <= info3.getLastModified() && info3.getLastModified() <= now2.getSecs()); -// assertTrue(now1.getMicroSecPart() <= info3.getLastModifiedTime().getMicroSecPart() && infoSymlink.getLastModifiedTime().getMilliSecPart() <= now2.getMicroSecPart()); -// assertTrue(now1.getSecs() <= info3.getLastAccess() && info3.getLastAccess() <= now2.getSecs()); -// assertTrue(now1.getMicroSecPart() <= info3.getLastAccessTime().getMicroSecPart() && infoSymlink.getLastAccessTime().getMilliSecPart() <= now2.getMicroSecPart()); -// assertNotEquals(newLastModifiedLinkMicros, info3.getLastModifiedTime().getMicroSecPart()); -// assertNotEquals(newLastModifiedLinkMicros, info3.getLastAccessTime().getMicroSecPart()); -// } - @Test public void testGetLinkInfoSymLinkDanglingLink() throws IOException { -- GitLab