1

So, I'm attempting to call the Linux C - stat function.

My JNA code:

    public int stat(bap path, bap statdump);

the bap class:

public static class bap extends Structure {

    public byte[] array;

    public bap(int size) {
        array = new byte[size];
    }

    @Override
    protected List getFieldOrder() {
        return Arrays.asList(new String[]{"array"});
    }

}

Which, while nasty, performs as a byte array pointer for many other functions successfully. What I think the problem is, is here: int stat(const char *restrict path, struct stat *restrict buf);, as defined by http://linux.die.net/man/3/stat

How do I pass a constant char array, and what does the *restrict mean? I attempted to google, but I don't think it liked * in the search query, as nothing was relevant.

EDIT: full exception

Exception in thread "main" java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:      43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:58)
Caused by: java.lang.UnsatisfiedLinkError: Error looking up function 'stat': java: undefined       symbol: stat
    at com.sun.jna.Function.<init>(Function.java:208)
    at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:536)
    at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:513)
    at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:499)
    at com.sun.jna.Library$Handler.invoke(Library.java:199)
    at com.sun.proxy.$Proxy0.stat(Unknown Source)
JavaProphet
  • 931
  • 14
  • 29
  • 1
    [`restrict`](http://en.wikipedia.org/wiki/Restrict) is a hint to the C compiler, so you can ignore it for purposes of JNA function mappings. – technomage Apr 26 '15 at 11:25

2 Answers2

2

Have you looked at sys/stat.h to see if there's an actual declaration for stat() or if it's a C preprocessor macro?

In the link above, stat will actually be stat64 if __USE_FILE_OFFSET64 is defined.

To see if this is your problem, simply change the function name from stat to stat64.

As a more permanent solution supply a function mapper to your library load.

The following example first looks up the base label, then tries again after appending "64":

FunctionMapper mapper = new FunctionMapper() {
    public String getFunctionName(NativeLibrary library, java.lang.reflect.Method method) {
        String name = method.getName();
        try {
            library.getFunction(name);
        } catch(UnsatisfiedLinkError e) {
            try {
                library.getFunction(name + "64");
                return name + "64";
            } catch(UnsatisfiedLinkError e) {
                 // If neither variant worked, report failure on the base label
            }
        }
        return name;
    }
};
Map options = new HashMap() {
    { put(Library.OPTION_FUNCTION_MAPPER, mapper); }
};
library = Native.loadLibrary("c", options);
technomage
  • 9,861
  • 2
  • 26
  • 40
0

It's also possible that stat function just don't exists on your installed libc version, as it happened to me.

stat function is not present on Debian 11.6 using GLIBC 2.31 but it is at Ubuntu 22.04 which is using GLIBC 2.35.

libc stat function is just a wrapper to syscall 4 though, so you can use the following code to call stat using syscall function

public interface Libc extends Library {

  Stats INSTANCE = Native.loadLibrary(Platform.C_LIBRARY_NAME, Libc.class);

  default int stat0(String pathname, Stat statbuf){
    return this.syscall(4, pathname, statbuf);
  }

  int syscall(int number, Object... args);

}

Complete code is hosted here, if you're interested

Debug

Debian 11.6

$ strings /lib/x86_64-linux-gnu/libc.so.6  | grep 'GNU C Library'
GNU C Library (Debian GLIBC 2.31-13+deb11u5) stable release version 2.31.

$ nm -D /lib/x86_64-linux-gnu/libc.so.6  | grep ' stat'
00000000000ec1c0 W statfs@@GLIBC_2.2.5
00000000000ec1c0 W statfs64@@GLIBC_2.2.5
00000000000ec220 W statvfs@@GLIBC_2.2.5
00000000000ec220 W statvfs64@@GLIBC_2.2.5
00000000000ec040 T statx@@GLIBC_2.28

Ubuntu 22.02

$ strings /lib/x86_64-linux-gnu/libc.so.6  | grep 'GNU C Library'
GNU C Library (Ubuntu GLIBC 2.35-0ubuntu3.1) stable release version 2.35.


$ nm -D /lib/x86_64-linux-gnu/libc.so.6  | grep ' stat'
0000000000113e60 W stat@@GLIBC_2.33
0000000000113e60 W stat64@@GLIBC_2.33
00000000001142b0 W statfs@@GLIBC_2.2.5
00000000001142b0 W statfs64@@GLIBC_2.2.5
0000000000114310 W statvfs@@GLIBC_2.2.5
0000000000114310 W statvfs64@@GLIBC_2.2.5
00000000001141e0 T statx@@GLIBC_2.28
deFreitas
  • 4,196
  • 2
  • 33
  • 43