【问题标题】:How to turn a regular file into a symlink on Linux如何在 Linux 上将常规文件转换为符号链接
【发布时间】:2010-02-24 23:43:08
【问题描述】:

我正在编写一个(取消)存档工具,它的设计方式是首先从存档中创建一个常规文件,然后再检查特殊属性并可能确定该项目实际上是一个符号链接。

注意:在更多人误解我想要制作一个文件的符号链接之前。不,我将符号链接数据,即它的路径,写入文件,然后我想告诉文件系统这是一个符号链接

我一直在 OS X 上开发此功能,只需相应地设置其类型和创建者代码,就可以将常规文件转换为符号链接。

现在我想让这段代码也能在 Linux 上运行。所以我喜欢在那里找到类似的方式。

我知道创建符号链接的正常方法是调用 symlink() 函数,但我想知道是否还有一种方法可以将常规文件更改为符号链接,就像在 OSX 的 BSD 系统中一样,这样我就不必过多地重构我的工作代码?

有 lstat(),它在 st_mode 的最高位返回文件类型。现在我想知道这个模式字段是否也有类似的setter函数。

【问题讨论】:

  • 检查我是否理解:您想将常规文件转换为指向文件包含内容的符号链接?
  • 与较新的问题"What is there behind a symbolic link?" 相关。从接受的答案中,我得出结论,普通文件和符号链接之间的区别在于某些 inode 标志,所以我想翻转该标志就足够了,但我想这并不容易。

标签: linux symlink bsd


【解决方案1】:

我不相信 Linux 中有一种方法可以按照您的描述执行此操作。 IIRC,文件系统将符号链接信息存储在 inode 表中而不是常规文件中,因此没有直接的方法将文件转换为链接。

如果符号链接的路径存储在文件中,为什么不读出路径,删除文件,并在其位置创建符号链接?

【讨论】:

  • 我接受这个答案不是因为它相当明显的变通建议,而是为了解释为什么没有办法做我想做的事。我希望你的解释是正确的:)
  • 也许我对没有仔细阅读感到困惑,但根据this answer,我得出结论,符号链接只是一个在inode中有特殊标志的文件。那这个flag就不能翻转了吗?
  • @Alexy 这比这更复杂,因为你有内核级 inode 以及一大堆因文件系统而异的特定于实现的东西。如果您发现自己需要在如此低的级别上操作符号链接,那么您可能正在做一些艰难的事情。
【解决方案2】:

展示我写的作为对 bmarguiles 答案的评论,

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char **argv) {
    char *buffer = 0, *name = 0;
    int i;
    for (i = 1; i < argc; i++) {
        struct stat st;
        int fd = open(argv[i], O_RDONLY);
        fstat(fd, &st);
        buffer = realloc(buffer, st.st_size + 1);
        read(fd, buffer, st.st_size);
        close(fd);
        buffer[st.st_size] = '\0';
        name = realloc(name, strlen(argv[i]) + 2);
        sprintf(name, "%s~", argv[i]);
        symlink(buffer, name);
        rename(name, argv[i]);
    }
    free(buffer);
    free(name);
    return 0;
}
$ vi f2s.c ... $ cc -o f2s f2s.c $ echo -n // 测试 $ ./f2s 测试 $ ls -l 测试 lrwxrwxrwx 1 me me 1 Feb 24 23:17 test -> / $回声-n/>测试2 $ strace ./f2s test2 打开(“test2”,O_RDONLY)= 3 fstat(3, {st_mode=S_IFREG|0644, st_size=1, ...}) = 0 读取(3,“/”,1)= 1 关闭(3)= 0 符号链接("/", "test2~") = 0 重命名(“test2~”,“test2”)= 0

这只是一个演示;它确实需要更多的错误处理,也许还有更好的临时文件名。

【讨论】:

  • 我很好奇为什么使用realloc() 而不是malloc()
  • 主要是因为我很懒,只想在最后输入一个free。这不是生产质量代码。
  • 你没你想的那么懒,你已经有两个free()的=)
  • 哈哈是的,回想起来,移动到循环内的malloc+free 实际上对我来说输入它的工作量是一样多的。尽管如此,我还是在 Stack Overflow 答案表单中快速写下了这篇文章——你很幸运,我什至费心复制、编译和测试它 :-)
  • 感谢您努力展示这一点。这不是真的必要,但我很感激你的努力。我在接受您的额外努力与 bta 对我的问题的现场答复之间左右为难。我会给你一个,然后他打勾,因为你已经有两个了。我希望这不会太不公平。
【解决方案3】:

不,你不能把一个变成另一个。您必须取消链接以终止文件,然后进行符号链接以创建符号链接作为替换。

【讨论】:

  • 最好创建一个不同名称的符号链接,然后在原始文件上重命名它。这是一个原子替换,不会有文件名丢失的间隙(就像您取消链接后发生的那样)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-28
  • 1970-01-01
  • 2019-04-04
  • 1970-01-01
  • 2012-10-03
  • 1970-01-01
相关资源
最近更新 更多