每个幼儿园的孩子都知道,Linux 中的文件路径不能超过PATH_MAX字符。
但是在我的系统上试验,命令
ln -s $(for i in {0..1024}; do printf dir/../; done)foobar foobar1
Run Code Online (Sandbox Code Playgroud)
失败并显示错误消息File name too long。
我不太明白为什么。这里没有长文件名,只有文件的预期内容foobar1很长。甚至还没有人试图遍历符号链接的内容以到达目标。当然,我可以拥有一个内容远大于PATH_MAX.
另一方面,像这样的命令
for i in {0..4096}; do ln -s $i $(expr $i + 1); done
Run Code Online (Sandbox Code Playgroud)
成功。只有当我试图遍历链时,系统才会抱怨。
但我对遍历任何东西都不感兴趣。我正在编写必须读取符号链接值(无需遍历)的软件,我想知道是否需要考虑很长的值。
在 Linux 中哪里记录了这是不允许的?或者它是否依赖于文件系统实现并且可以更改?
对符号链接的调用失败
ENAMETOOLONG (File name too long)
Run Code Online (Sandbox Code Playgroud)
这是来自内核。它也依赖于文件系统,因此为什么在任何地方都找不到定义的 SYMLINK_MAX 。例如...
XFS
if (pathlen < 0 || pathlen > MAXPATHLEN) {
xfs_alert(mp, "%s: inode (%llu) bad symlink length (%lld)",
__func__, (unsigned long long) ip->i_ino,
.......
}
Run Code Online (Sandbox Code Playgroud)
和 MAXPATHLEN == 1024
重新定义
item_len = ROUND_UP(strlen(symname));
if (item_len > MAX_DIRECT_ITEM_LEN(parent_dir->i_sb->s_blocksize)) {
retval = -ENAMETOOLONG;
.......
}
Run Code Online (Sandbox Code Playgroud)
分机2
struct super_block * sb = dir->i_sb;
int err = -ENAMETOOLONG;
unsigned l = strlen(symname)+1;
.....
if (l > sb->s_blocksize)
goto out;
....
return err;
Run Code Online (Sandbox Code Playgroud)
符号链接应该在文件名所在的任何地方都可用,因此它小于 PATH_MAX 是合乎逻辑的,它里面的内容并不重要。来自 Linux 上的符号链接手册页。
ENAMETOOLONG
target or linkpath was too long.
Run Code Online (Sandbox Code Playgroud)
这是模糊的,因为文件系统定义了它。您可以达到的另一个限制是_POSIX_SYMLINK_MAX。
#define _POSIX_SYMLINK_MAX 255
Run Code Online (Sandbox Code Playgroud)
要测试它,请在目录中创建以下两个链接。这个会成功
ln -s foo Fh5LNDZYm2vUlf3jypJtAaX1ElqHZAF4ivsuq8sHyKVLDrYi4zR3T2QcXwS5TPRTys9aUxuh3qtnlNnFQGInmLiM7GK1xpN78ZbcD4JWizfPa7VWwhR4XWpvaJLHCIONUTC6A8fjNVfhv434vWckuKDzTacno0LE13mBVHuj5RDgJIkmW1zUcMMh5E38VisPxSN7BGxBVXHtn0cUPmZLmYSzGrOJqEJzimvwh2uDi8uXEOwBLbsfYlxBOz1kw8P
Run Code Online (Sandbox Code Playgroud)
这个会失败
ln -s foo Fh5LNDZYm2vUlf3jypJtAaX1ElqHZAF4ivsuq8sHyKVLDrYi4zR3T2QcXwS5TPRTys9aUxuh3qtnlNnFQGInmLiM7GK1xpN78ZbcD4JWizfPa7VWwhR4XWpvaJLHCIONUTC6A8fjNVfhv434vWckuKDzTacno0LE13mBVHuj5RDgJIkmW1zUcMMh5E38VisPxSN7BGxBVXHtn0cUPmZLmYSzGrOJqEJzimvwh2uDi8uXEOwBLbsfYlxBOz1kw8Pk
Run Code Online (Sandbox Code Playgroud)
一个是 255 个字符长,另一个是 256 个字符。在您的问题中,此命令将起作用,因为每个单独的链接都有自己的 inode 并且名称很短。
for i in {0..4096}; do ln -s $i $(expr $i + 1); done
Run Code Online (Sandbox Code Playgroud)