Как превратить регулярный файл в символьную ссылку на Linux

Я пишу (ООН) инструмент архивации и способ, которым это разработано, это сначала создает регулярный файл из архива, прежде чем это исследует специальные атрибуты и сможет решить, что этот объект является символьной ссылкой на самом деле.

Примечание: Прежде чем больше людей неправильно понимает меня для желания сделать символьную ссылку файла. Нет, я пишу данные символьной ссылки, т.е. его путь, в файл, и затем я хочу сказать файловой системе, что это - символьная ссылка

Я разрабатывал это на OS X, где возможно превратить регулярный файл в символьную ссылку путем простой установки ее кодов Типа и Создателя соответственно.

Теперь мне нравится получать этот код, работающий над Linux также. Таким образом, мне нравится находить похожий способ там.

Я знаю, что нормальный способ создать символьную ссылку состоит в том, чтобы назвать символьную ссылку () функцией, но интересно, существует ли также способ изменить регулярный файл в символьную ссылку, точно так же, как это возможно в системе OSX BSD, так, чтобы я не осуществлял рефакторинг свой рабочий код слишком много?

Существует lstat (), который возвращает тип файла в upmost битах st_mode. Теперь интересно, существует ли также аналогичная функция метода set для этого поля режима.

7
задан Thomas Tempelmann 24 February 2010 в 23:55
поделиться

3 ответа

Я не верю, что в Linux есть способ сделать это так, как вы описали. IIRC, файловая система хранит информацию о симлинках в таблице inode, а не в обычном файле, поэтому нет прямого способа превратить файл в ссылку.

Если путь к симлинку хранится внутри файла, почему бы не считать путь, удалить файл и создать симлинк на его месте?

.
4
ответ дан 7 December 2019 в 05:21
поделиться

Демонстрация того, что я написал в качестве комментария к ответу 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

Это просто демонстрация; ему действительно нужна дополнительная обработка ошибок и, возможно, лучшее временное имя файла.

3
ответ дан 7 December 2019 в 05:21
поделиться

Нет, вы не можете превратить одно в другое. Вы должны отсоединить файл, чтобы уничтожить его, а затем создать симлинк в качестве замены.

1
ответ дан 7 December 2019 в 05:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: