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

Inhaltsverzeichnis
Vorwort
Vorwort des Gutachters
1 Einstieg in C
2 Das erste Programm
3 Grundlagen
4 Formatierte Ein-/Ausgabe mit »scanf()« und »printf()«
5 Basisdatentypen
6 Operatoren
7 Typumwandlung
8 Kontrollstrukturen
9 Funktionen
10 Präprozessor-Direktiven
11 Arrays
12 Zeiger (Pointer)
13 Kommandozeilenargumente
14 Dynamische Speicherverwaltung
15 Strukturen
16 Ein-/Ausgabe-Funktionen
17 Attribute von Dateien und das Arbeiten mit Verzeichnissen (nicht ANSI C)
18 Arbeiten mit variabel langen Argumentlisten – <stdarg.h>
19 Zeitroutinen
20 Weitere Headerdateien und ihre Funktionen (ANSI C)
21 Dynamische Datenstrukturen
22 Algorithmen
23 CGI mit C
24 MySQL und C
25 Netzwerkprogrammierung und Cross–Plattform-Entwicklung
26 Paralleles Rechnen
27 Sicheres Programmieren
28 Wie geht’s jetzt weiter?
A Operatoren
B Die C-Standard-Bibliothek
Stichwort

Buch bestellen
Ihre Meinung?

Spacer
<< zurück
C von A bis Z von Jürgen Wolf
Das umfassende Handbuch
Buch: C von A bis Z

C von A bis Z
3., aktualisierte und erweiterte Auflage, geb., mit CD und Referenzkarte
1.190 S., 39,90 Euro
Rheinwerk Computing
ISBN 978-3-8362-1411-7
Pfeil 17 Attribute von Dateien und das Arbeiten mit Verzeichnissen (nicht ANSI C)
Pfeil 17.1 Attribute einer Datei ermitteln – »stat()«
Pfeil 17.1.1 »stat()« – »st_mode«
Pfeil 17.1.2 »stat()« – »st_size«
Pfeil 17.1.3 »stat()« – »st_atime«, »st_mtime« und »st_ctime«
Pfeil 17.1.4 »stat()« – »st_gid« und »st_uid«
Pfeil 17.1.5 »stat()« – »st_nlink«, »st_ino«
Pfeil 17.1.6 »stat()« – »st_dev«, »st_rdev«
Pfeil 17.2 Prüfen des Zugriffsrechts – »access()«
Pfeil 17.3 Verzeichnisfunktionen
Pfeil 17.3.1 Verzeichnis erstellen, löschen und wechseln – »mkdir()«, »rmdir« und »chdir«
Pfeil 17.3.2 In das Arbeitsverzeichnis wechseln – »getcwd()«
Pfeil 17.3.3 Verzeichnisse öffnen, lesen und schließen – »opendir()«, »readdir()« und »closedir()«

Das Ermitteln der Eigenschaften einer Datei oder das Öffnen und Auslesen eines Verzeichnisses sind systemabhängig. Denn jedes Betriebssystem verwaltet Dateien und Verzeichnisse auf andere Art. Daher wird in Büchern oft auf dieses Thema verzichtet. In diesem Kapitel versuche ich, es so universell wie möglich zu behandeln.

17 Attribute von Dateien und das Arbeiten mit Verzeichnissen (nicht ANSI C)


Rheinwerk Computing - Zum Seitenanfang

17.1 Attribute einer Datei ermitteln – »stat()« Zur nächsten ÜberschriftZur vorigen Überschrift

Der Funktion stat() wird die Adresse der Struktur struct stat übergeben. Aus dieser Struktur können die Attribute der Datei ausgelesen werden. Die Syntax dazu lautet:

#include <sys/stat.h>    /* LINUX/UNIX     */
#include <sys/types.h>   /* LINUX/UNIX     */
#include <sys\stat.h>    /* MS-DOS/WINDOWS */

int stat(const char *pfad, struct stat *puffer);

Mit stat() werden somit die Attribute der Datei, die Sie mit pfad angeben, in die Adresse der Strukturvariablen puffer geschrieben. Ein Beispiel:

struct stat attribut;
stat("testprogramm.txt", &attribut);
...
if(attribut.st_mode & S_IFCHR)
   printf("Datei ist eine Gerätedatei");

Hiermit wird getestet, ob die Datei testprogramm.txt eine Gerätedatei ist.

Es folgt eine Auflistung der einzelnen Variablen der Struktur struct stat, in der sich die jeweiligen Attribute zu einer Datei befinden. Dabei ist wiederum anzumerken, dass es Unterschiede zwischen Linux/UNIX und MS-DOS/Windows gibt. Tabelle 17.1 enthält die einzelnen Elemente der Struktur stat.


Tabelle 17.1 Bedeutung der einzelnen Strukturvariablen in »stat( )«

Variable Bedeutung
st_dev

Gerätenummer (Device-Nummer) des Dateisystems

st_ino

Inode-Nummer (nur Linux)

st_mode

Dateimodus (Dateityp und Zugriffsrechte)

st_nlink

Anzahl fester Links auf die Datei (bei MS-DOS/Windows immer 1)

st_uid

numerische UID des Dateieigentümers

st_gid

numerische GID des Dateieigentümers

st_rdev

Geräte-ID (nur für Spezialdateien; bei MS-DOS/Windows st_dev)

st_size

Größe der Datei in Bytes

st_atime

Datum des letzten Zugriffs

st_mtime

Datum der letzten Veränderung (bei MS-DOS/Windows st_atime)

st_ctime

Datum der Inode-Änderung (bei MS-DOS/Windows st_atime)

st_blksize

eingestellte Blockgröße (nicht überall vorhanden)

st_blocks

Anzahl der verwendeten st_blksize-Blöcke (nicht überall vorhanden)



Rheinwerk Computing - Zum Seitenanfang

17.1.1 »stat()« – »st_mode« Zur nächsten ÜberschriftZur vorigen Überschrift

Mit dem Strukturelement short st_mode in der Struktur stat können Sie die Dateiart erfragen. Dazu verknüpfen Sie den bitweisen UND-Operator (&) und den in st_mode gespeicherten Wert mit einer der Konstanten aus Tabelle 17.2.


Tabelle 17.2 Dateimodus (Dateityp erfragen)

Konstante Bedeutung
S_IFREG

reguläre Datei

S_IFDIR

Verzeichnis

S_IFCHR

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)


POSIX schreibt diese Konstanten allerdings nicht vor. Bei Linux/UNIX-Systemen könnten diese Konstanten auch als entsprechende Makros in der Headerdatei <sys/stat.h> implementiert sein. Der Makroname entspricht dabei dem Konstantennamen (S_IFREG(), S_IFDIR(), S_IFCHR(), S_ISBLK(), S_ISFIFO(), S_IS–LINK() und S_ISSOCK()). Alle diese Makros geben 1 zurück, wenn Entsprechendes zutrifft, ansonsten 0.

Im folgenden Listing können Sie über Argumente aus der Kommandozeile beliebig viele Dateien dahingehend abfragen, ob es sich um eine reguläre Datei (S_IFREG), eine zeichenorientierte Gerätedatei (S_IFCHR) oder ein Verzeichnis (S_IFDIR) handelt.

/* file_chk.c */
#include <stdio.h>
#include <stdlib.h>
#ifdef __unix__
      #include <unistd.h>
      #include <sys/stat.h>
      #include <sys/types.h>
#else
      #include <sys\stat.h>
#endif

int main(int argc, char *argv[]) {
   struct stat attribut;

   if(argc == 1) {
      printf("%s = ",*argv);
      if(stat(*argv, &attribut) == -1) {
         fprintf(stderr,"Fehler bei stat ...\n");
         return EXIT_FAILURE;
      }
      if(attribut.st_mode & S_IFREG)
         printf("Reguläre Datei\n");
      else if(attribut.st_mode & S_IFDIR)
         printf("Directory\n");
      else if(attribut.st_mode & S_IFCHR)
         printf("Gerätedatei\n");
      else
         printf("Unbekannte Datei\n");
   }
   else {
      while(*++argv) {
         printf("%s = ",*argv);
         if(stat(*argv, &attribut) == -1) {
            fprintf(stderr,"Fehler bei stat (2)...\n");
            return EXIT_FAILURE;
         }
         if(attribut.st_mode & S_IFREG)
            printf("Reguläre Datei\n");
         else if(attribut.st_mode & S_IFDIR)
            printf("Directory\n");
         else if(attribut.st_mode & S_IFCHR)
            printf("Gerätedatei\n");
         else
            printf("Unbekannte Datei\n");
      }/* Ende while */
   }
   return EXIT_SUCCESS;
}

Abbildung 17.1 Erfragen der Dateiart mit »st_mode«

Zuerst werden in der Schleife mit

if(stat(*argv, &attribut) == -1)

die Attribute der Datei *argv in die Adresse der Strukturvariablen attribut geschrieben. Anschließend werden einige Attribute mit den folgenden Zeilen abgefragt, um zu ermitteln, um welche Dateiart es sich hierbei handelt:

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

Danach fährt die Programmausführung mit dem nächsten Argument in der Kommandozeile fort.

Wenn sich das Listing bei Ihnen nicht übersetzen lässt und Sie unter Linux/UNIX arbeiten, sollten Sie es mit den entsprechenden Makros probieren:

if( S_IFREG(attribut.st_mode) )
   printf("Reguläre Datei\n");
else if( S_IFDIR(attribut.st_mode) )
   printf("Directory\n");
else if( S_IFCHR(attribut.st_mode) )
   printf("Gerätedatei\n");
else
   printf("Unbekannte Datei\n");

Mit dem Strukturelement st_mode in der Struktur stat lassen sich die Zugriffsrechte einer Datei ebenfalls abfragen. Dies funktioniert genauso wie bei der Abfrage der Dateiart. Zudem müssen Sie den bitweisen UND-Operator (&) mit einer der unter Linux/UNIX vorgegebenen Konstanten verknüpfen (siehe Tabelle 17.3).


Tabelle 17.3 Dateimodus (Rechte erfragen) unter Linux/UNIX

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


Bei MS-DOS/Windows gibt es zum Erfragen der Zugriffsrechte die Möglichkeiten, die Tabelle 17.4 aufführt.


Tabelle 17.4 Dateimodus (Rechte erfragen) unter MS-DOS/Windows

Konstante Bedeutung
S_IWRITE

nur Schreibrecht

S_IREAD

nur Leserecht

S_IEXEC

Ausführen erlaubt bzw. Verzeichnis durchsuchen erlaubt


Hierzu ein Beispiel für Linux/UNIX:

/* check_rwx.c */
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>

int main(int argc, char *argv[]) {
   struct stat attribut;
   int i;
   char l_rwx[10];
   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 */
   };
   while(*++argv) { /* einzelne Argumente durchlaufen */
      l_rwx[0]='\0';
      printf("%18s = ",*argv);
      if(stat(*argv, &attribut) == -1) {
         fprintf(stderr,"Fehler bei stat?!?...\n");
         return EXIT_FAILURE;
      }
      for(i = 0; i < 9; i++) {
         /* wenn nicht 0, dann gesetzt */
         if(attribut.st_mode & bits[i])
            l_rwx[i]=rwx[i];  /*r,w oder x*/
         else
            l_rwx[i] = '-'; /*wenn nicht gesetzt, dann '-'*/
      }
      l_rwx[9]='\0';
      printf("%s\n",l_rwx);
   }/*Ende while*/
   return EXIT_SUCCESS;
}

Abbildung 17.2 Ausgabe der Zugriffsrechte unter Linux/UNIX

Dieses Listing stellt eine einfache Methode dar, wie die Zugriffsrechte einer Datei oder eines Verzeichnisses in gewohnter Linux-Manier ausgegeben werden können. Bei MS-DOS/Windows können Sie so vorgehen:

if(attribut.st_mode & S_IREAD)
 { /* Datei darf nur gelesen werden */ }
else if(attribut.st_mode & S_IWRITE)
 { /* Datei darf beschrieben werden */ }
else if(attribut.st_mode & S_IEXEC)
 { /* Datei ist eine ausführbare (bsp. *.exe */ }

Wird hingegen bei Linux/UNIX die oktale Darstellung der Zugriffsrechte benötigt, können Sie dies folgendermaßen erreichen:

/* permission_oct.c */
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>

int main(int argc, char *argv[]) {
   struct stat attribut;

   while(*++argv) { /* einzelne Argumente durchlaufen */
      printf("%18s = ",*argv);
      if(stat(*argv, &attribut) == -1) {
         fprintf(stderr,"Fehler bei stat?!?...\n");
         return EXIT_FAILURE;
      }
      printf("%o\n", attribut.st_mode & 0777);
   }
   return EXIT_SUCCESS;
}

Rheinwerk Computing - Zum Seitenanfang

17.1.2 »stat()« – »st_size« Zur nächsten ÜberschriftZur vorigen Überschrift

Kommen wir nun zu einem weiteren Parameter der Struktur stat. Um die Größe einer Datei in Bytes zu ermitteln, kann die Strukturvariable st_size verwendet werden. Ein Wert wird aber nur für reguläre Dateien und Verzeichnisse (bei MS-DOS/Windows 0 für Verzeichnisse) zurückgegeben. Beim Filesystem werden dabei nicht die einzelnen Bytes angegeben, sondern immer ganze Blöcke von Bytes. Typische Blockgrößen sind 512 oder 1024 Bytes. Das bedeutet, die Variable von st_size gibt nicht den physikalischen Speicher einer Datei aus, den diese wirklich belegt. Das folgende Programm gibt die Größe aller Dateien auf dem Bildschirm aus, die Sie in der Kommandozeile angeben.

/* size.c */
#include <stdio.h>
#include <stdlib.h>
#ifdef __unix__
      #include <sys/stat.h>
      #include <sys/types.h>
#else
      #include <sys\stat.h>
#endif

int main(int argc, char *argv[]) {
   struct stat attribut;
   unsigned long sizeofall=0;

   if(argc == 1) {
      if(stat(*argv, &attribut) == -1) {
         fprintf(stderr,"Fehler bei stat....\n");
         return EXIT_FAILURE;
      }
      else {
         printf("Größe von %s = %ld Bytes\n",
            *argv,attribut.st_size);
         return EXIT_SUCCESS;
      }
   }
   else {
      while(*++argv) {
         if(stat(*argv, &attribut) == -1) {
            fprintf(stderr,"Fehler bei stat....\n");
            return EXIT_FAILURE;
         }
         else {
            printf("Größe von %s = %ld Bytes\n",
               *argv,attribut.st_size);
            sizeofall += attribut.st_size;
         }
      }
   }
   printf("Größe aller Dateien in der "
          " Kommandozeile = %ld Bytes",sizeofall);
   printf("= %ld KB\n",sizeofall/=1024);
   return EXIT_SUCCESS;
}

Abbildung 17.3 Größe von Dateien mit »st_size« ermitteln

Wie ich bereits erwähnt habe, gelingt es unter Windows/MS-DOS nicht, die Größe eines Verzeichnisses zu erhalten. Bei UNIX/Linux hingegen funktioniert das schon, da Verzeichnisse hier wie normale Dateien behandelt werden.


Rheinwerk Computing - Zum Seitenanfang

17.1.3 »stat()« – »st_atime«, »st_mtime« und »st_ctime« Zur nächsten ÜberschriftZur vorigen Überschrift

Um spezielle Zeitdaten einer Datei abzufragen, befinden sich in der Struktur stat folgende Variablen:

  • st_atime = Zeit des letzten Zugriffs
  • st_mtime = Zeit der letzten Änderung des Dateiinhalts
  • st_ctime = Zeit der letzten Inode-Änderung

Hinweis

Mit einer Inode werden unter Linux/UNIX Verwaltungsinformationen von den eigentlichen Daten getrennt gespeichert. Diese Inode-Informationen sind dabei Merkmale wie Zugriffszeit, Rechte, Größe und weitere Angaben. Die einzige Information, die nicht zur Inode gehört, ist der Name der Datei.


Die Unterscheidung dieser drei Zeitattribute trifft nur für Linux/UNIX zu. Bei MS-DOS/Windows bedeuten alle drei Zeiten dasselbe: nämlich den Zeitpunkt, zu dem die Datei das letzte Mal geändert wurde. Dazu ein Beispiel: Von allen Dateien, die Sie in der Kommandozeile eingeben, wird die Zeit des letzten Zugriffs und die Zeit der letzten Änderung ausgegeben:

/* ch_time.c */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#ifdef __unix__
      #include <sys/stat.h>
      #include <sys/types.h>
#else
      #include <sys\stat.h>
#endif

int main(int argc, char *argv[]) {
   struct stat attribut;
   unsigned long sizeofall=0;

   if(argc == 1) {
      if(stat(*argv, &attribut) == -1) {
         fprintf(stderr,"Fehler bei stat....\n");
         return EXIT_FAILURE;
      }
      else {
         printf("Groesse von %s = %ld Bytes\n",
            *argv,attribut.st_size);
         printf("letzter Zugriff : %s",
            ctime(&attribut.st_atime));
         printf("letzte Aenderung: %s",
            ctime(&attribut.st_mtime));
         return EXIT_SUCCESS;
      }
   }
   else {
      while(*++argv) {
         if(stat(*argv, &attribut) == -1) {
            fprintf(stderr,"Fehler bei stat....\n");
            return EXIT_FAILURE;
         }
         else {
            printf("Groesse von %s = %ld Bytes\n",
                *argv,attribut.st_size);
            printf("letzter Zugriff : %s",
               ctime(&attribut.st_atime));
            printf("letzte Aenderung: %s\n",
               ctime(&attribut.st_mtime));
            sizeofall += attribut.st_size;
         }
      }
   }
   printf("Groesse aller Dateien in der "
          "Kommandozeile = %ld Bytes",sizeofall);
   printf("= %ld KB\n",sizeofall/=1024);
   return EXIT_SUCCESS;
}

Abbildung 17.4 Abfragen verschiedener Zeitdaten unter Linux

Das Programm wurde mit dem vorherigen Beispiel vermischt. Auf diese Weise wird gleichzeitig die Größe der Datei inklusive der letzten Änderung und des letzten Zugriffs auf die Datei ausgegeben.

Unter Linux lässt sich außerdem mithilfe der Variablen st_atime und st_mtime beim Kopieren einer Datei verhindern, dass diese beiden Werte verändert werden. Gemeint ist damit Folgendes: Wenn Sie eine Datei beispielsweise mit cp kopieren, werden normalerweise alle drei Werte auf das aktuelle Datum gesetzt. Wollen Sie das Datum des Originals erhalten (letzter Zugriff und Änderung des Inhalts), können Sie folgendermaßen vorgehen:

/* manipulate_time.c */
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <utime.h>
#include <fcntl.h>

int main(int argc, char *argv[]) {
   FILE *q,*z;
   struct stat attribut;
   char buf[1024];
   int i;
   struct utimbuf zeit;  /* siehe Funktion utimes() */

   if(stat(argv[1],&attribut) < 0) {
      fprintf(stderr, "Fehler bei stat ...\n");
      return EXIT_FAILURE;
   }
   zeit.actime = attribut.st_atime;
   zeit.modtime= attribut.st_mtime;

   q=fopen(argv[1],"r");
   z=fopen(argv[2],"w");
   if(q == NULL || z == NULL) {
      fprintf(stderr,"Fehler bei fopen ...\n");
      return EXIT_FAILURE;
   }
   while( (i=fread(buf, 1, 1024, q)) > 0 )
      fwrite(buf, 1, i, z);

   /* Wichtig!!! Ohne den Stream zu schließen, wird die
    * aktuelle Zeit verwendet, da die Datei erst nach
    * return 0 beendet wird. */
   fclose(q);
   fclose(z);
   /* Jetzt die Zeit von quelle in ziel eintragen */
   if(utime(argv[2], &zeit) < 0) {
      printf("Fehler bei utime() ...\n");
      return EXIT_FAILURE;
   }
   return EXIT_SUCCESS;
}

Kopieren Sie einmal eine Datei mittels cp, und sehen Sie sich die Zeiten mit ls –l, ls -lu und ls -lc an. Bei der Überprüfung der Zeitangabe werden Sie feststellen, dass alle drei Zeitdaten auf dieselbe Zeit gesetzt wurden.

Wiederholen Sie dies nun mit dem eben geschriebenen Programm. Bei einem erneuten Blick auf die Zeitdaten sind die Variablen st_atime und st_mtime jetzt identisch mit der Originaldatei. Hätten Sie in diesem Listing fclose() nicht oder erst nach der Funktion utime() verwendet, so würde wieder der aktuelle Zeitstempel gesetzt, da dies den letzten Zugriff darstellt.

Wollen Sie herausfinden, welche von zwei Dateien älter ist, können Sie dies mit der Strukturvariablen st_mtime ermitteln:

/* older_file.c */
#include <sys/stat.h>
#include <stdio.h>
#include <time.h>
#include <stdlib.h>

time_t st_mTime(char *name) {
   struct stat s;

   if (stat(name, &s)) {
      perror(name);
      exit(EXIT_FAILURE);
   }
   return s.st_mtime;
}

int main(int argc, char *argv[]) {
   time_t t1, t2;

   if (argc == 3) {
      t1 = st_mTime(argv[1]),
      t2 = st_mTime(argv[2]);
      if(t1 != t2)
         printf("%s ist %s wie %s\n"
          ,argv[1],(t1>t2?"neuer":"älter"),argv[2]);
      else
         printf("Beide Dateien sind gleich alt\n");
   }
   else {
      fprintf(stderr, "Verwendung %s datei1 datei2\n",argv[0]);
      return EXIT_FAILURE;
   }
   return EXIT_SUCCESS;
}

In diesem Listing wurde die Headerdatei <time.h> verwendet, um den Rückgabetyp time_t zu verwenden. Zu dieser Headerdatei finden Sie im Buch noch einen eigenen Abschnitt (19.1).


Rheinwerk Computing - Zum Seitenanfang

17.1.4 »stat()« – »st_gid« und »st_uid« Zur nächsten ÜberschriftZur vorigen Überschrift

Um herauszufinden, wer der Eigentümer und der Gruppeneigentümer einer Datei ist, können Sie sich der Variablen st_uid (Eigentümer) und st_gid (Gruppeneigentümer) bedienen. Hierzu das Listing:

/* ugid.c */
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>

int main(int argc, char *argv[]){
   struct stat attribut;

   while(*++argv) {
      if(stat(*argv,&attribut) < 0) {
         fprintf(stderr, "Fehler bei stat ...\n");
         return EXIT_FAILURE;
      }
      printf("\n%18s\n", *argv);
      printf("USER-ID  : %d\n", attribut.st_uid);
      printf("GROUP-ID : %d\n\n", attribut.st_gid);
   }
   return EXIT_SUCCESS;
}

Rheinwerk Computing - Zum Seitenanfang

17.1.5 »stat()« – »st_nlink«, »st_ino« Zur nächsten ÜberschriftZur vorigen Überschrift

Weitere Informationen zu einer Datei unter Linux lassen sich mit den Variablen st_nlink (Anzahl der Links) und st_ino (Inode-Nummer der Datei) ausgeben:

/* link_ino.c */
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>

int main(int argc, char *argv[]){
   struct stat attribut;

   while(*++argv) {
      if(stat(*argv,&attribut) < 0) {
         fprintf(stderr, "Fehler bei stat ...\n");
         return EXIT_FAILURE;
       }
       printf("\n%18s\n",*argv);
       printf("Anzahl Links  : %d\n",attribut.st_nlink);
       printf("Inode Nummer  : %d\n\n",attribut.st_ino);
   }
   return EXIT_SUCCESS;
}

Rheinwerk Computing - Zum Seitenanfang

17.1.6 »stat()« – »st_dev«, »st_rdev« topZur vorigen Überschrift

Die Strukturvariablen st_dev und st_rdev sind recht nützlich für Gerätedateien. Bei MS-DOS/Windows haben beide Variablen dieselbe Bedeutung:

  • st_dev – enthält für jeden Dateinamen die Gerätenummer des Filesystems, in dem sich diese Dateien und ihr zugehöriger Inode befinden. (Windows/MS-DOS und Linux/UNIX).
  • st_rdev – hat nur für zeichen- und blockorientierte Gerätedateien einen definierten Wert, nämlich die Gerätenummer des zugeordneten Geräts. Die majornummer legt den Gerätetyp fest, während der minornummer der entsprechende Gerätetreiber übergeben wird. So werden verschiedene Geräte des gleichen Typs unterschieden (nur Linux/UNIX).

Das Folgende ist ein Beispielprogramm nur für MS-DOS/Windows. Das Programm liefert zu angegebenen Dateinamen den Laufwerksnamen zurück:

/* lfwrk.c */
#include <stdio.h>
#include <stdlib.h>
#include <sys\stat.h>

int main(int argc, char *argv[]) {
   struct stat laufwerknr;

   if(argc==1) {
      fprintf(stderr, "usage:%s Datei1 Datei2 Datei3\n", *argv);
      return EXIT_FAILURE;
   }
   while(*++argv) {
      printf("%s = Laufwerk : ",*argv);
      if(stat(*argv, &laufwerknr) == -1) {
         fprintf(stderr,"..Fehler bei stat...!\n");
         return EXIT_FAILURE;
      }
      else
         printf("%c (%d)\n",
            laufwerknr.st_dev + 'A',laufwerknr.st_dev);
   }
   return EXIT_SUCCESS;
}

Abbildung 17.5 Ermittlung des Laufwerks, in dem sich die Datei befindet

Ein kurze Erklärung zu:

laufwerknr.st_dev + 'A'

Da der PC die Laufwerke nicht – wie Sie es gewohnt sind – mit

A:\ = 1. Diskettenlaufwerk
B:\ = 2. Diskettenlaufwerk
C:\ = 1.Festplatte
D:\ = 2.Festplatte oder CD-ROM-Laufwerk
................usw. bis Z:\ falls vorhanden

erkennt, sondern mit Nummern wie

0 = 1. Diskettenlaufwerk
1 = 2. Diskettenlaufwerk
2 = 1.Festplatte
3 = 2.Festplatte oder CD-ROM-Laufwerk

wurde einfach die dezimale Ziffer 0 + 'A' hinzuaddiert. Dies gelingt, weil das Zeichen 'A' intern für den Wert 65 steht (siehe ASCII-Tabelle) und anschließend auch das Formatzeichen char für 65 (%c = char) ausgegeben wird. Somit wird z. B. für das Laufwerk 2 der Buchstabe C zurückgegeben (2+'A' = 67; ASCII-codiert = 'C').

Das Beispiel dazu für Linux/UNIX sieht so aus:

/* b_c_file.c */
#include <sys/sysmacros.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <stdio.h>

int main(int argc, char *argv[]) {
   struct stat statpuffer;

   if(argc == 1) {
      fprintf(stderr, "usage: %s Datei1 Datei2 ....\n", *argv);
      return EXIT_FAILURE;
   }
   while(*++argv) {
      printf("%s: ",*argv);
      if(stat(*argv, &statpuffer) == -1)
         fprintf(stderr,"Fehler bei stat...\n");
      else {
         printf("dev = %2d/%2d",major(statpuffer.st_dev),
                                minor(statpuffer.st_dev));
         if(S_ISCHR(statpuffer.st_mode)||
            S_ISBLK(statpuffer.st_mode)) {
            printf("-> rdev = %2d/%2d (%s",
               major(statpuffer.st_rdev),
               minor(statpuffer.st_rdev),
               (S_ISCHR(statpuffer.st_mode))?"zeichen" :"block");
            printf("orientiert");
         }
      }
      printf("\n");
   }
   return EXIT_SUCCESS;
}

Vielleicht noch ein Wort zu dieser Zeile:

if(S_ISCHR(statpuffer.st_mode)||
   S_ISBLK(statpuffer.st_mode))

Hiermit wird überprüft, ob es sich um eine zeichenorientierte (S_ISCHR) oder eine blockorientierte (S_ISBLK) Gerätedatei handelt. Es erfolgt dann eine entsprechende Ausgabe.



Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen. >> Zum Feedback-Formular
<< zurück
  
  Zum Katalog
Zum Katalog: C von A bis Z

 C von A bis Z
Jetzt bestellen


 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps
Zum Katalog: C/C++






 C/C++


Zum Katalog: Einstieg in C






 Einstieg in C


Zum Katalog: Schrödinger programmiert C++






 Schrödinger
 programmiert C++


Zum Katalog: C++ Handbuch






 C++ Handbuch


Zum Katalog: IT-Handbuch für Fachinformatiker






 IT-Handbuch für
 Fachinformatiker


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo




Copyright © Rheinwerk Verlag GmbH 2009
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.


[Rheinwerk Computing]

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