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

 << zurück
C von A bis Z von Jürgen Wolf
Das umfassende Handbuch für Linux, Unix und Windows
– 2., aktualisierte und erweiterte Auflage 2006
Buch: C von A bis Z

C von A bis Z
1.116 S., mit CD, Referenzkarte, 39,90 Euro
Galileo Computing
ISBN 3-89842-643-2
gp Kapitel 19 Attribute von Dateien und Arbeiten mit Verzeichnissen (nicht ANSI C)
  gp 19.1 Attribute einer Datei ermitteln – stat()
    gp 19.1.1 stat() – st_mode
    gp 19.1.2 stat() – st_size
    gp 19.1.3 stat() – st_atime, st_mtime und st_ctime
    gp 19.1.4 stat() – st_gid und st_uid
    gp 19.1.5 stat() – st_nlink, st_ino
    gp 19.1.6 stat() – st_dev, st_rdev
  gp 19.2 Prüfen des Zugriffsrechts – access
  gp 19.3 Verzeichnis-Funktionen
    gp 19.3.1 Verzeichnis erstellen, löschen und wechseln – mkdir, rmdir und chdir
    gp 19.3.2 Wechseln in das Arbeitsverzeichnis – getcwd
    gp 19.3.3 Verzeichnisse öffnen, lesen und schließen – opendir, readdir und closedir

Kapitel 19 Attribute von Dateien und Arbeiten mit Verzeichnissen (nicht ANSI C)

Themen, wie 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 soll versucht werden, dieses Thema so universell wie möglich zu behandeln.


Galileo Computing - Zum Seitenanfang

19.1 Attribute einer Datei ermitteln – stat()  downtop

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

#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, welche 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, worin sich die jeweiligen Attribute zu einer Datei befinden. Wobei wiederum anzumerken ist, dass es Unterschiede zwischen Linux/UNIX und MS-DOS/Windows gibt. Hier die einzelnen Elemente der Struktur stat:


Tabelle 19.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)


Galileo Computing - Zum Seitenanfang

19.1.1 stat() – st_mode  downtop

Mit dem Strukturelement short st_mode in der Struktur stat können Sie die Dateiart erfragen. Dies funktioniert, indem der bitweise UND-Operator (&) und der in st_mode gespeicherte Wert mit einer der folgenden Konstanten verknüpft wird:


Tabelle 19.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_ISLINK() 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. Hier das Listing:

/* 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
Hier klicken, um das Bild zu Vergrößern

Abbildung 19.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:


Tabelle 19.3   Dateimodus (Rechte erfragen) (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 folgenden Möglichkeiten:


Tabelle 19.4   Dateimodus (Rechte erfragen) (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    /* Zugriffrechte 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
Hier klicken, um das Bild zu Vergrößern

Abbildung 19.2   Ausgabe der Zugriffsrechte unter Linux/UNIX

Dieses Listing stellt eine einfache Methode dar, wie die Zugriffsrechte einer Datei oder eines Verzeichnisses Linux-gewohnt ausgegeben werden können. Bei MS-DOS/Windows könnnen 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;
}

Galileo Computing - Zum Seitenanfang

19.1.2 stat() – st_size  downtop

Nun ein weiterer 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
Hier klicken, um das Bild zu Vergrößern

Abbildung 19.3   Größe von Dateien mit st_size ermitteln

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


Galileo Computing - Zum Seitenanfang

19.1.3 stat() – st_atime, st_mtime und st_ctime  downtop

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

gp  st_atime = Zeit des letzten Zugriffs
gp  st_mtime = Zeit der letzten Änderung des Dateiinhalts
gp  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, wann 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. Hier das Listing:

/* 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("Größe 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("Größe 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("Größe aller Dateien in der "
          "Kommandozeile = %ld Bytes",sizeofall);
   printf("= %ld KB\n",sizeofall/=1024);
   return EXIT_SUCCESS;
}

Abbildung
Hier klicken, um das Bild zu Vergrößern

Abbildung 19.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, wenn Sie eine Datei bspw. 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 in Kapitel 21, Zeitroutinen.


Galileo Computing - Zum Seitenanfang

19.1.4 stat() – st_gid und st_uid  downtop

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;
}

Galileo Computing - Zum Seitenanfang

19.1.5 stat() – st_nlink, st_ino  downtop

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;
}

Galileo Computing - Zum Seitenanfang

19.1.6 stat() – st_dev, st_rdev  toptop

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

gp  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).
gp  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).

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
Hier klicken, um das Bild zu Vergrößern

Abbildung 19.5   Ermittlung des Laufwerks, in welchem 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 daher, 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:

/* 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. Wenn ja, erfolgt eine dementsprechende Ausgabe.

 << zurück
  
  Zum Katalog
Zum Katalog: C von A bis Z
C von A bis Z
bestellen
 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps
Zum Katalog: Shell-Programmierung






 Shell-Programmierung


Zum Katalog: Linux-UNIX-Programmierung






 Linux-UNIX-Programmierung


Zum Katalog: C/C++






 C/C++


Zum Katalog: UML 2.0






 UML 2.0


Zum Katalog: Reguläre Ausdrücke






 Reguläre Ausdrücke


Zum Katalog: Linux






 Linux


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo





Copyright © Galileo Press 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.


[Galileo Computing]

Galileo Press, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de