Я пишу (ООН) инструмент архивации и способ, которым это разработано, это сначала создает регулярный файл из архива, прежде чем это исследует специальные атрибуты и сможет решить, что этот объект является символьной ссылкой на самом деле.
Примечание: Прежде чем больше людей неправильно понимает меня для желания сделать символьную ссылку файла. Нет, я пишу данные символьной ссылки, т.е. его путь, в файл, и затем я хочу сказать файловой системе, что это - символьная ссылка
Я разрабатывал это на OS X, где возможно превратить регулярный файл в символьную ссылку путем простой установки ее кодов Типа и Создателя соответственно.
Теперь мне нравится получать этот код, работающий над Linux также. Таким образом, мне нравится находить похожий способ там.
Я знаю, что нормальный способ создать символьную ссылку состоит в том, чтобы назвать символьную ссылку () функцией, но интересно, существует ли также способ изменить регулярный файл в символьную ссылку, точно так же, как это возможно в системе OSX BSD, так, чтобы я не осуществлял рефакторинг свой рабочий код слишком много?
Существует lstat (), который возвращает тип файла в upmost битах st_mode. Теперь интересно, существует ли также аналогичная функция метода set для этого поля режима.
Я не верю, что в Linux есть способ сделать это так, как вы описали. IIRC, файловая система хранит информацию о симлинках в таблице inode, а не в обычном файле, поэтому нет прямого способа превратить файл в ссылку.
Если путь к симлинку хранится внутри файла, почему бы не считать путь, удалить файл и создать симлинк на его месте?
.Демонстрация того, что я написал в качестве комментария к ответу 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
Это просто демонстрация; ему действительно нужна дополнительная обработка ошибок и, возможно, лучшее временное имя файла.
Нет, вы не можете превратить одно в другое. Вы должны отсоединить файл, чтобы уничтожить его, а затем создать симлинк в качестве замены.