Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 在Unix上从文件句柄创建硬链接?_Linux_Macos_Unix - Fatal编程技术网

Linux 在Unix上从文件句柄创建硬链接?

Linux 在Unix上从文件句柄创建硬链接?,linux,macos,unix,Linux,Macos,Unix,如果我有一个打开文件的句柄,那么在文件系统中删除对该文件的所有引用之后,是否可以创建指向该文件的硬链接 例如,类似这样的内容: fd = fopen("/tmp/foo", "w"); unlink("/tmp/foo"); fwrite(fd, "Hello, world!\n"); create_link_from_fd(fd, "/tmp/hello"); fclose(fd); fd = open("/tmp", O_TMPFILE | O_RDWR, 0600); // write

如果我有一个打开文件的句柄,那么在文件系统中删除对该文件的所有引用之后,是否可以创建指向该文件的硬链接

例如,类似这样的内容:

fd = fopen("/tmp/foo", "w");
unlink("/tmp/foo");
fwrite(fd, "Hello, world!\n");
create_link_from_fd(fd, "/tmp/hello");
fclose(fd);
fd = open("/tmp", O_TMPFILE | O_RDWR, 0600);
// write something to the file here
// fchown()/fchmod() it
linkat(fd, "", AT_FDCWD, "/tmp/test", AT_EMPTY_PATH);

特别是,我想这样做,这样我就可以安全地写入大数据文件,然后将它们移动到原子的位置,而不必担心在我的程序被写入文件时被杀死后自我清理。

在Linux上,你可以尝试调用< <代码> /PRO/FUD/FD>代码>的不可移植的技巧,试图调用< /P>
 char pbuf[64];
 snprintf (pbuf, sizeof(pbuf), "/proc/self/fd/%d", fd);
 link(pbuf, "/tmp/hello");
如果在
取消链接(“/tmp/foo”)
后,这个技巧起作用,我会感到惊讶。。。我没有试过

一种更具可移植性(但不那么健壮)的方法是生成一条“唯一的临时路径”,可能类似于

 int p = (int) getpid();
 int t = (int) time(0);
 int r = (int) random();
 sprintf(pbuf, sizeof(pbuf), "/tmp/out-p%d-r%d-t%d.tmp", p, r, t);
 int fd = open  (pbuf, O_CREAT|O_WRONLY);
写入并关闭文件后,您可以
将其重命名为更合理的路径。您可以在程序中使用
atexit
来进行重命名(或删除)


还有一些
cron
工作,每小时清理一次[old]
/tmp/out*.tmp

一般来说不是,不是。[编辑:自Linux 3.11以来,现在有了
linkat
;请参阅。这通常不适用于POSIX系统,因为POSIX
linkat
仅限于目录。]这里有一些安全注意事项:有人可以向您传递一个打开的文件描述符,您通常无法自己打开该描述符,例如:

mkdir lock; chmod 700 lock
echo secret contents > lock/in
sudoish cmd < lock/in
mkdir锁;chmod 700锁
回显秘密内容>锁定/进入
sudoish cmd
此处,
cmd
以用户身份运行,该用户无权按名称打开输入文件(
lock/in
),但仍可从中读取。如果
cmd
可以在同一文件系统上创建新名称,则可以将文件内容传递给后续进程。(很明显,它可以复制这些内容,所以这个问题更多的是“错误地传递内容”,而不是“故意传递内容”。)

这就是说,人们已经想出了在内部通过inode/vnode“重新链接”文件的方法(在大多数文件系统中很容易做到),因此您可以为它调用自己的私有系统。描述符必须引用相应装入点上的真实文件,当然,无法将管道、套接字或设备“重新链接”为常规文件

否则,您将陷入“捕捉信号、清理并期待最好的结果”或类似的伎俩,“放弃子流程,运行它,如果它成功/失败,则采取适当的移动/清理操作”



编辑以添加历史注释:上面的
lock
示例并不特别好,但在V6 Unix时代,使用了这个技巧的更高级版本。如今,MDQ的各个部分以各种形式存在。

最新发布的linux 3.11使用新的
O_TMPFILE
open(2)
标志为这个问题提供了解决方案。使用此标志,您可以在某些文件系统(由该文件系统中的目录指定)中创建一个“不可见”文件(即没有硬链接的inode)。然后,在完全设置文件后,可以使用
linkat
创建硬链接。它的工作原理如下:

fd = fopen("/tmp/foo", "w");
unlink("/tmp/foo");
fwrite(fd, "Hello, world!\n");
create_link_from_fd(fd, "/tmp/hello");
fclose(fd);
fd = open("/tmp", O_TMPFILE | O_RDWR, 0600);
// write something to the file here
// fchown()/fchmod() it
linkat(fd, "", AT_FDCWD, "/tmp/test", AT_EMPTY_PATH);

请注意,除了>=3.11内核要求之外,这还需要底层文件系统的支持(我在ext3上尝试了上面的代码片段,但它在btrfs上似乎不起作用)。

为了避免安全问题,可以通过以下方法来证实这一点,即使用
/proc/self/fd/n
“唯一和临时路径”,而是使用POSIX
mkstemp
(3)调用创建唯一名称,并在一次调用中打开它。