在 Linux 中,符号链接的值可以比 PATH_MAX 长吗?
in Linux, can the value of a symlink be longer than PATH_MAX?
幼儿园的每个 child 都知道,Linux 中的文件路径不能超过 PATH_MAX
个字符。
但是在我的系统上进行试验,命令
ln -s $(for i in {0..1024}; do printf dir/../; done)foobar foobar1
失败并显示错误消息 File name too long
。
我不太明白为什么。这里没有长文件名,只有文件 foobar1
的预期 内容 很长。甚至还没有人试图 遍历 符号 link 的内容以到达目标。当然,我可以拥有一个内容比 PATH_MAX
大得多的文件。
另一方面,像
这样的命令
for i in {0..4096}; do ln -s $i $(expr $i + 1); done
成功。只有当我试图遍历链时,系统才会抱怨。
但我对遍历任何东西都不感兴趣。我正在编写必须读取符号 link 值(无需遍历)的软件,我想知道是否需要考虑很长的值。
Linux 中哪里记录了不允许这样做?还是 file-system 依赖于实现并且可以更改?
对 symlink 的调用失败
ENAMETOOLONG (File name too long)
这是来自内核。它也依赖于文件系统,因此你找不到 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,
.......
}
和 MAXPATHLEN == 1024
reiserfs
item_len = ROUND_UP(strlen(symname));
if (item_len > MAX_DIRECT_ITEM_LEN(parent_dir->i_sb->s_blocksize)) {
retval = -ENAMETOOLONG;
.......
}
ext2
struct super_block * sb = dir->i_sb;
int err = -ENAMETOOLONG;
unsigned l = strlen(symname)+1;
.....
if (l > sb->s_blocksize)
goto out;
....
return err;
symlink 应该可以在任何文件名所在的地方使用,因此它小于 PATH_MAX 是合乎逻辑的,这与它里面的内容无关。来自 Linux.
上的 symlink 手册页
ENAMETOOLONG
target or linkpath was too long.
这是模糊的,因为文件系统定义了它。您可以达到的另一个限制是 _POSIX_SYMLINK_MAX
.
#define _POSIX_SYMLINK_MAX 255
要测试它,请在目录中创建以下两个 link。这个一定会成功
ln -s foo Fh5LNDZYm2vUlf3jypJtAaX1ElqHZAF4ivsuq8sHyKVLDrYi4zR3T2QcXwS5TPRTys9aUxuh3qtnlNnFQGInmLiM7GK1xpN78ZbcD4JWizfPa7VWwhR4XWpvaJLHCIONUTC6A8fjNVfhv434vWckuKDzTacno0LE13mBVHuj5RDgJIkmW1zUcMMh5E38VisPxSN7BGxBVXHtn0cUPmZLmYSzGrOJqEJzimvwh2uDi8uXEOwBLbsfYlxBOz1kw8P
这个会失败
ln -s foo Fh5LNDZYm2vUlf3jypJtAaX1ElqHZAF4ivsuq8sHyKVLDrYi4zR3T2QcXwS5TPRTys9aUxuh3qtnlNnFQGInmLiM7GK1xpN78ZbcD4JWizfPa7VWwhR4XWpvaJLHCIONUTC6A8fjNVfhv434vWckuKDzTacno0LE13mBVHuj5RDgJIkmW1zUcMMh5E38VisPxSN7BGxBVXHtn0cUPmZLmYSzGrOJqEJzimvwh2uDi8uXEOwBLbsfYlxBOz1kw8Pk
一个是 255 个字符长,另一个是 256 个字符。在你的问题中,这个命令可以工作,因为每个人 link 都有自己的 inode 并且名称很短。
for i in {0..4096}; do ln -s $i $(expr $i + 1); done
幼儿园的每个 child 都知道,Linux 中的文件路径不能超过 PATH_MAX
个字符。
但是在我的系统上进行试验,命令
ln -s $(for i in {0..1024}; do printf dir/../; done)foobar foobar1
失败并显示错误消息 File name too long
。
我不太明白为什么。这里没有长文件名,只有文件 foobar1
的预期 内容 很长。甚至还没有人试图 遍历 符号 link 的内容以到达目标。当然,我可以拥有一个内容比 PATH_MAX
大得多的文件。
另一方面,像
这样的命令for i in {0..4096}; do ln -s $i $(expr $i + 1); done
成功。只有当我试图遍历链时,系统才会抱怨。
但我对遍历任何东西都不感兴趣。我正在编写必须读取符号 link 值(无需遍历)的软件,我想知道是否需要考虑很长的值。
Linux 中哪里记录了不允许这样做?还是 file-system 依赖于实现并且可以更改?
对 symlink 的调用失败
ENAMETOOLONG (File name too long)
这是来自内核。它也依赖于文件系统,因此你找不到 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,
.......
}
和 MAXPATHLEN == 1024
reiserfs
item_len = ROUND_UP(strlen(symname));
if (item_len > MAX_DIRECT_ITEM_LEN(parent_dir->i_sb->s_blocksize)) {
retval = -ENAMETOOLONG;
.......
}
ext2
struct super_block * sb = dir->i_sb;
int err = -ENAMETOOLONG;
unsigned l = strlen(symname)+1;
.....
if (l > sb->s_blocksize)
goto out;
....
return err;
symlink 应该可以在任何文件名所在的地方使用,因此它小于 PATH_MAX 是合乎逻辑的,这与它里面的内容无关。来自 Linux.
上的 symlink 手册页ENAMETOOLONG
target or linkpath was too long.
这是模糊的,因为文件系统定义了它。您可以达到的另一个限制是 _POSIX_SYMLINK_MAX
.
#define _POSIX_SYMLINK_MAX 255
要测试它,请在目录中创建以下两个 link。这个一定会成功
ln -s foo Fh5LNDZYm2vUlf3jypJtAaX1ElqHZAF4ivsuq8sHyKVLDrYi4zR3T2QcXwS5TPRTys9aUxuh3qtnlNnFQGInmLiM7GK1xpN78ZbcD4JWizfPa7VWwhR4XWpvaJLHCIONUTC6A8fjNVfhv434vWckuKDzTacno0LE13mBVHuj5RDgJIkmW1zUcMMh5E38VisPxSN7BGxBVXHtn0cUPmZLmYSzGrOJqEJzimvwh2uDi8uXEOwBLbsfYlxBOz1kw8P
这个会失败
ln -s foo Fh5LNDZYm2vUlf3jypJtAaX1ElqHZAF4ivsuq8sHyKVLDrYi4zR3T2QcXwS5TPRTys9aUxuh3qtnlNnFQGInmLiM7GK1xpN78ZbcD4JWizfPa7VWwhR4XWpvaJLHCIONUTC6A8fjNVfhv434vWckuKDzTacno0LE13mBVHuj5RDgJIkmW1zUcMMh5E38VisPxSN7BGxBVXHtn0cUPmZLmYSzGrOJqEJzimvwh2uDi8uXEOwBLbsfYlxBOz1kw8Pk
一个是 255 个字符长,另一个是 256 个字符。在你的问题中,这个命令可以工作,因为每个人 link 都有自己的 inode 并且名称很短。
for i in {0..4096}; do ln -s $i $(expr $i + 1); done