Wie können Mac-Apps den Speicherort einer Datei verfolgen?

18

Ich beobachte auf meinem Mac ein solches Verhalten:

  • Öffnen Sie eine PDF-Datei mit PDF Expert, nehmen Sie einige Änderungen an der Datei vor, verschieben Sie die Datei in Finder, speichern Sie sie in PDF Expert, und sie wird korrekt an der neuen Stelle gespeichert.
  • Öffnen Sie eine Shell in einem Verzeichnis wie ~/foo, werfen Sie das Verzeichnis mit einer anderen App in den Papierkorb und die pwd der Shell wird korrekt ausgegeben ~/.Trash/foo.

Was passiert unter der Haube? Diese Fälle scheinen darauf hinzudeuten, dass Apps nicht nur einen absoluten Pfad der Datei wie Emacs enthalten (habe ich Recht damit?), Oder handelt es sich um einen völlig anderen Mechanismus?

nichijou
quelle

Antworten:

21

macos hat ein besonderes /.vol/ System, das dem aktuellen Verzeichnis und den Dateien zugeordnet ist. Auf die Dateien und Verzeichnisse kann zugegriffen werden /.vol/<device_id>/<inode_number>, unabhängig davon, wo sich die Dateien im Dateisystem befinden.

Es ist ein schönes kleines System.

So können Programme beispielsweise die Inode-Nummer von abrufen /Users/jdoe/someFile.txtund diese dann über öffnen /.vol/12345/6789(in diesem Fall lautet die Geräte-ID 12345 und die Inode-Nummer 6789). Sie bewegen sich dann an eine /Users/jdoe/someFile.txtbeliebige Stelle (auf derselben Lautstärke), und alles funktioniert. Sie können sogar ein Shell-Skript schreiben, das dies unterstütztmagic .

ls -di <file> um die Inode-Nummer zu bekommen.

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

BEARBEITEN:

Sie verwenden statdiese Option, um die ID des Volumes und die Inode-Nummer gemäß der von IMSoP hervorgehobenen verknüpften Antwort abzurufen.

GetFileInfo /.vol/12345/6789würde den aktuellen Speicherort der Datei zurückgeben, die sich zuvor in befunden hat /Users/jdoe/someFile.txt.

Weitere Informationen finden Sie unter /programming/11951328/is-there-any-function-to-retrieve-the-path-associated-with-an-inode .

thecarpy
quelle
1
Laut verknüpften Antworten statist hier ein sinnvollerer Befehl als ls -di, da er Ihnen die Volume- / Geräte-ID sowie die Datei-ID / Inode-Nummer mitteilt.
IMSoP
4
In Debian habe ich keine /.vol/und dies passiert immer noch (obwohl ich brauche pwd -P, wird nur dann die Ausgabe von plain pwdaktualisiert). Ich schätze, Programme müssen Dateien nicht über einen speziellen Pfad öffnen, da sie im Allgemeinen Dateideskriptoren erhalten (und behalten), die vom Kernel ohnehin auf Inodes abgebildet werden. Ich vermute, auf dem Mac /.vol/ist nicht so wichtig.
Kamil Maciorowski
Wenn Sie also eine Datei auf einen anderen Datenträger verschieben, bricht dieses Schema ab.
Joel Coehoorn
1
@JoelCoehoorn Ja, aber technisch können Sie nicht bewegen , eine Datei auf einen anderen Datenträger. Sie können es auf den anderen Datenträger kopieren und dann löschen. Es gibt Verknüpfungen, um dies als "einen Schritt" auszuführen. Es handelt sich jedoch weiterhin um ein Kopieren und Löschen und nicht um eine Verschiebung. Technisch gesehen handelt es sich also um eine andere Datei.
ibrewster
1
Viele Texteditoren lesen eine bestimmte Datei, schließen sie, bearbeiten ihre Kopie und speichern sie unter demselben Pfad, sodass sie die Datei an ihrem alten Speicherort neu erstellen. Aber sie könnten die Datei die ganze Zeit geöffnet lassen und ganz am Ende schreiben. Mein bashauf Debian macht das. Ich starte, bewege mich exec 3<>foodann fooinnerhalb des gleichen Dateisystems und echo whatever >&3überprüfe dann fooden neuen Speicherort - und er wird geändert. Obwohl bashin der Datei nicht gesucht werden kann, können es andere Programme im Allgemeinen. Mein Punkt ist /.vol/nicht wesentlich, Programme können ohne es leicht so arbeiten. Oder ich verstehe nicht, was der Unterschied ist.
Kamil Maciorowski
1

Die Antwort unten ist falsch (siehe Kommentare). Bitte ignorieren


Neben der guten Antwort thecarpy gab, ist es wahrscheinlich , dass Ihre Programme einfach halten eine Datei Griff , das vom Speicherort der Dateien im Verzeichnisbaum unabhängig ist (und auf Unix-Systemen das Löschen der Datei sogar so lange fortsetzt, bis Sie es schließen ).

Ein Datei-Handle ist im Grunde genommen der direkte Zugriff auf die Datei, unabhängig davon, wo oder wie oft (bei Hardlinks) sie in der Verzeichnisstruktur vorhanden ist.

Tom
quelle
Nein, du hast es auch nicht verstanden, denke ich ... siehe meinen Kommentar zu @KamilMaciorowski. Das Dateihandle ändert sich nicht, wenn Sie die Datei dann speichern, wird eine neue Datei am ursprünglichen Speicherort erstellt .... nicht so bei MacOS!
thecarpy
1
Sie haben recht, das ist sehr unerwartet und sehr unähnlich zu Unix. :(
Tom
Einverstanden und aufgestimmt!
thecarpy
0

Ich bin mir nicht sicher, warum MacOS diese Funktion anstelle der Standard-C-Funktionalität verwendet. Vorausgesetzt, dass das, was ich vor Jahren in "Mac OS X Unleashed" gelesen habe, richtig ist, stellte sich heraus, dass ich wieder etwas Neues gelernt habe.

Bitte schauen Sie sich folgendes einfaches C-Programm an:

#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);
}

Kompilieren Sie das Programm, führen Sie es im Hintergrund aus, und mv file.txt file2.txtBEVOR das Programm "Beendet den Ruhezustand, Schreiben in eine Datei" ausgibt. (Sie haben 10 Sekunden)

Beachten Sie, dass file2.txtdie Ausgabe Ihres Programms zwar verschoben wurde, bevor der Text in die Datei gedruckt wurde (über den Dateideskriptor).

$ 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

HAFTUNGSAUSSCHLUSS: Ich habe die "include" -Liste nicht gekürzt, dies wurde schnell zusammen gehackt, um einen Punkt zu beweisen.

thecarpy
quelle