Как приложения Mac могут отслеживать местоположение файла?

18

Я наблюдаю такое поведение на моем Mac:

  • Откройте PDF с PDF Expert, внесите некоторые изменения в файл, переместите файл в Finder, сохраните его в PDF Expert, и он будет правильно сохранен на новом месте.
  • Откройте оболочку в каталоге, например ~/foo, очистите каталог с другим приложением, и pwd оболочки правильно выведет ~/.Trash/foo.

Что происходит под капотом? Кажется, что эти случаи указывают на то, что приложения не просто хранят абсолютный путь к файлу, как, например, emacs (я прав с этим?), Или это совершенно другой механизм?

Nichijou
источник

Ответы:

21

У macos есть специальная /.vol/система, сопоставленная с реальным каталогом и файлами. Файлы и каталоги доступны через /.vol/<device_id>/<inode_number>, независимо от того, где файлы находятся в файловой системе.

Это милая маленькая система.

Таким образом, программы могут, например, получить номер инода /Users/jdoe/someFile.txtи затем открыть его через /.vol/12345/6789(в этом случае идентификатор устройства равен 12345, а номер инода 6789). Затем вы перемещаетесь /Users/jdoe/someFile.txtкуда угодно (на ту же громкость), и все просто работает. Вы даже можете написать сценарий оболочки, который поддерживает это magic.

ls -di <file> чтобы получить номер инода.

$ ls -di /User/jdoe/someFile.txt
6789 /User/jdoe/someFile.txt

РЕДАКТИРОВАТЬ:

Вы используете statдля получения идентификатора тома и номера inode, в соответствии со связанным ответом, как выделено IMSoP.

GetFileInfo /.vol/12345/6789вернет текущее местоположение файла, ранее находившегося в /Users/jdoe/someFile.txt.

См. Https://stackoverflow.com/questions/11951328/is-there-any-function-to-retrieve-the-path-associated-with-an-inode для получения дополнительной информации.

thecarpy
источник
1
Согласно связанным ответам, statэто более полезная команда, чем ls -di, поскольку она сообщает вам номер тома / устройства, а также идентификатор файла / номер индекса.
IMSoP
4
В Debian у меня нет, /.vol/и это все еще происходит (хотя мне нужно pwd -P, только тогда pwdобновляется вывод plain ). Я предполагаю, что программы не должны открывать файлы по какому-либо специальному пути, потому что в общем случае они получают (и сохраняют) файловые дескрипторы, которые в любом случае отображаются ядром на inode. Я подозреваю, что на Mac /.vol/это тоже не существенно.
Камиль Мачоровский
Поэтому, если вы переместите файл на другой диск, эта схема нарушится.
Джоэл Коухорн
1
@JoelCoehoorn Да, но технически вы не можете переместить файл на другой диск. Вы можете скопировать его на другой диск, затем удалить его, и есть ярлыки, чтобы сделать это как «один шаг», но это все равно копирование и удаление, а не перемещение, то есть технически другой файл.
ibrewster
1
Многие текстовые редакторы читают данный файл, закрывают его, работают с его копией и сохраняют по тому же пути, поэтому они воссоздают файл в его старом местоположении. Но они могут держать файл открытым все время и писать в него в самом конце. Мой bashна Debian делает это. Я бегу exec 3<>foo, затем переместился fooв ту же файловую систему, echo whatever >&3затем проверил fooновое место - и оно изменилось. Хотя bashне может искать в файле, другие программы в целом могут. Моя точка зрения не /.vol/является существенной, программы могут легко работать без этого. Или я не понимаю, в чем разница.
Камиль Мачоровски
1

Ответ ниже ложный (см. Комментарии). Пожалуйста, игнорируйте


В дополнение к хорошему ответу, который дал Карпи, вполне вероятно, что ваши программы просто держат дескриптор файла , который не зависит от расположения файлов в дереве каталогов (а в системах Unix даже не удаляет файл, по крайней мере, пока вы его не закроете) ).

Дескриптор файла - это, по сути, прямой доступ к файлу, независимо от того, где и как часто (в случае жестких ссылок) он существует в структуре каталогов.

Том
источник
Нет, ты тоже не понял, я думаю ... см. Мой комментарий к @KamilMaciorowski. Дескриптор файла не изменяется, когда вы сохраняете файл, новый файл создается в исходном месте .... не так на macos!
thecarpy
1
Вы правы, это очень неожиданно и очень непохоже на Unix. :(
Том
Договорились и проголосовали!
thecarpy
0

Хотя я не уверен, почему macos использует это вместо стандартной функциональности C, предполагая, что то, что я читал много лет назад в «Mac OS X Unleashed», было правильным, оказалось, что я снова узнал что-то новое.

Пожалуйста, посмотрите на следующую простую программу на C:

#include <stdio.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{
    struct timespec ts;
        ts.tv_sec = 10;
        ts.tv_nsec = 0;
    FILE * fp;

    fp = fopen("file.txt", "a");
    int f = fileno(fp);

    if (fp == NULL)
    {
        printf("Error opening file!\n");
        exit(1);
    }

    struct stat file_stat;
    int ret;
    ret = fstat (f, &file_stat);
    printf("inode number is %d\n", file_stat.st_ino);
    nanosleep(&ts, NULL);

    printf("Finished sleep, writing to file.\n");

/* print some text */
    const char *text = "Write this to the file";
    dprintf(f, "Some text: %s\n", text);

/* print integers and floats */
    int i = 1;
    float py = 3.1415927;
    dprintf(f, "Integer: %d, float: %f\n", i, py);

/* printing single characters */
    char c = 'A';
    dprintf(f, "A character: %c\n", c);

    close(f);
}

Скомпилируйте программу, запустите ее в фоновом режиме и быстро mv file.txt file2.txtДО того, как программа напечатает «Законченный сон, запись в файл». (у вас есть 10 секунд)

Обратите внимание, что file2.txtвывод вашей программы, хотя она была перемещена до того, как текст был напечатан в файл (через дескриптор файла).

$ gcc myfile.c
$ ./a.out &
[1] 21416
$ inode number is 83956
$ ./mv file.txt file2.txt
$ Finished sleep, writing to file.
[1]+  Done                    ./a.out
$ cat file2.txt
Some text: Write this to the file
Integer: 1, float: 3.141593
A character: A

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: Я не обрезал список «включить», он был быстро взломан, чтобы доказать свою точку зрения.

thecarpy
источник