Rheinwerk Computing < openbook > Rheinwerk Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger

 << zurück
Linux-UNIX-Programmierung von Jürgen Wolf
Das umfassende Handbuch – 2., aktualisierte und erweiterte Auflage 2006
Buch: Linux-UNIX-Programmierung

Linux-UNIX-Programmierung
1216 S., mit CD, 49,90 Euro
Rheinwerk Computing
ISBN 3-89842-749-8
gp Kapitel 3 Attribute von Dateien und Verzeichnissen
  gp 3.1 Struktur stat
    gp 3.1.1 Dateiart und Zugriffsrechte einer Datei erfragen – st_mode
    gp 3.1.2 User-ID-Bit und Group-ID-Bit – st_uid und st_gid
    gp 3.1.3 Inode ermitteln – st_ino
    gp 3.1.4 Linkzähler – st_nlink
    gp 3.1.5 Größe der Datei – st_size
    gp 3.1.6 st_atime, st_mtime, st_ctime

Kapitel 3 Attribute von Dateien und Verzeichnissen

Im Kapitel zuvor wurden Sie häufig auf dieses Kapitel verwiesen. Hier werden nun die Attribute vorgestellt, die eine jede Datei und jedes Verzeichnis im Inode speichert.


Rheinwerk Computing

3.1 Struktur stadowntop

Die einzelnen Attribute zu einer Datei oder einem Verzeichnis können Sie aus der Struktur stat herauslesen. Die einzelnen Strukturvariablen von stat sind das Thema der nun folgenden Seiten.

Die Struktur stat ist in der Headerdatei <sys/stat.h> definiert und besitzt gewöhnlich (wird nicht fest vorgeschrieben) die in der Tabelle aufgelisteten Strukturvariablen.


Tabelle 3.1    Strukturvariablen in struct stat und deren Bedeutung

Variable Bedeutung POSIX
st_dev Gerätenummer (Device-Nummer) des Dateisystems, auf dem sich die Datei/das Verzeichnis befindet. ja
st_ino Inode-Nummer ja
st_mode Dateimodus (Dateityp und Zugriffsrechte) ja
st_nlink Anzahl fester Links auf die Datei ja
st_uid UID des Dateieigentümers ja
st_gid GID des Dateieigentümers ja
st_rdev Geräte-ID (nur für Spezialdateien) nein
st_size Größe der Datei in Bytes ja
st_atime Datum des letzten Zugriffs ja
st_mtime Datum der letzten Veränderung ja
st_ctime Datum der Inode-Änderung ja
st_blksize Eingestellte Blockgröße nein
st_blocks Anzahl der verwendeten st_blksize-Blöcke nein

Sie haben drei Versionen, womit Sie die Dateiattribute der Struktur stat erfragen können. Hier die Syntax:

#include <sys/types.h>
#include <sys/stat.h>
int stat(const char *pfadname, struct stat *buf);
int fstat(int fd, struct stat *buf);
int lstat(const char *pfadname, struct stat *buf);

Alle drei Versionen geben bei einem Fehler -1 und bei Erfolg des Funktionsaufrufs 0 zurück. Bei allen drei Funktionen müssen Sie die Adresse einer Variablen vom Typ struct stat übergeben. Nach dem Funktionsaufruf befinden sich dann die entsprechenden Informationen (siehe Tabelle 3.1) zur betreffenden Datei in den einzelnen Strukturvariablen.

Bei der Funktion stat() geben Sie dabei die Datei mit pfadnamen an. Die Funktion lstat() ist ähnlich wie stat(), nur mit dem Unterschied, wenn es sich bei der Datei um einen symbolischen Link handeln sollte, dann werden die Attribute des symbolischen Links anstatt die der Datei nach buf geschrieben. Die Funktion fstat() ist die Variante der niedrigeren Ebene, die als erstes Argument einen bereits geöffneten Filedeskriptor erwartet.


Rheinwerk Computing

3.1.1 Dateiart und Zugriffsrechte einer Datei erfragen – st_mode  downtop

Die Strukturvariable st_mode kann gleich für zwei Abfragen verwendet werden. Zum einen erfragt man mit ihr, um was für eine Dateiart es sich handelt, und zum anderen, welche Zugriffsrechte diese Datei besitzt.

Die Dateiart können Sie mit den in der Tabelle aufgelisteten Makros abfragen. Jedes dieser Makros liefert 1 zurück, wenn die Bedingung zutrifft, oder 0, falls nicht.


Tabelle 3.2    Makros in <sys/stat.h> für die Dateiart – st_mode

Makro Bedeutung
S_ISREG() Reguläre Datei
S_ISDIR() Verzeichnis
S_ISCHR() Zeichenorientierte Gerätedatei
S_ISBLK() Blockorientierte Gerätedatei
S_ISFIFO() FIFO (benannte Pipe)
S_ISLINK() Symbolischer Link (nicht bei POSIX.1 oder SVR4)
S_ISSOCK() Socket (nicht bei POSIX.1 oder SVR4)

Wie schon erwähnt, können Sie über die Strukturvariable st_mode auch die einfachen Zugriffsrechte der drei Benutzerklassen (rwx|rwx|rwx), die es unter Linux/UNIX gibt, ermitteln. Hier die Tabelle mit den einzelnen Konstanten, womit Sie die Zugriffsrechte überprüfen können.


Tabelle 3.3    Zugriffsrechte der drei Benutzerklassen in <sys/stat.h>

Konstante Bedeutung Benutzerklasse
S_IRUSR read (Leserecht) Dateieigentümer
S_IWUSR write (Schreibrecht) Dateieigentümer
S_IXUSR execute (Ausführungsrecht) Dateieigentümer
S_IRGRP read (Leserecht) Gruppe des Dateieigentümers
S_IWGRP write (Schreibrecht) Gruppe des Dateieigentümers
S_IXGRP execute (Ausführungsrecht) Gruppe des Dateieigentümers
S_IROTH read (Leserecht) Alle anderen Benutzer
S_IWOTH write (Schreibrecht) Alle anderen Benutzer
S_IXOTH execute (Ausführungsrecht) Alle anderen Benutzer

»Alle anderen« heißt auch wirklich alle anderen, die nicht in der Gruppe sind. So gesehen gibt es im Dateimodus 0705 immer eine gelackmeierte Benutzergruppe.

Verändern können Sie die Zugriffsrechte mit der Funktion chmod() oder dem gleichnamigen Befehl in einer Shell.

Das folgende Listing demonstriert nun, wie Sie ein komplettes Verzeichnis (hier das Arbeitsverzeichnis) auslesen und die Dateiart und Zugriffsrechte (Linux-/UNIX-gerecht) mithilfe der Funktion stat() und der Strukturvariablen st_mode ermitteln können.

/* my_stat.c */
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd. h.>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <dirent.h>
#include <stdlib.h>
int main (int argc, char **argv) {
  DIR *dir;
  struct dirent *dirzeiger;
  const char *rwx = "rwxrwxrwx";
  int bits[]= {
     S_IRUSR,S_IWUSR,S_IXUSR,/*Zugriffsrechte User*/
     S_IRGRP,S_IWGRP,S_IXGRP,/*Zugriffsrechte Gruppe*/
     S_IROTH,S_IWOTH,S_IXOTH /*Zugriffsrechte der Rest*/
  };
  /* Arbeitsverzeichnis öffnen */
  if((dir=opendir(".")) == NULL) {
    fprintf(stderr,"Fehler bei opendir: %s\n",
       strerror(errno));
    return (EXIT_FAILURE);
  }
  /* Das komplette Verzeichnis auslesen */
  while((dirzeiger=readdir(dir)) != NULL) {
    struct stat attribut;
    int i;
    char l_rwx[10];
    l_rwx[9] = '\0';
    if(stat(dirzeiger->d_name, &attribut) == -1) {
      fprintf(stderr,"Fehler bei stat: %s\n",
         strerror(errno));
      return (EXIT_FAILURE);
    }
    /* Dateiart erfragen */
    if( S_ISREG(attribut.st_mode) )
      printf("Reguläre Datei           : ");
    else if( S_ISDIR(attribut.st_mode) )
      printf("Verzeichnis              : ");
    else if( S_ISCHR(attribut.st_mode) )
      printf("zeichenorient. Gerätedatei : ");
    else if( S_ISBLK(attribut.st_mode) )
      printf("blockorient. Gerätedatei : ");
    else if( S_ISFIFO(attribut.st_mode) )
      printf("FIFO oder named Pipe     : ");
    else
      printf("Unbekannte Datei          : ");
    /* Dateinamen ausgeben */
    printf("%-20s [",dirzeiger->d_name);
    /* Einfache Zugriffsrechte erfragen */
    l_rwx[0]='\0';
    for(i=0; i<9; i++) { /*Wenn nicht 0, dann gesetzt*/
      l_rwx[i]=(attribut.st_mode & bits[i]) ? rwx[i] : '-';
    }
    l_rwx[9]='\0';
    printf("%s]\n",l_rwx);
  }
  closedir(dir);
  return EXIT_SUCCESS;
}

Das Programm bei der Ausführung:

$ gcc –o my_stat my_stat.c
$ ./my_stat
Verzeichnis              : .                    [rwxrwx---]
Verzeichnis              : ..                   [rwxrwx---]
Verzeichnis              : bin                  [rwxrwx---]
Reguläre Datei           : dir1.c               [rwx------] 
Verzeichnis              : etc                  [rwxrwx---]
Reguläre Datei           : file                 [rwxr-xr-x]
Reguläre Datei           : file1.txt            [rw-r--r--]
Verzeichnis              : lib                  [rwxrwx---]
Verzeichnis              : mails                [rwx------]
Reguläre Datei           : my_stat.c            [rwx------]
Reguläre Datei           : my_stat              [rwxr-xr-x]
Reguläre Datei           : out.txt              [rw-r--r--]
Reguläre Datei           : reformime            [rwx------]
Verzeichnis              : sbin                 [rwxrwx---]
Reguläre Datei           : test                 [rwxrwxrwx]
Reguläre Datei           : test.txt             [rwx------]
Reguläre Datei           : testfile.txt         [rwx------]
Verzeichnis              : tmp                  [rwxrwx---]
Reguläre Datei           : Unbenannt2.cpp       [rwx------]
Verzeichnis              : usr                  [rwxrwx---]
Verzeichnis              : var                  [rwxrwx---]

Sollten Sie Probleme mit den Makros S_IS* haben, dann arbeiten Sie vermutlich mit einem älteren UNIX-/Linux-System, das die Makros noch nicht unterstützt. In solch einem Fall müssen Sie die Konstanten S_IF* als Bitmask verwenden, z. B.:

if(attribut.st_mode & S_IFREG)
   printf("Reguläre Datei\n");
else if(attribut.st_mode & S_IFDIR)
   printf("Directory\n");

Rheinwerk Computing

3.1.2 User-ID-Bit und Group-ID-Bit – st_uid und st_gid  downtop

Wollen Sie den Eigentümer und den Gruppeneigentümer einer Datei ermitteln, können Sie die Strukturvariablen st_uid (Eigentümer) und st_gid (Gruppeneigentümer) abfragen. Hierzu ein kurzes Listing:

/* ugid.c */
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>
int main(int argc, char **argv) {
   struct stat attribut;
   if(argc < 2)
      printf("usage: %s datei(en)\n", *argv);
   while(*++argv != NULL) {
      if(stat(*argv,&attribut) < 0) {
           fprintf(stderr, "stat(): %s\n", strerror(errno));
           return EXIT_FAILURE;
        }
      printf("%-18s\n",*argv);
      printf("USER-ID  : %d\n"   ,attribut.st_uid);
      printf("GROUP-ID : %d\n\n" ,attribut.st_gid);
    }
   return EXIT_SUCCESS;
}

Das Programm bei seiner Ausführung:

$ gcc –o ugid ugid.c
$ ./ugid ugid.c
ugid.c
USER-ID     :  1003
GROUP-ID    :  513

Rheinwerk Computing

3.1.3 Inode ermitteln – st_ino  downtop

Ich setze zwar voraus, dass Sie wissen, was ein Inode ist, aber für den Fall der Fälle hier eine kurze Erklärung dazu. Ein Inode (Information Node = Informationsknoten) ist ein Eintrag in einer bestimmten Tabelle einer Partition, die Informationen zu einer Datei enthält. Dies sind Informationen über den Besitzer, die Zugriffsrechte, die Größe und vor allem auch über die Position einer Datei, wo diese auf der Partition gespeichert ist.

Wird z. B. eine Datei angelegt, werden alle Informationen zu dieser Datei in einem freien Inode geschrieben, dessen Nummer sich im Verzeichnis der Datei befindet. Das heißt, der Inode selbst befindet sich nicht im selben Verzeichnis wie die Datei, sondern nur die dazugehörende Inode-Nummer. Linux/UNIX trennt die Verwaltung von Informationen und der eigentlichen Datei. Somit kann es für einen Inode mehrere Dateinamen im System geben (siehe Abschnitt 3.1.4).


Hinweis   Sie werden es wahrscheinlich geahnt haben: Die meisten Informationen der Struktur stat werden aus diesem Inode gelesen.


Jetzt wissen Sie, was die Inode-Nummer bedeutet, und somit auch, was Sie mit st_ino für Informationen erhalten. Ein Listing dazu kann ich mir ersparen, da die Ermittlung von st_ino genauso abläuft wie im Listing zuvor (siehe Abschnitt 3.1.2).


Rheinwerk Computing

3.1.4 Linkzähler – st_nlink  downtop

Ein Link ist unter Linux/UNIX eine einfache Möglichkeit, einen Alias für eine Originaldatei anzulegen. Damit können Sie auf ein und dieselbe Datei unter mehreren Namen und an einer anderen Stelle, als sich die Originaldatei befindet, zugreifen. Es gibt viele Gründe, so etwas zu tun. Z. B. befindet sich eine Datei oder eine Anwendung im tiefsten Dschungel der Verzeichnishierarchie, und Sie wollen nicht immer wieder einen ellenlangen Text in die Kommandozeile eingeben. Dafür können Sie in Ihrem Arbeitsverzeichnis einen Link (= Verbindung) zu dieser Datei anlegen. Sie können dabei (fast) beliebig viele Links anlegen.

Ein Beispiel. Sie wollen ein Programm aus Ihrem /home-Verzeichnis aufrufen, das sich im Pfad /opt/kde/bin/ befindet. Anstatt das Programm jedes Mal mit folgendem Aufruf zu starten:

/opt/kde/bin/programmname

können Sie hierzu einen Link zu diesem Programm erstellen. In der Kommandozeile können Sie dabei folgendermaßen vorgehen:

$ ln /opt/kde/bin/programmname programmname

Von jetzt an können Sie aus Ihrem /home-Verzeichnis auf das Programm mit programmname zugreifen. Natürlich müssen Sie den Programmnamen dabei nicht einbehalten. Sie können genauso gut einen anderen Namen dafür verwenden:

$ ln /opt/kde/bin/programmname neuer_name

Hinweis   Eine Datei existiert so lange, bis der letzte Link auf diese Datei gelöscht wurde.


Man unterscheidet generell zwischen einem harten Link und einem symbolischen Link. Mit einem symbolischen Link kann man im Gegensatz zu harten Links auch partitionsübergreifend Dateien verlinken. Des Weiteren können symbolische Links auch auf ein Verzeichnis zeigen, was bei harten Links nicht möglich ist. Symbolische Links erkennen Sie bei der Ausgabe von Verzeichnissen mit ls -l an einem Pfeil und einem l (für Link) als erstes Zeichen der Ausgabe:

$ ls –l 
lrwxrwxrwx 1 juergen users 10 Nov  6 00:13 hallo -> /var/hallo

Die »Größe« eines Symlinks ist immer die Länge seines Ziels, also dem Textstring hinter »–>« in ls.

Wollen Sie aus Ihrem Programm heraus einen harten oder einen symbolischen Link erstellen, bieten sich dazu zwei Funktionen an:

#include <unistd. h.>
int link(const char *name, const char *linkname);
int symlink(const char *pfadname, const char *symlink);

Beide Funktionen geben bei Erfolg 0, ansonsten bei einem Fehler -1 zurück. Mit der Funktion link() erzeugen Sie einen harten Link linkname auf die existierende Datei name. Mit symlink() erzeugen Sie einen symbolischen Link mit dem Namen symlink auf pfadname.

Es muss erwähnt werden, dass st_nlink keinen symbolischen Link mitzählt. Dies liegt daran, dass Symlinks selbst einen Inode besitzen und somit außer dem Zielnamen (der ja nicht immer existieren muss) keine Beziehung zu der referenzierten Datei haben. Weiterhin referenziert ein Symlink eine potenzielle Datei, während ein dentry (Verzeichniseintrag) einen Inode referenziert, inkl. gleicher Inodes für mehrere dentries. Ein Symlink dagegen ist ein dentry mit eigenständigem Inode.

Anders als beim harten Link kann es passieren, dass der symbolische Link ins Nichts zeigt (auch genannt »Dangling Symlink«). Linux überprüft nicht, ob ein symbolischer Link noch gültig ist, das müssen die Anwendungen machen. Das ist eigentlich auch logisch. Denn haben Sie z. B. einen symbolischen Link auf einem anderen Rechner über ein Netzwerk gesetzt, würde dies bedeuten, dass dieser Rechner dauerhaft überprüft werden muss. Einen symbolischen Link kann man eher mit der »grausamen« Verknüpfung von MS-Systemen vergleichen. Wollen Sie abfragen, auf welche Originaldatei oder welches Verzeichnis der symbolische Link verweist, so können Sie dies mit der Funktion readlink() in Erfahrung bringen.

#include <unistd. h.>
int readlink(const char *sym_link, char *buf, int buf_size);

Gibt diese Funktion -1 zurück, ist etwas nicht in Ordnung mit dem symbolischen Link (siehe z. B. /proc/2/exe). Natürlich sagt ein Rückgabewert von 0 noch nichts über die Existenz der referenzierten Datei aus. Somit bleibt bei den symbolischen Links immer ein wenig Ungewissheit übrig. Die Funktion readlink() terminiert den String buf übrigens nicht. Aber da die Funktion als Rückgabewert die Anzahl der gelesenen Bytes zurückgibt, sollte dies kein Problem sein.

Ob eine Datei/ein Verzeichnis, die/das durch einen Symlink referenziert wird, nun tatsächlich existiert, kann man entweder mit einem stat() nach readlink() oder einem open() überprüfen. Existiert die Zieldatei nicht, wird in beiden Fällen (stat/open) ENOENT in errno zurückgegeben.

Natürlich gibt es noch viel mehr zu den Links zu sagen, aber dies ist nicht im Sinne eines Buchs zur Programmierung. Dazu seien entsprechende Manual Pages oder eines der vielen guten Linux-Bücher empfohlen (oder ein Blick auf den Inhalt der Buch-CD).

Hierzu nun ein Listing, das die Anzahl von Links (st_nlink) einer Datei überprüft, die Sie als erstes Argument in der Kommandozeile übergeben. Anschließend wird jeweils ein harter und ein symbolischer Link zu dieser Datei erzeugt und die Anzahl von Links ausgegeben. Worauf der symbolische Link verweist, wird mit readlink() ebenso ausgegeben. Am Ende werden der harte und der symbolische Link mit unlink() gelöscht. Hier das Listing:

/* my_link.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd. h.>
#define HARD_LINK "hard_link"
#define SYM_LINK  "sym_link"
#define MAX 255
static int attribute( const char *name ) {
  struct stat st;
  if(stat(name , &st) < 0) {
    fprintf(stderr, "Fehler bei stat: %s\n",
       strerror(errno));
    return -1;
  }
  printf("Anzahl Links  : %d\n",st.st_nlink);
  return 1;
}
int main(int argc, char **argv) {
  const char *ptr;
  char buf[MAX];
  int n;
  if(argc < 2) {
    printf("usage: %s datei\n", argv[0]);
    return EXIT_FAILURE;
  }
  ptr = argv[1];
  /* Anzahl der Links erfragen */
  if( attribute( ptr ) < 0)
    return EXIT_FAILURE;
  /* Einen harten Link erzeugen */
  if((link(ptr, HARD_LINK)) == -1) {
    printf("Konnte keinen Hardlink erstellen\n");
    return EXIT_FAILURE;
  }
  printf("Nach dem Funktionsaufruf von link()\n");
  /* Wieder die Anzahl der Links erfragen */
  if(attribute( ptr ) < 0)
    return EXIT_FAILURE;
  if((symlink(ptr, SYM_LINK)) == -1) {
    printf("Konnte keinen sym. Link erstellen\n");
    return EXIT_FAILURE;
  }
  printf("Nach dem Funktionsaufruf von symlink()\n");
  /* Wieder die Anzahl der Links erfragen */
  if(attribute( ptr ) < 0)
    return EXIT_FAILURE;
  /* Namen anzeigen, worauf der symbolische Link verweist */
  n=readlink(SYM_LINK, buf, MAX);
  printf("Der symbolische Link \"%s\"  zeigt auf"
         " \"%.*s\"\n",SYM_LINK, n, buf);
  /* Links wieder entfernen */
  unlink(HARD_LINK);
  unlink(SYM_LINK);
  return EXIT_SUCCESS;
}

Das Programm bei der Ausführung:

$ gcc –o my_link my_link.c
$ ./my_link test_file
Anzahl Links  : 1
Nach dem Funktionsaufruf von link()
Anzahl Links  : 2
Nach dem Funktionsaufruf von symlink()
Anzahl Links  : 2
Der symbolische Link "sym_link" zeigt auf "test_file"

Rheinwerk Computing

3.1.5 Größe der Datei – st_size  downtop

Mit der Strukturvariablen st_size können Sie sich die Größe einer Datei in Bytes ermitteln lassen. Bei regulären Dateien erhalten Sie dabei die Anzahl von Bytes, die in die Datei geschrieben wurden. Diese Größe muss sich nicht auf den reinen physikalischen Speicherplatz beziehen, da dieser in der Regel immer ein Vielfaches der Blockgröße ist (Gleiches gilt auch umgekehrt, siehe den Abschnitt über ftruncate() in Kapitel 2). Bei Verzeichnissen ist der Wert abhängig vom Filesystem, und bei symbolischen Links enthält st_size die Länge in Bytes (nicht immer, siehe /proc/xxx/fd, wo alle 64 lang sind), die der Dateiname belegt (ohne abschließendes \0), auf den der symbolische Link verweist. In SVR4 enthält st_size außerdem bei den Pipes die Anzahl der zu lesenden Bytes.


Hinweis   Der Speicherplatz wird bei einem Filesystem nicht in Bytes, sondern immer in Blöcken von Bytes angegeben. Die Blockgröße hängt vom Filesystem ab. In SVR4 und BSD haben Sie dabei die Möglichkeit, die beiden Strukturvariablen st_blocks und st_blksize, die in der Struktur stat definiert sind, zu verwenden. Aus der Multiplikation von st_blocks * st_blksize bekommen Sie dann den physikalischen Speicher, den das Dateisystem für die Datei wirklich belegt. Wollen Sie wissen, wie viele Blöcke eine Datei belegt, können Sie auch das Kommando du verwenden (oder st_blocks inspizieren).


Hierzu ein Beispiel:

/* file_size.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd. h.>
static int filesize( const char *name ) {
   struct stat st;
   if(stat(name , &st) < 0) {
      fprintf(stderr, "Fehler bei stat: %s\n",
         strerror(errno));
      return -1;
    }
   printf("Größe in st_size  : %d Bytes\n",(int)st.st_size);
   return 1;
}  
int main(int argc, char **argv) {
   const char *ptr;
   
   if(argc < 2) {
         printf("usage: %s datei\n",argv[0]);
         return EXIT_FAILURE;
      }
   ptr = argv[1];
   /* Größe der Datei abfragen */
   if( filesize( ptr ) < 0)
      return EXIT_FAILURE;
   return EXIT_SUCCESS;
}

Das Programm bei seiner Ausführung:

$ gcc –o file_size file_size.c
$ ./file_size file_size.c
Größe in st_size: 643 Bytes
---[Linux]---
$ du -h file_size.c
4,0K    file_size.c
---[BSD]---
$ du -h file_size.c
2,0K    file_size.c

Zur Demonstration, wie viel physikalischen Speicher die Datei (hier file_size.c) tatsächlich verwendet, wurde das Kommando du der Option -h verwendet.


Rheinwerk Computing

3.1.6 st_atime, st_mtime, st_ctime  toptop

Für Zeitdaten stehen Ihnen in der Struktur stat gleich drei Variablen zur Verfügung:

gp  st_atime = Zeit des letzten Lesezugriffs (dazu gehören nicht stat(), open())
gp  st_mtime = Zeit des letzten Schreibzugriffs
gp  st_ctime = Zeit der letzten Inode-Änderung (z. B. chmod())

Und auch hierzu ein Listing:

/* file_times.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd. h.>
#include <time.h>
static int file_times(const char *name) {
   struct stat st;
   if(stat(name , &st) < 0) {
      fprintf(stderr, "Fehler bei stat: %s\n",
         strerror(errno));
      return -1;
   }
   printf("Letzter Zugriff          : %s",
      ctime( &st.st_atime ));
   printf("Letzte Änderung (Inhalt) :%s",
      ctime( &st.st_mtime ));
   printf("Letzte Änderung (Inode)  : %s",
      ctime( &st.st_ctime ));
   return 1;
}  
int main(int argc, char **argv) {
   const char *ptr;
   
   if(argc < 2) {
         printf("usage: %s datei\n",argv[0]);
         return EXIT_FAILURE;
      }
   ptr = argv[1];
   /* Größe der Datei abfragen */
   if( file_times( ptr ) < 0)
      return EXIT_FAILURE;
   return EXIT_SUCCESS;
}

In diesem Beispiel wurde außerdem die Standardfunktion ctime() verwendet, die in der Headerdatei <time.h> definiert ist, womit aus dem Zeitformat time_t, aus dem die Strukturvariablen st_atime, st_mtime und st_ctime gebildet sind (primitive Datentypen), in einen String konvertiert wird. Hier das Programm bei der Ausführung:

$ gcc –o file_times file_times.c
$ ./file_times file_times.c
Letzter Zugriff          : Tue Nov  4 23:28:36 2003
Letzte Änderung (Inhalt) : Fri Nov  7 00:10:36 2003
Letzte Änderung (Inode)  : Tue Nov  4 23:28:36 2003
$ touch file_times.c
$ ./file_times file_times.c
Letzter Zugriff          : Fri Nov  7 00:23:56 2003
Letzte Änderung (Inhalt) : Fri Nov  7 00:23:56 2003
Letzte Änderung (Inode)  : Fri Nov  7 00:23:56 2003

Wollen Sie die Zugriffs- und/oder Modifikationszeit verändern, können Sie dies mit der Funktion utime() realisieren.

#include <sys/types.h>
#include <utime.h>
int utime(const char *pfad, const struct utimbuf *time_ptr);

Bei Erfolg gibt diese Funktion 0, ansonsten bei einem Fehler -1 zurück. Die Struktur utimbuf sieht wie folgt aus:

struct utime {
   time_t actime;  /* access time -> st_atime       */
   time_t modtime  /* modification time -> st_mtime */
};

Damit können Sie die Zugriffs- und Modifikationszeit auf mindestens den 01. Januar 1970, 01:00:00 Uhr, zurücksetzen. In der Praxis:

/* backward.c */
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd. h.>
#include <utime.h>
int main(int argc, char **argv) {
   const char *ptr;
   struct utimbuf zeit;
   
   if(argc < 2) {
         printf("usage: %s datei\n",argv[0]);
         return EXIT_FAILURE;
      }
   ptr = argv[1];   
   zeit.actime = 0;
   zeit.modtime =0;
   /* Größe der Datei abfragen */
   if( utime( ptr, &zeit ) < 0) {
      perror("uptime");
      return EXIT_FAILURE;
   }
   return EXIT_SUCCESS;
}

Das Programm bei der Ausführung:

$ gcc –o backward backward.c
$ ./file_times file_times.c
Letzter Zugriff          : Fri Nov  7 00:23:56 2003
Letzte Änderung (Inhalt) : Fri Nov  7 00:23:56 2003
Letzte Änderung (Inode)  : Tue Nov  4 23:28:36 2003
$ ./backward file_times.c
$ file_times file_times.c
Letzter Zugriff          : Thu Jan  1 01:00:00 1970
Letzte Änderung (Inhalt) : Thu Jan  1 01:00:00 1970
Letzte Änderung (Inode)  : Tue Nov  4 23:28:36 2003
 << zurück
  
  Zum Rheinwerk-Shop
Neuauflage: Linux-UNIX-Programmierung
Neuauflage:
Linux-UNIX-
Programmierung

bestellen
 Ihre Meinung?
Wie hat Ihnen das Openbook gefallen?
Ihre Meinung

 Buchtipps
Zum Rheinwerk-Shop: Linux-Server






 Linux-Server


Zum Rheinwerk-Shop: Das Komplettpaket LPIC-1 & LPIC-2






 Das Komplettpaket
 LPIC-1 & LPIC-2


Zum Rheinwerk-Shop: Linux-Hochverfügbarkeit






 Linux-
 Hochverfügbarkeit


Zum Rheinwerk-Shop: Shell-Programmierung






 Shell-
 Programmierung


Zum Rheinwerk-Shop: Linux Handbuch






 Linux Handbuch


 Lieferung
Versandkostenfrei bestellen in Deutschland, Österreich und der Schweiz
Info





Copyright © Rheinwerk Verlag GmbH 2006
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das Openbook denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt.
Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


Nutzungsbestimmungen | Datenschutz | Impressum

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de

Cookie-Einstellungen ändern