7

Im on Linux and my Java application is not intended to be portable.

I'm looking for a way to identify a file uniquely in Java. I can make use of statfs syscall since the pair (f_fsid, ino) uniquely identifies a file (not only across a file system) as specified here: http://man7.org/linux/man-pages/man2/statfs.2.html

The question is if it is possible extract fsid from Java directly so I can avoid writing JNI function?

inode can be extracted with NIO, but how about fsid? inode and fsid comes from different structure and are operated by different syscalls...

4
  • Pardon my ignorance, but wouldn't a file system path (e.g. /home/user/file.txt) identify the file? Commented Dec 26, 2018 at 18:23
  • 1
    @KarolDoabecki Unfortunately identifying simply by file path are not tolerable to renaming and is prone to race conditions in case we are operating on files concurrently. Commented Dec 26, 2018 at 18:24
  • 2
    @KarolDowbecki not in the case of a symlink Commented Dec 26, 2018 at 18:25
  • 1
    if (and this is a big if) you need to go the native route and depending on your performance requirements I would suggest using JNA over JNI because JNA doesn't require that you write a native support library. I was surprised by how easy it was to use JNA. github.com/java-native-access/jna Commented Dec 26, 2018 at 18:40

2 Answers 2

4

This java example demonstrates how to get the unix inode number of a file.

import java.nio.file.*;
import java.nio.file.attribute.*;

public class MyFile {

  public static void main(String[] args) throws Exception  {

    BasicFileAttributes attr = null;
    Path path = Paths.get("MyFile.java");

    attr = Files.readAttributes(path, BasicFileAttributes.class);

    Object fileKey = attr.fileKey();
    String s = fileKey.toString();
    String inode = s.substring(s.indexOf("ino=") + 4, s.indexOf(")"));
    System.out.println("Inode: " + inode);
  }
}

The output

$ java MyFile
Inode: 664938

$ ls -i MyFile.java 
664938 MyFile.java

credit where credit is due: https://www.javacodex.com/More-Examples/1/8

Sign up to request clarification or add additional context in comments.

8 Comments

If we are operating across the same file system it seems to work fine. But the inode of two files can be the same (even unlikely) if they are in some different directories which are on different file systems... cant they?
Or this inode includes fsid as well...?
@SomeName How about the FileStore which you can access via Files.getFileStore? docs.oracle.com/javase/8/docs/api/java/nio/file/FileStore.html docs.oracle.com/javase/8/docs/api/java/nio/file/…
Looks like this is exactly what I need. Thanks!
@SomeName it’s not really clear at which point using Java code or using native code really is required. Java NIO has a way to uniquely identify files (the object returned by fileKey() does that) and it also has a watch service abstraction. Note that the code of the answer goes great lengths to destroy the uniqueness of the file key. It first converts it to a String, then extracts the not-unique inode from it. If you look at the original string representation, you’ll see something like "(dev=xxx,inode=yyy)", clearly hinting at the fact that the key object does uniquely identify the file.
|
2

I would suggest the GIT method of hashing the file contents. This is proof against copying and renaming.

Java is supposed to be platform independent so using Unix specific methods may not be what you want.

2 Comments

This is the exact solution Im currently using... But unfortunately it was proven to not has enough flexibility we need.
@Some Name could you please elaborate?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.