8

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

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

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

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

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

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

4

3 回答 3

4

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

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

于 2010-02-25T00:07:43.430 回答
3

展示我写的作为对 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

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

于 2010-02-25T04:20:55.320 回答
1

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

于 2010-02-25T00:08:20.320 回答