staging.inyokaproject.org

Fesstellen ob Datei und Verzeichnis auf demselben Dateisystem sind

Status: Gelöst | Ubuntu-Version: Xubuntu 20.04 (Focal Fossa)
Antworten |

uzfH8

Avatar von uzfH8

Anmeldungsdatum:
3. Mai 2013

Beiträge: 1011

Ich habe ein Skript, dass Hardlinks von Dateien erzeugt, die der Benutzer wählen kann. Die Dateien befinden sich auf einem per nfs eingebundenem Verzeichnis. Es ist denkbar, dass der Benutzer versehentlich Dateien von seinem Rechner wählt, die sich dann natürlich nicht hardlinken lassen. Ich würde daher vorher gerne prüfen, ob Datei und Verzeichnis in dem der Link entstehen soll auch wirklich auf demselben Datenträger sind. Ich habe das ursprüngliche Skript etwas erweitert und in ruby geschrieben. Der stat-Aufruf ist in ruby in der Klasse File::Stat gekapselt. Die Methode dev dieser Klasse gibt mir die device Nummer. Reicht es, diese device Nummern für die Datei und das Verzeichnis auf Gleichheit zu prüfen, das heißt, ist es garantiert, dass verschiedene Dateisysteme hier verschiedene Nummern haben? Oder gibt es bessere Ideen, wie ich sicherstellen kann, dass ln nicht fehlschlägt?

Dakuan

Avatar von Dakuan

Anmeldungsdatum:
2. November 2004

Beiträge: 6532

Also ich mache das bisher auch so wenn ich Dateien verschieben will. Denn auf dem gleichen Dateisystem kann man das mit rename() machen, was deutlich schneller geht. Ich benutze dafür die entsprechende C-Funktion.

Geht aber auch in der Shell

stat --print="%D\n" <Dateiname>
802
$

Wie das genau codiert ist, kann ich ohne mein dickes Buch jetzt aber nicht sagen.

p.s. Ob das so auch übers Netzwerk geht, weiß ich nicht. Mit Sockets habe ich noch nicht experimentiert.

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13242

uzfH8 schrieb:

Die Methode dev dieser Klasse gibt mir die device Nummer. Reicht es, diese device Nummern für die Datei und das Verzeichnis auf Gleichheit zu prüfen, das heißt, ist es garantiert, dass verschiedene Dateisysteme hier verschiedene Nummern haben? Oder gibt es bessere Ideen, wie ich sicherstellen kann, dass ln nicht fehlschlägt?

Nein, ich denke, das sollte tun. Ich habe das mal eben überprüft mit meinem BTRFS-Volume, das zwei Subvolumes hat, die unter / und /home gemountet sind:

1
2
$ ruby -e 'p ARGV.map {|path| File.stat(path).dev}' / /home ~
[27, 51, 51]

Man sieht, obwohl es ja sogar nur ein Volume darunter ist, wir das vermutlich durch Linux VFS auf zwei Device-Ids gemappt.

Allerdings: der ln kann ja auch aus anderen Gründen scheitern. Man könnte also auch die Strategie verfolgen es einfach zu tun und die Fehlermeldung anzuzeigen, die ggf. hochkommt (wenn die denn sinnvoll ist).

Dakuan

Avatar von Dakuan

Anmeldungsdatum:
2. November 2004

Beiträge: 6532

Man sieht, obwohl es ja sogar nur ein Volume darunter ist, wir das vermutlich durch Linux VFS auf zwei Device-Ids gemappt.

In meinem dicken Buch ist die Rede von Major und Minor ID Nummer, aber wie die aufgeteilt sind, konnte ich aus dem Text jetzt nicht direkt ablesen. Jedenfalls ist da keine Tabelle.

Aber dazu mal drei weitere Beispiele:

$ stat --print="%D\n" /etc/fstab
801
$ 

Das ist die erste Partition auf dem selben PC wie im obigen Beispiel. Ein weiteres Beispiel von einem USB-Stick (aus der Grabbelkiste, frei zur weiteren Verwendung).

$ stat --print="%D\n" '/media/manfred/Lubuntu 16.04.3 LTS i386/md5sum.txt'
821
manfred@samurai:~$

Was ich jetzt aber nicht ganz verstehe ist folgendes Beispiel:

$ stat --print="%D\n" extern/data/ab0308.jpg
37
$ 

Das ist eine Datei, die auf einem NAS liegt und im home Verzeichnis unter ~/extern eingebunden ist., aber auch eine deutlich andere ID hat.

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17630

Dakuan schrieb:

Also ich mache das bisher auch so wenn ich Dateien verschieben will. Denn auf dem gleichen Dateisystem kann man das mit rename() machen, was deutlich schneller geht.

Das halte ich für ein Gerücht.

Ein mv auf dem gleichen Dateisystem ändert nur den Eintrag in der Tabelle des Dateisystems, aber verschiebt, also liest und schreibt kein einziges Bytes der Daten in der Datei.

Eine 1,6 GB-Datei wird in weniger als 1/100tel Sekunde verschoben auf einer klassischen Festplatte.

Dakuan

Avatar von Dakuan

Anmeldungsdatum:
2. November 2004

Beiträge: 6532

Das halte ich für ein Gerücht.

Wieso das denn?

Ein mv auf dem gleichen Dateisystem ändert nur den Eintrag in der Tabelle des Dateisystems, aber verschiebt, also liest und schreibt kein einziges Bytes der Daten in der Datei.

Das sag ich doch. Ein Rename auf dem gleichen Dateisystem ist auch nichts weiter als eine Änderung am Inhalt der Dateien, die die betroffenen Verzeichnisse repräsentieren. Funktioniert aber nur innerhalb eines Dateisystems (Verzeichnisses?).

Ein Verzeichnis ist ja auch nur eine Datei. Und wenn die Aktion sich innerhalb einer Partition abspielt, werden nur Einträge von einer Datei in eine andere ausgeführt (wenn es die selbe Partition ist).

Wenn das nicht richtig wäre, wäre ich schon vor einigen Jahren böse auf die Nase gefallen.

uzfH8

(Themenstarter)
Avatar von uzfH8

Anmeldungsdatum:
3. Mai 2013

Beiträge: 1011

Dakuan schrieb:

Was ich jetzt aber nicht ganz verstehe ist folgendes Beispiel:

$ stat --print="%D\n" extern/data/ab0308.jpg
37
$ 

Das ist eine Datei, die auf einem NAS liegt und im home Verzeichnis unter ~/extern eingebunden ist., aber auch eine deutlich andere ID hat.

Es ist jedenfalls das was ich brauche, dass eingebundene Verzeichnisse unterscheidbar sind. Ich war etwas irritiert, dass das so kleine Zahlen sind. Da ich nicht weiß, wie sich die bestimmen, wären da ja zufällige Kollisionen eher denkbar, im Gegensatz zu den länglichen UUIDs.

Eine Fehlerbehandlung, wenn ln fehlschlägt empfiehlt sich natürlich in jedem Fall, aber ich ziehe es vor zwischen zwei Arten von Fehlern zu unterscheiden.

Fehler durch den Benutzer, soll dieser korrigieren können. Dazu muss ich ihm aber eine sinnvolle Fehlermeldung anzeigen, die er versteht. Beispielsweise prüfe ich auch, ob versehentlich eine Verzeichnis ausgewählt wurde, damit ich eine hilfreiche Fehlermeldung der Art "Sie haben Verzeichnis foobar ausgewählt. Ein Hardlink für ein Verzeichnis ist nicht möglich." ausgeben kann. Wenn ich einfach einen generellen Fehler der Art "ln hat nicht funktioniert" für alle Fehler ausgebe, besteht die Gefahr, dass ich jedesmal hinlaufen und es selbst erklären muss.

Danke an alle Kommentatoren.

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13242

Dakuan schrieb:

$ stat --print="%D\n" /etc/fstab
801
$ 

Du kannst Dir übrigens ein wenig Tipparbeit sparen: stat -c %D /etc/fstab tut es auch.

Dakuan

Avatar von Dakuan

Anmeldungsdatum:
2. November 2004

Beiträge: 6532

Es ist jedenfalls das was ich brauche, dass eingebundene Verzeichnisse unterscheidbar sind.

Nur damit keine Missverständnisse auftreten, du kannst damit keine Verzeichnisse unterscheiden, nur die Dateisysteme auf dem die Ziele liegen.

Ich war etwas irritiert, dass das so kleine Zahlen sind.

Besonders viele Geräte hat man ja selten. Mein Buch beschreibt das nicht weiter, erwähnt aber das bis Kernel 2.4 für Major (Type) und Minor ID nur jeweils 8 Bit reserviert wurden.

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13242

Dakuan schrieb:

Es ist jedenfalls das was ich brauche, dass eingebundene Verzeichnisse unterscheidbar sind.

Nur damit keine Missverständnisse auftreten, du kannst damit keine Verzeichnisse unterscheiden, nur die Dateisysteme auf dem die Ziele liegen.

Genau das wird ja hier benötigt.

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17630

Dakuan schrieb:

Das halte ich für ein Gerücht.

Wieso das denn?

Weil ich es missverstanden habe. ☺

Durch unaufmerksames Lesen hatte ich verstanden, dass Du rename statt mv verwendest, aber Du schreibst ja von Funktionen in Programmen, nicht Programmen/Befehlen i.d. Shell.

uzfH8

(Themenstarter)
Avatar von uzfH8

Anmeldungsdatum:
3. Mai 2013

Beiträge: 1011

rklm schrieb:

Genau das wird ja hier benötigt.

Richtig, also Problem insoweit gelöst. Praktisch funktioniert es auch bisher, es bleibt mir aber wohl die Restunsicherheit, ob es wirklich garantiert ist, dass unterschiedliche Dateisysteme hier unterschiedliche Ausgaben produzieren.

Dakuan

Avatar von Dakuan

Anmeldungsdatum:
2. November 2004

Beiträge: 6532

In "The Linux Programming Interface" Chap. 14.2 p.254 steht:

Each partition is treated by the kernel as a separate device residing under the /dev directory.

...

A disk partition may hold any type of information, but usually contains one of the following:

  • a file system ...

Ich denke das reicht.

Ich habe nochmal ein Experiment gemacht, und eine der Beispieldateien auf dem NAS abgefragt, wobei ich das NAS diesmal über Caja eingebunden hatte:

manfred@samurai:~$ stat -c %D /run/user/1000/gvfs/smb-share\:server\=lager1.local\,share\=homes/manfred/data/ab0308.jpg 
31

Interessant ist, das diesmal eine andere ID kommt. Ob das jetzt an gvfs liegt oder daran dass es sich um ein Raid System handelt, kann ich nicht sagen.

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13242

Dakuan schrieb:

Ich habe nochmal ein Experiment gemacht, und eine der Beispieldateien auf dem NAS abgefragt, wobei ich das NAS diesmal über Caja eingebunden hatte:

manfred@samurai:~$ stat -c %D /run/user/1000/gvfs/smb-share\:server\=lager1.local\,share\=homes/manfred/data/ab0308.jpg 
31

Interessant ist, das diesmal eine andere ID kommt. Ob das jetzt an gvfs liegt oder daran dass es sich um ein Raid System handelt, kann ich nicht sagen.

Gib doch mal die gesamten Befehle und Ausgaben aus. Ansonsten ist unklar, was Du mit "anderer ID" meinst.

Dakuan

Avatar von Dakuan

Anmeldungsdatum:
2. November 2004

Beiträge: 6532

Da fehlt doch nur der Prompt in der letzten Zeile.

Was ich gemacht habe: Ich habe in Caja über Orte das NAS gesucht, mich eingelogt und fertig.

Danach habe ich mir mit mc den Pfad herausgesucht und genau diesen im Terminal eingegeben.

Ich werde das morgen noch einmal wiederholen, um zu sehen ob die ID gleich bleibt. Was kann ich denn noch testen?

Antworten |