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

时间:2010-02-24 23:43:08

标签: linux symlink bsd

我正在编写一个(联合国)归档工具及其设计方式,它首先会在检查特殊属性之前从归档创建一个常规文件,并且可能会确定此项目是符号链接。

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

我一直在OS X上进行开发,只需相应地设置Type和Creator代码,就可以将常规文件转换为符号链接。

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

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

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

3 个答案:

答案 0 :(得分:4)

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

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

答案 1 :(得分: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 / > 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

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

答案 2 :(得分:1)

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