Macアプリはどのようにしてファイルの場所を追跡できますか?


18

Macで次のような動作を観察します。

  • PDF ExpertでPDFを開き、ファイルにいくつかの変更を加え、Finderでファイルを移動し、PDF Expertで保存すると、新しい場所に正しく保存されます。
  • などのディレクトリでシェルを開き、~/foo別のアプリでディレクトリをゴミ箱に移動すると、シェルのpwdが正しく出力します~/.Trash/foo

フードの下で何が起こっているのですか?これらのケースは、アプリがemacsのようなファイルの絶対パスを保持しているだけではないことを示しているようですが(これでいいのでしょうか)、それともまったく異なるメカニズムですか?

回答:


21

macosには/.vol/、実際のディレクトリとファイルにマップされる特別なシステムがあります。ファイルがディレクトリにあるか/.vol/<device_id>/<inode_number>どうかに関係なく、ファイルとディレクトリはを介してアクセスできます。

素敵な小さなシステムです。

したがって、プログラムは、たとえば、iノード番号を取得し/Users/jdoe/someFile.txtてから開くことができます/.vol/12345/6789(この場合、デバイスIDは12345、iノード番号は6789です)。次に、/Users/jdoe/someFile.txt好きな場所(同じボリューム上)に移動すると、すべてが機能します。これをサポートするシェルスクリプトを作成することもできmagicます。

ls -di <file> iノード番号を取得します。

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

編集:

あなたが使う statIMSoPで強調表示されているリンクされた回答に従って、ボリュームのIDとiノード番号を取得します。

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を参照してください


1
リンクされた回答によると、ボリューム/デバイスIDとファイルID / inode番号を通知statするためls -di、ここよりも便利なコマンドです。
-IMSoP

4
Debianにはありませんが/.vol/、これはまだ起こります(必要なのにpwd -P、plainの出力pwdが更新されるだけです)。プログラムは特別なパスを介してファイルを開く必要がないと思います。一般に、それらはカーネルによってiノードにマップされるファイル記述子を取得(および保持)するためです。私は疑う Macが上/.vol/だけでなく、必須ではありません。
カミルマシオロウスキ

したがって、ファイルを別のディスクに移動すると、このスキームは壊れます。
ジョエルCoehoorn

1
@JoelCoehoornはい、ただし技術的には、ファイルを別のディスクに移動することはできません。他のディスクにコピーしてから削除することができます。これを「1ステップ」として実行するショートカットがありますが、それでもコピーではなく移動であり、技術的には別のファイルです。
-ibrewster

1
多くのテキストエディターは、指定されたファイルを読み取り、閉じ、そのコピーを使用して同じパスに保存するため、古い場所にファイルを再作成します。ただし、ファイルを常に開いたままにして、最後に書き込む場合があります。私のbashDebianはそれを行います。を実行しexec 3<>foofoo同じファイルシステム内で移動してから、新しい場所でecho whatever >&3チェックインしfooました。けれどもはbash、ファイル内の一般的な缶内の他のプログラムを追求することはできません。私のポイントは/.vol/必須ではなく、プログラムはそれなしでも簡単にこのように機能します。または、違いが分からない。
カミルマシオロウスキ

1

以下の答えは偽です(コメントを参照)。無視して下さい


thecarpyが与えた良い答えに加えて、プログラムはディレクトリツリー内のファイルの場所に依存しないファイルハンドルを保持しているだけである可能性があります(そして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

免責事項:「include」リストを整理していませんが、これはポイントを証明するためにすぐにハッキングされました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.