| #include <pronix.de> |
|
|
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.
20.1. Attribute einer Datei ermitteln-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) |
20.1.1 stat() - st_mode
Mit dem Strukturelement short st_mode in der Struktur stat können Sie die Dateiart erfragen. Dies funktioniert, in dem der bitweise UND-Operator (&) und der in st_mode gespeicherte Wert mit einer der folgenden Konstanten verknüpft wird:
| Konstante | Bedeutung |
| S_IFREG | Reguläre Datei |
| S_IFDIR | Verzeichnis |
| S_IFCHR | Zeichenorientierte Gerätedatei |
| S_ISBLK | Blockorientierte Gerätedatei |
| S_ISFIFO | Pipe oder FIFO |
| 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:
#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");
exit (1);
}
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");
exit (1);
}
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 0;
}

Abbildung 20.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 Strukturvariable 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:
| Konstante | Bedeutung |
| S_IRUSR | read (user; Leserecht für Eigentümer) |
| S_IWUSR | write (user; Schreibrecht für Eigentümer) |
| S_IXUSR | execute (user; Ausführrecht für Eigentümer) |
| S_IRGRP | read (group; Leserecht für Gruppe) |
| S_IWGRP | write (group; Schreibrecht für Gruppe) |
| S_IXGRP | execute (group; Ausführungsrecht für Gruppe) |
| S_IROTH | read (other; Leserecht für alle anderen Benutzer) |
| S_IWOTH | write (other; Schreibrecht für alle anderen Benutzer) |
| S_IXOTH | execute (other; Ausführungsrecht für alle anderen Benutzer) |
Bei MS-DOS/Windows gibt es zum Erfragen der Zugriffsrechte die folgenden Möglichkeiten:
| 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:
#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");
exit (0);
}
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 0;
}

Abbildung 20.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:
#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");
exit (1);
}
printf("%o\n", attribut.st_mode & 0777);
}/*Ende while*/
return 0;
}
20.1.2 stat() - st_size
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.
#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");
exit (1);
}
else
{
printf("Größe von %s = %ld Bytes\n"
,*argv,attribut.st_size);
exit (1);
}
}
else
{
while(*++argv)
{
if(stat(*argv, &attribut) == -1)
{
fprintf(stderr,"Fehler bei stat....\n");
exit (1);
}
else
{
printf("Größe von %s = %ld Bytes\n"
,*argv,attribut.st_size);
sizeofall+=attribut.st_size;
}
}/*Ende while*/
} /*Ende else*/
printf("Größe aller Dateien in der "
" Kommandozeile = %ld Bytes",sizeofall);
printf("= %ld KB\n",sizeofall/=1024);
return 0;
}

Abbildung 20.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.
20.1.3 stat() - st_atime, st_mtime und st_ctime
Um spezielle Zeitdaten einer Datei abzufragen, befinden sich in der Struktur stat folgende Variablen:
|
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:
#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");
exit (1);
}
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));
exit (1);
}
}
else
{
while(*++argv)
{
if(stat(*argv, &attribut) == -1)
{
fprintf(stderr,"Fehler bei stat....\n");
exit (1);
}
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;
}
} /*Ende while*/
} /*Ende else*/
printf("Größe aller Dateien in der "
"Kommandozeile = %ld Bytes",sizeofall);
printf("= %ld KB\n",sizeofall/=1024);
return 0;
}

Abbildung 20.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:
#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");
exit(0);
}
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");
exit(0);
}
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\n");
return 0;
}
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 Strukturvariable st_mtime ermitteln:
#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(0);
}
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 0;
}
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 22, Zeitroutinen.
20.1.4 stat() - st_gid und st_uid
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:
#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");
exit(0);
}
printf("\n%18s\n",*argv);
printf("USER-ID : %d\n",attribut.st_uid);
printf("GROUP-ID : %d\n\n",attribut.st_gid);
}
return 0;
}
20.1.5 stat() - st_nlink, st_ino
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.
#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");
exit(0);
}
printf("\n%18s\n",*argv);
printf("Anzahl Links : %d\n",attribut.st_nlink);
printf("Inode Nummer : %d\n\n",attribut.st_ino);
}
return 0;
}
20.1.6 stat() - st_dev, st_rdev
Die Strukturvariablen st_dev und st_rdev sind recht nützlich für Gerätedateien. Bei MS-DOS/Windows haben beide Variablen dieselbe Bedeutung:
Ein Beispielprogramm nur für MS-DOS/Windows. Das Programm liefert zu angegebenen Dateinamen den Laufwerksnamen zurück:
#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);
exit (1);
}
while(*++argv)
{
printf("%s = Laufwerk : ",*argv);
if(stat(*argv, &laufwerknr) == -1)
fprintf(stderr,"..Fehler bei stat...!\n");
else
printf("%c (%d)\n",
laufwerknr.st_dev + 'A',laufwerknr.st_dev);
}
return 0;
}

Abbildung 20.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:
#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);
exit (0);
}
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");
} /*Ende while*/
return 0;
}
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.
Mit der Funktion access() können Sie feststellen, ob ein Prozess bestimmte Berechtigungen für den Zugriff auf eine Datei hat. Die Syntax zur Funktion access() lautet:
#include <unistd.h> /* für UNIX/LINUX */ #include <io.h> /* für MS-DOS */ int access(const char *pfad, int modus);
So wird überprüft, ob der pfad der Datei existiert und die Zugriffsrechte modus besitzt. Folgende Zugriffsrechte (Modus) existieren:
| modus | Bedeutung |
| 00 oder F_OK | Datei existiert |
| 01 oder X_OK | Datei ausführbar (nur Linux/UNIX) |
| 02 oder W_OK | Datei beschreibbar |
| 04 oder R_OK | Datei lesbar |
| 06 oder W_OK|R_OK | Datei lesbar und beschreibbar |
Bei Erfolg gibt diese Funktion den Wert 0 zurück, ansonsten bei Fehler -1. Das folgende Listing überprüft die Zugriffsrechte aller in der Kommandozeile eingegebenen Programme mit der Funktion access():
#ifdef __unix__
#include <unistd.h>
#define EXIST F_OK
#define EXEC X_OK
#define WRITE W_OK
#define READ R_OK
#else
#include <io.h>
#define EXIST 00
#define EXEC 01
#define WRITE 02
#define READ 04
#endif
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
if(argc == 1)
{
fprintf(stderr,"Mindestens eine Datei angeben!\n");
exit (0);
}
while(*++argv)
{
printf("%s : \n",*argv);
/*Existiert die Datei?*/
if(access(*argv, EXIST) != -1)
{ /*Lesen und Schreiben nicht erlaubt*/
if(access(*argv, WRITE|READ) == -1)
{
/*Nur lesen?*/
if(access(*argv, READ) != -1)
printf("...ist lesbar\n");
/*Nur schreiben?*/
else if(access(*argv, WRITE) != -1)
printf("...ist schreibbar\n");
}
else
printf("ist Lesen und schreiben erlaubt\n");
/*Datei ausführbar?*/
if(access(*argv, EXEC) != -1)
printf("...ist ausführbar\n");
}
else
fprintf(stderr,"...existiert nicht\n");
} /*Ende while*/
return 0;
}
Zuerst wird überprüft, ob die Datei überhaupt existiert:
if(access(*argv, EXIST) != -1)
Ob die Datei zum Lesen und Schreiben freigegeben ist, wird anschließend mit der folgenden Zeile überprüft:
if(access(*argv, WRITE|READ) != -1)
Trifft dies nicht zu, werden die einzelnen Zugriffsmöglichkeiten getestet:
if(access(*argv, READ) != -1)
printf("...ist lesbar\n");
else if(access(*argv, WRITE) != -1)
printf("...ist schreibbar\n");
Die Überprüfung, ob die Datei ausführbar ist
if(access(*argv, EXEC) != -1)
kann bei Windows/MS-DOS entfernt werden, da sie nur unter UNIX/Linux einen Sinn ergibt. In diesem Listing wurden die Konstanten der einzelnen Zugriffsrechte hinter Makros versteckt, damit das Programm möglichst portabel bleibt. Unter Linux/UNIX werden übrigens nur die ersten drei User-Bits UID überprüft (rwx), also die Zugriffsrechte des Datei-Eigentümers. Es ist auch möglich, access() mit mehreren Konstanten zu verknüpfen:
if( (access(*argv,F_OK|R_OK) ) != -1) /* if( (access(*argv,00|04) ) != -1) */
Hier wird z.B. ermittelt, ob die Datei existiert und ob für sie Leserechte vorhanden sind.