如何确定一个目录是在文件系统层次结构中的另一个目录之下还是之上
How to find out if a directory is under or above another directory in the file system hierarchy
我目前正在做一个类似于 FTP 的项目。为此,我需要实施虚拟 chrooting,它也应该适用于 Windows 平台。
我目前的做法是每个用户都有一个特定的主目录(由 File
对象表示),每次用户尝试访问文件或目录时,服务器都会检查这个文件或目录是否在此主目录中。
遗憾的是,我不确定如何以不占用太多 CPU 时间和 HDD 访问时间的方式执行此检查。人们可以简单地尝试遍历目录,如果我们到达一个等于给定主目录的目录,我们就会感到满意。如果我们到达根目录,我们 return false
因为给定的文件很可能不在主目录中。
我相信这个检查会起作用,但我也认为这会非常昂贵,而且在多用户环境中可能非常低效。
如果能帮助我更好地设计这个算法,我将不胜感激。也许甚至存在一种方法?不过我还没有找到。
提前致谢!
// 编辑:根据要求,这里是此文件结构的一些示例
- /
- home/
- user1/
- file1.txt
- file2.txt
- user2/
- picture.png
- someDir/
我们假设有 2 个用户("user1" 和 "user2"),用户 1 的主目录为“/home/user1”,用户 2 的主目录为“/home/user2”。
如果应用于此场景,我正在寻找的方法应该会给出以下结果:
isInsideHome("/home/user2/picture.png", "user1") -> false
isInsideHome("/home/user1/file1.txt", "user1") -> true
isInsideHome("/", "user1") -> false
isInsideHome("/home", "user2") -> false
我希望这些例子能阐明我在寻找什么。
假设您不调用诸如 createNewFile()、exists() 等方法 java.io.File 不需要 HDD 访问,并且只需要最小的 CPU。
例如我的电脑上有none条路径,但代码执行无异常
public static void main(String[] args) {
System.out.println(isInsideHome("/home/user2/picture.png", "user1"));
System.out.println(isInsideHome("/home/user1/file1.txt", "user1"));
System.out.println(isInsideHome("/", "user1"));
System.out.println(isInsideHome("/home", "user2"));
}
private static boolean isInsideHome(String pathStr, String leaf) {
File path = new File(pathStr);
File search = new File(leaf);
while ((path = path.getParentFile()) != null) {
if (search.getName().equals(path.getName())) {
return true;
}
}
return false;
}
java.io.File.getParentFile() 的来源表明不涉及 HDD 访问...
public static void main(String[] args) {
System.out.println(isInsideHome("/home/user2/picture.png", "user1"));
System.out.println(isInsideHome("/home/user1/file1.txt", "user1"));
System.out.println(isInsideHome("/", "user1"));
System.out.println(isInsideHome("/home", "user2"));
}
private static boolean isInsideHome(String pathStr, String leafStr) {
File path = new File(pathStr);
File leaf = new File(leafStr);
while ((path = path.getParentFile()) != null) {
if (leaf.getName().equals(path.getName())) {
return true;
}
}
return false;
}
我目前正在做一个类似于 FTP 的项目。为此,我需要实施虚拟 chrooting,它也应该适用于 Windows 平台。
我目前的做法是每个用户都有一个特定的主目录(由 File
对象表示),每次用户尝试访问文件或目录时,服务器都会检查这个文件或目录是否在此主目录中。
遗憾的是,我不确定如何以不占用太多 CPU 时间和 HDD 访问时间的方式执行此检查。人们可以简单地尝试遍历目录,如果我们到达一个等于给定主目录的目录,我们就会感到满意。如果我们到达根目录,我们 return false
因为给定的文件很可能不在主目录中。
我相信这个检查会起作用,但我也认为这会非常昂贵,而且在多用户环境中可能非常低效。
如果能帮助我更好地设计这个算法,我将不胜感激。也许甚至存在一种方法?不过我还没有找到。
提前致谢!
// 编辑:根据要求,这里是此文件结构的一些示例
- /
- home/
- user1/
- file1.txt
- file2.txt
- user2/
- picture.png
- someDir/
我们假设有 2 个用户("user1" 和 "user2"),用户 1 的主目录为“/home/user1”,用户 2 的主目录为“/home/user2”。
如果应用于此场景,我正在寻找的方法应该会给出以下结果:
isInsideHome("/home/user2/picture.png", "user1") -> false
isInsideHome("/home/user1/file1.txt", "user1") -> true
isInsideHome("/", "user1") -> false
isInsideHome("/home", "user2") -> false
我希望这些例子能阐明我在寻找什么。
假设您不调用诸如 createNewFile()、exists() 等方法 java.io.File 不需要 HDD 访问,并且只需要最小的 CPU。
例如我的电脑上有none条路径,但代码执行无异常
public static void main(String[] args) {
System.out.println(isInsideHome("/home/user2/picture.png", "user1"));
System.out.println(isInsideHome("/home/user1/file1.txt", "user1"));
System.out.println(isInsideHome("/", "user1"));
System.out.println(isInsideHome("/home", "user2"));
}
private static boolean isInsideHome(String pathStr, String leaf) {
File path = new File(pathStr);
File search = new File(leaf);
while ((path = path.getParentFile()) != null) {
if (search.getName().equals(path.getName())) {
return true;
}
}
return false;
}
java.io.File.getParentFile() 的来源表明不涉及 HDD 访问...
public static void main(String[] args) {
System.out.println(isInsideHome("/home/user2/picture.png", "user1"));
System.out.println(isInsideHome("/home/user1/file1.txt", "user1"));
System.out.println(isInsideHome("/", "user1"));
System.out.println(isInsideHome("/home", "user2"));
}
private static boolean isInsideHome(String pathStr, String leafStr) {
File path = new File(pathStr);
File leaf = new File(leafStr);
while ((path = path.getParentFile()) != null) {
if (leaf.getName().equals(path.getName())) {
return true;
}
}
return false;
}