从Java中的FileDescriptor获取路径



我的问题的一些快速背景:

我正在编写一个编译器,将域类型强制规范转换为Java安全管理器代码。简而言之,DTE定义"类型"(对象),为这些类型分配路径;然后定义"域"(subject),并定义域对各种类型的权限(rwxdc)。我需要在JSM中尽可能地模仿这种行为。

目前我正在研究写权限。我已经成功地重写了JSM的checkWrite(字符串文件名)方法。列表中的下一个是checkWrite(FileDescriptor文件描述符),而这一个更为棘手。由于定义DTE的方式,我需要路径信息来确定是否允许写入操作。

  • 是否可以从FileDescriptor中提取路径数据?我猜不会——我已经查看了文档和各种教程,没有发现任何迹象表明我有任何方法可以获得这些信息(不过,我很高兴被证明是错误的;这会让我的工作更容易)。

  • 如果上面的答案是否定的,有人能提出一个可行的解决方案吗?例如,有没有什么方法可以让我编写本机代码来做我想做的事情,并将其绑定到我的自定义JSM类中?我可以做那种"高级"的事情,但我需要一些如何开始的想法。

  • 或者我的唯一选项基本上是拒绝使用FileDescriptor的所有写入权限?我很想避免这种情况,因为这是一个糟糕的解决方案,但如果这是现实,我需要知道。

非常感谢您抽出时间。

简短的回答是否定的,因为文件独立于用于访问该文件的路径(至少在任何重要的操作系统上)。

一种可能的解决方案是使用方面框架捕获打开文件的调用,并将引用的文件描述符放入WeakHashMap<FileDescriptor,File>中。然后,只要您需要验证写入,就可以简单地查看此映射。

希望不会被反射限制阻止,但现在你可以使用这个(代码基于另一个答案),从Android O:开始

val file = File(filesDir, "ff")
file.parentFile!!.mkdirs()
val fileOutputStream = FileOutputStream(file)
val fd = fileOutputStream.fd
val method = fd.javaClass.getMethod("getInt$")
val fdId = method.invoke(fd)
val path = Paths.get("/proc/self/fd/$fdId")
val filePath = Files.readSymbolicLink(path)
Log.d("AppLog", "filePath:$filePath")

但不确定FileChannel。它的实现文件("FileChannelImpl")应该具有;路径";(文件路径字符串类型)和";fd";是FileDescriptor,但两者都通过反射隐藏

从java:中的FileDescriptor获取路径的解决方案

工作原理:

我们知道文件描述符包含描述符id,用于定位当前进程中打开的文件。

什么是文件描述符,用简单的术语解释?

如果我们知道描述符id,那么我们可以通过以下java代码很容易地找到文件路径:

Path path = Paths.get("/proc/self/fd/"+fd_id);
System.out.println(Files.readSymbolicLink(path)); //return file path in file descriptor

此处:

fd_id文件描述符id(0,1,2…..)

/proc其a目录包含在系统中运行的所有进程

/自当前运行的java类进程id

/fd文件描述符目录

//fd_id文件描述符id

SafeFileDescriptor.java

import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Paths;
import java.nio.file.Files;
import java.nio.file.Path;  
public class SafeFileDescriptor {
 static {
    System.load("Documents/java native interface exmples/libSafeFileDescriptor.so");
}
private native int getFDid(FileDescriptor fd);
public static void main(String[] args) throws IOException{  
    FileOutputStream fout = new FileOutputStream("Documents/test.txt");
    FileDescriptor fd=fout.getFD();
    int fd_id = new SafeFileDescriptor().getFDid(fd);
    Path path = Paths.get("/proc/self/fd/"+fd_id);
    System.out.println(Files.readSymbolicLink(path));
}
}

getFDid()是一种本地方法,用于获取给定文件描述符对象的描述符id

以下代码是getFDid()本机方法的实现

SafeFileDescriptor.h

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class SafeFileDescriptor */
#ifndef _Included_SafeFileDescriptor
#define _Included_SafeFileDescriptor
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     SafeFileDescriptor
 * Method:    getFDid
 * Signature: (Ljava/io/FileDescriptor;)I
 */
JNIEXPORT jint JNICALL Java_SafeFileDescriptor_getFDid
  (JNIEnv *, jobject, jobject);
#ifdef __cplusplus
}
#endif
#endif

从java文件SafeFileDescriptor.java 创建SafeFileDescriptor.h

javac -h dir SafeFileDescriptor.java

将"dir"替换为存储SafeFileDescriptor.h 的目录

SafeFileDescriptor.c

#include <jni.h>
#include "SafeFileDescriptor.h"
JNIEXPORT jint JNICALL Java_SafeFileDescriptor_getFDid
  (JNIEnv *env, jobject this_object, jobject fdObject) {
    jclass fileDescriptor = (*env)->GetObjectClass(env,fdObject);
    jfieldID id_fd = (*env)->GetFieldID(env, fileDescriptor, "fd", "I");
    return (*env)->GetIntField(env,fdObject,id_fd);
}

编译SafeFileDescriptor.c

gcc -fPIC -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/linux" -shared -o libSafeFileDescriptor.so SafeFileDescriptor.c

libSafeFileDescriptor.so文件添加到java类文件

System.load("Documents/java native interface exmples/libSafeFileDescriptor.so");

根据@androiddeveloper和@zakmck的回答添加了附加信息。

/对于大多数Unix变体,包括大多数Linux变体和MacOS,dev/fd是一个更好的解决方案,但并非适用于所有变体。它适用于我在CentOS 9和MacOS 12.1上使用。

fdescfdesc文件系统通常安装在/dev/fd上。它的功能类似于Linux上的/proc//fd(或简称/proc/self/fd),也就是说,它为当前运行的进程提供了所有活动文件描述符的列表。请注意,一个典型的Linux系统具有象征性地链接到/proc/self/fd的/dev/fd。

参考文献:

  • https://web.archive.org/web/20190724030849/http://osxbook.com/book/bonus/ancient/whatismacosx/arch_fs.html

  • https://en.wikipedia.org/wiki/File_descriptor

  • https://unix.stackexchange.com/questions/123602/portability-of-file-descriptor-links/123659#123659

相关内容

  • 没有找到相关文章

最新更新