如何在 Linux 上将常规文件转换为符号链接

发布于 2024-08-22 10:45:20 字数 446 浏览 19 评论 0原文

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

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

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

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

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

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

I'm writing an (un)archiving tool and the way it is designed it first creates a regular file from the archive before it examines the special attributes and may decide that this item is a symlink, in fact.

Note: Before more people misunderstand me for wanting to make a symlink of a file. No, I write the symlink data, i.e. its path, into the file, and then I want to tell the file system that this is a symlink

I've been developing this on OS X, where it's possible to turn a regular file into a symlink by simply setting its Type and Creator codes accordingly.

Now I like to get this code working on Linux as well. So I like to find a similar way there.

I am aware that the normal way to create a symlink is to call the symlink() function, but I wonder if there is also a way to change a regular file into a symlink, just like it's possible in OSX's BSD system, so that I do not have to refactor my working code too much?

There is lstat(), which returns the file type in st_mode's upmost bits. Now I wonder if there's also an analogous setter function for this mode field.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

皓月长歌 2024-08-29 10:45:20

我不相信 Linux 中有一种方法可以像你所描述的那样做到这一点。 IIRC,文件系统将符号链接信息存储在索引节点表中,而不是存储在常规文件中,因此没有直接的方法将文件转换为链接。

如果符号链接的路径存储在文件内,为什么不读出该路径,删除该文件,然后在其位置创建一个符号链接?

I don't believe there is a way in Linux to do this as you describe. IIRC, the filesystem stores symlink information in the inode table and not in a regular file so there's no direct way of turning a file into a link.

If the symlink's path is stored inside the file, why not read out the path, delete the file, and create a symlink in its place?

盛装女皇 2024-08-29 10:45:20

展示我所写的对 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 / > test
$ ./f2s test
$ ls -l test
lrwxrwxrwx 1 me me 1 Feb 24 23:17 test -> /
$ echo -n / > test2
$ strace ./f2s test2
open("test2", O_RDONLY)                 = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=1, ...}) = 0
read(3, "/", 1)                         = 1
close(3)                                = 0
symlink("/", "test2~")                  = 0
rename("test2~", "test2")               = 0

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

Demonstrating what I wrote as a comment to bmarguiles's answer,

#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 / > test
$ ./f2s test
$ ls -l test
lrwxrwxrwx 1 me me 1 Feb 24 23:17 test -> /
$ echo -n / > test2
$ strace ./f2s test2
open("test2", O_RDONLY)                 = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=1, ...}) = 0
read(3, "/", 1)                         = 1
close(3)                                = 0
symlink("/", "test2~")                  = 0
rename("test2~", "test2")               = 0

This is just a demonstration; it really needs more error-handling and maybe a better temporary filename.

错爱 2024-08-29 10:45:20

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

No, you can't turn one into the other. You have to unlink to kill the file and then symlink to create a symlink as a replacement.

原来是傀儡 2024-08-29 10:45:20

假设您有一个名为 file 的文本文件,其中包含指向其他位置的另一个名为 file

file 的文件的路径:

./some_subdir/file

用指向其内容路径的符号链接替换该文件

ln -sf $(cat file)

Suppose you have a text file named file with a path in it to another file somewhere else named file

file:

./some_subdir/file

Replace the file inplace with a symlink to its content path

ln -sf $(cat file)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文