67. Systemprogrammierung II: Dateiattribute

Dateien haben unter modernen Betriebssystemen eine Unzahl von Metainformationen (d.h., Informationen über ihren eigentlichen Inhalt hinaus: Name, Zugriffsrechte, Änderungsdatum usf.). Zugriff auf sie bietet stat aus sys.stat.h. Es füllt eine struct stat aus. Aus ihr lassen sich u.a. entnehmen

  • Typ und Zugriffsrechte (st_mode)
  • Eigentümer (st_uid)
  • Änderungszeit (st_mtime)
  • Größe (st_size)

Die Zeiten sind dabei im üblichen Unix-Format kodiert, nämlich Zahl der Sekunden seit dem 1.1.1970. Damit kann man die Daten einfach wie ganze Zahlen vergleichen.

Der Eigentümer der Datei ist numerisch kodiert – um auf wirkliche Namen zu kommen, kann man die Funktion getpwent verwenden.

In st_mode ist zusätzlich kodiert, was für eine “Datei” sich hinter dem Namen verbirgt. Makros für Zugriff auf st mode:

  • S ISDIR(m) Wahr, wenn Verzeichnis
  • S_ISLNK(m) Wahr, wenn symbolischer Link
  • S_ISREG(m) Wahr, wenn normale Datei

Analog Makros für die verschiedenen Zugriffsrechte:

  • S IRUSR Lesen für Eigentümer
  • S_IWUSR Schreiben für Eigentümer
  • S_IXUSR Ausführen für Eigentümer
  • S_IRGRP Schreiben für Gruppe
  • S_IROTH Lesen für andere

Mit diesen Makros und der Funktion chmod(char *filename, mode_t mode) können die Rechte für eigene Dateien auch gesetzt werden. Das mag z.B. praktisch sein, um der eigenen Gruppe auf jeden Fall Schreibrecht zu geben. In solchen Fällen kann man aber auch an den Einsatz von mode_t umask denken.

Im folgenden Beispiel werden zwei Funktionen definiert, die jeweils auf einzelne Felder einer stat-Struktur zugreifen. Im Hauptprogramm wird dann bestimmt, wie die Altersrelation zwischen zwei in der Kommandozeile erwähnten Dateien ist. Sowas könnte z.B. nützlich sein, um zu bestimmen, ob eine Datei neu erzeugt werden muss, ganz ähnlich, wie Make das macht.

Bei der Gelegenheit verwenden wir den einzigen ternären Operator von C, das Fragezeichen. Der Ausdruck a?b:c hat einfach den Wert b, wenn a wahr ist, und sonst den Wert c – wir haben hier also einen einfachen Spezialfall von Selektion. Laut Präzendenztabelle bindet ? lächerlich schwach, so dass hier Klammern fast immer angesagt sind.

#include <sys/stat.h>
#include <stdio.h>
#include <time.h>

size_t getFSize(char *name)
{
  struct stat s;
  if (stat(name, &s)) {
    perror(name); exit(1);
  }
  return s.st_size;
}

time_t getMTime(char *name)
{
  struct stat s;
  if (stat(name, &s)) {
    perror(name); exit(1);
  }
  return s.st_mtime;
}

int main(int argc, char **argv)
{
  if (argc==3) {
    time_t t1=getMTime(argv[1]),
      t2=getMTime(argv[2]);
    printf("%s (%d Bytes) ist %s als %s (%d Bytes).\n",
      argv[1], getFSize(argv[1]), (t1>t2?"neuer":"älter"),
      argv[2], getFSize(argv[2]));
  } else {
    return 1;
  }
  return 0;
}


Markus Demleitner

Copyright Notice