Was ist los mit stat unter Mac OS X / Darwin? Oder Dateisysteme ohne Namen

2108
Charles Stewart

In Beantwortung einer Frage, die ich zu SO gestellt hatte: Gib den Mount-Punkt eines Pfads an, schlug ein Befragter vor stat, den Gerätenamen zu ermitteln, der dem Volume eines bestimmten Pfads zugeordnet ist. Dies funktioniert gut unter Linux, liefert aber unter Mac OS X 10.4 verrückte Ergebnisse. Für mein System geben df und mount Folgendes:

cas cas$ df Filesystem 512-blocks Used Avail Capacity Mounted on /dev/disk0s3 58342896 49924456 7906440 86% / devfs 194 194 0 100% /dev fdesc 2 2 0 100% /dev <volfs> 1024 1024 0 100% /.vol automount -nsl [166] 0 0 0 100% /Network automount -fstab [170] 0 0 0 100% /automount/Servers automount -static [170] 0 0 0 100% /automount/static /dev/disk2s1 163577856 23225520 140352336 14% /Volumes/Snapshot /dev/disk2s2 409404102 5745938 383187960 1% /Volumes/Sparse cas cas$ mount /dev/disk0s3 on / (local, journaled) devfs on /dev (local) fdesc on /dev (union) <volfs> on /.vol automount -nsl [166] on /Network (automounted) automount -fstab [170] on /automount/Servers (automounted) automount -static [170] on /automount/static (automounted) /dev/disk2s1 on /Volumes/Snapshot (local, nodev, nosuid, journaled) /dev/disk2s2 on /Volumes/Sparse (asynchronous, local, nodev, nosuid) 

Beim Versuch, die Geräte von den Mount-Punkten abzurufen:

cas cas$ df | grep -e/  | awk ''  | while read line; do echo $line $(stat -f"%Sdr" $line); done / disk0s3r /dev ???r /dev ???r /.vol ???r /Network ???r /automount/Servers ???r /automount/static ???r /Volumes/Snapshot disk2s1r /Volumes/Sparse disk2s2r 

Hier füttere ich jeden Mountpunkt, der von df an stat gekratzt ist, und gebe die Ergebnisse des "% Sdr" -Formats aus. Dabei handelt es sich um den Gerätenamen: Cf. stat (1) man-Seite:

Der spezielle Ausgabespezifizierer S kann verwendet werden, um anzuzeigen, dass Die Ausgabe sollte ggf. im String-Format sein. Könnte genutzt werden in Kombination mit: ... dr Zeigt den tatsächlichen Gerätenamen an. 

Was ist los? Ist es ein Fehler in Stat oder eine Darwin-VFS-Verrücktheit?

Postscript Per Andrew McGregor, versuche, "% Sd" an stat weiterzugeben, um mehr Verrücktheit zu erreichen. Es listet einige scheinbar willkürliche Untermengen von Dateien von CWD auf ...

3

3 Antworten auf die Frage

3
Chris Johnsen

Erstens, als ein STAT - Format, „% Sdr“ als interpretierte dFeldwähler, durch die modifizierten SSpezifizierer, gefolgt von einem wörtlichen Klein R Charakter.

Die Manpage wäre wahrscheinlich klarer, wenn unter der Beschreibung von "d, r" anstelle von "dr" steht S. dund rsind beide separate Feldselektoren. rwählt die Gerätenummer aus der stat (2) -Info aus (dh st_rdev; nur nützlich bei der Registrierung von Geräteeinträgen (dh den Einträgen unter / dev)). dWählt die Gerätenummer des Geräts aus, das den angegebenen Eintrag enthält (dh st_dev). Die Zahl, die gedruckt wird, ist eine Kombination der Haupt- und Nebenzahlen, die durch ls (Haupt << 24 | Minor) angezeigt werden .

Sist ein Modifikator, der auf beiden angewandt werden kann d, rund mehr anderen Feld Selektoren. Bei der Anwendung auf doder rwird versucht, den Namen des Geräts anstelle der Rohnummer zu drucken. Einige Geräte, wie die virtuellen Dateisystemgeräte, haben keine richtigen Namen, so dass sie ???stattdessen gedruckt <major>,<minor>werden. Dies bedeutet nicht, dass diese Dateisysteme keine Geräte haben, nur dass ihre Geräte keine normalen Namen wie "disk0s3" haben.

Die "Shell Weirdness" ("scheinbar willkürliche Untermenge der Dateien von CWD") ist auf fehlende Zitate zurückzuführen. Die Shell sieht das (nicht zitierte) "???" Ergebnis und erweitert es als Glob-Muster. Wenn der cwd Einträge mit genau drei Bytes enthält (Zeichen abhängig vom Gebietsschema?), Ersetzt die Shell diese Einträge für das Glob-Muster. Das Verhalten (das Zitieren und die Glob-Erweiterung) variiert je nach Shell und kann normalerweise durch verschiedene Shell-Optionen geändert werden.

Sie können Ihren ursprünglichen Befehl wie folgt modifizieren, um das Glätten und das nachfolgende "r" zu vermeiden:

df | grep -e/ | awk '' | while read line; do echo "$line" "$(stat -f%Sd "$line"); done 

Aber ich würde es wahrscheinlich stattdessen so schreiben:

df | tail +2 | awk '' | xargs stat -f'%N %Sd %d' 
  • Beachten Sie, dass dies für alle angehängten Dateisysteme fehlschlägt, die Leerzeichen in ihren Mountpunktnamen enthalten. Weder die Ausgabe von mount noch df ist sehr einfach zu parsen (beide haben Felder, die fast beliebige Zeichenketten enthalten).

Mit dieser Ausgabe (Name, Gerätenummer, Gerätename) erhalten Sie möglicherweise eine bessere Vorstellung davon, was los ist.

Oder möchten Sie vielleicht zusätzlich zu den unformatierten Gerätenummern die Haupt- und Minor-Nummern sehen (vergleichen Sie diese mit dem, was Sie in (zB) sehen ls -l /dev/disk0s3):

df | tail +2 | awk '' | xargs stat -f'%N %Sd %d' |  awk 'BEGIN {$(NF+1) = int($NF/f) "," ($NF%f) } 1' 

Hier ist ein kleines C-Programm, das die problematische "df | head | awk" -Pipeline ersetzen kann.

Natürlich kann ein solches C-Programm die restliche Arbeit selbst erledigen, aber es wäre vielleicht schön, ein eigenständiges Programm zu haben, das nur NUL-terminierte Mountpunkte ausspucken kann.

mountz | xargs -0 stat -f'%N %Sd %d' |  awk 'BEGIN {$(NF+1) = int($NF/f) "," ($NF%f) } 1' 

Code:

#include <sys/mount.h> #include <stdio.h> #include <stdlib.h>  /* usage: mountz | xargs -0 command_for_each_mount_point */  int main(int argc, const char *argv[]) { struct statfs *buf; int flags = MNT_NOWAIT, num_fs, num_stat, i; unsigned bufsz;  num_fs = getfsstat(NULL, 0, flags); if (num_fs < 0) { perror("unable to count mounted filesystems: getfsstat"); exit(1); }  bufsz = sizeof(*buf) * num_fs; buf = malloc(bufsz); if (!buf) { perror("unable to allocate %u statfs structs"); exit(1); } fprintf(stderr, "p=%p\n", buf);  num_stat = getfsstat(buf, bufsz, flags); if (num_stat < 0) { perror("unable to getfsstat"); exit(1); } if (num_stat != num_fs) { fprintf(stderr, "Hmm, expected %u, got %d.\n", num_fs, num_stat); }  for (i = 0; i < num_stat; i++) { fprintf(stdout, "%s%c", buf[i].f_mntonname, 0); } } 
Ich hatte das alles herausgefunden, aber ich habe es in den akzeptierten Post geändert, weil Sie das alles so klar auslegen. Wrt. "Die Manpage wäre wahrscheinlich klarer, wenn unter der Beschreibung von S" d, r "anstelle von" dr "steht - nun, das kann man wohl löschen: -> Charles Stewart vor 14 Jahren 0
1
Douglas Leeder

Die virtuellen Dateisysteme haben also keine Geräte - ich habe es nicht für diese Dateisysteme versucht. Es ist kein Problem für / Network, / automount / Servers oder / automount / static, da diese keine Dateien enthalten sollten. Aber / dev ist interessant.

Die Erkenntnis, dass Darwin nicht der Meinung ist, dass Mount-Punkte mit Dateisystemen verknüpft werden müssen, ist der Schlüssel. Ich habe den akzeptierten Posten in Chris geändert, weil er alle Fragen so klar herausstellt. Charles Stewart vor 14 Jahren 0
1
Andrew McGregor
df | grep -e/ | awk '' | while read line; do echo $line $(stat -f"%Sd" $line); done / disk0s2 /dev XGS bin tmp /net XGS bin tmp /home XGS bin tmp 

Ich würde sagen, Darwin VFS-Verrücktheit.

Ah! Ich verstehe eine Sache: Das ist eine normale Unix-Shell-Verrücktheit: Die Dateisysteme werden "???" genannt, die sich beim Echo in die aus drei Buchstaben bestehenden Dateinamen im aktuellen Verzeichnis verwandeln, genau wie `echo $ (echo \? \? \?). `. Es zeigt jedoch, dass die Interpretation von Formatzeichenfolgen durch stat nicht mit dem übereinstimmt, was die stat (1) -Manpage sagt: "% Sd" macht, was die Manpage sagt, "% Sdr" sollte tun. Charles Stewart vor 14 Jahren 0