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 2 E/A-Funktionen
  gp 2.1 Elementare E/A-Funktionen
  gp 2.2 Filedeskriptor
    gp 2.2.1 Verwaltung für offene Deskriptoren
  gp 2.3 Funktionen, die den Filedeskriptor verwenden
    gp 2.3.1 Datei öffnen – open()
    gp 2.3.2 Anlegen einer neuen Datei – creat()
    gp 2.3.3 Datei schließen – close()
    gp 2.3.4 Schreiben von Dateien – write()
    gp 2.3.5 Lesen von Dateien – read()
    gp 2.3.6 Schreib-/Lesezeiger positionieren – lseek()
    gp 2.3.7 Duplizieren von Filedeskriptoren – dup() und dup2()
    gp 2.3.8 Ändern oder Abfragen der Eigenschaften eines Filedeskriptors – fcntl()
    gp 2.3.9 Record Locking – Sperren von Dateien einrichten
    gp 2.3.10 Multiplexing E/A – select()
    gp 2.3.11 Unterschiedliche Operationen – ioctl()
    gp 2.3.12 Lesen und Schreiben mehrerer Puffer – writev() und readv()
    gp 2.3.13 Übersicht zu weiteren Funktionen, die den Filedeskriptor verwenden
  gp 2.4 Standard-E/A-Funktionen
    gp 2.4.1 Der FILE-Zeiger
    gp 2.4.2 Öffnen und Schließen von Dateien
    gp 2.4.3 Formatierte Ausgabe
    gp 2.4.4 Formatierte Eingabe
    gp 2.4.5 Binäres Lesen und Schreiben
    gp 2.4.6 Zeichen- und zeilenweise Ein-/Ausgabe
    gp 2.4.7 Status der Ein-/Ausgabe überprüfen
    gp 2.4.8 Stream positionieren
    gp 2.4.9 Puffer kontrollieren
    gp 2.4.10 Datei löschen und umbenennen
    gp 2.4.11 Temporäre Dateien erstellen
  gp 2.5 Mit Verzeichnissen arbeiten
    gp 2.5.1 Ein neues Verzeichnis anlegen – mkdir()
    gp 2.5.2 In ein Verzeichnis wechseln – chdir(), fchdir()
    gp 2.5.3 Ein leeres Verzeichnis löschen – rmdir()
    gp 2.5.4 Format eines Datei-Eintrags in struct dirent
    gp 2.5.5 Einen Verzeichnisstream öffnen – opendir()
    gp 2.5.6 Lesen aus dem DIR-Stream – opendir() und Schließen des DIR-Streams – closedir()
    gp 2.5.7 Positionieren des DIR-Streams
    gp 2.5.8 Komplettes Verzeichnis einlesen – scandir()
    gp 2.5.9 Ganze Verzeichnisbäume durchlaufen – ftw()
  gp 2.6 Fehlerbehandlung
  gp 2.7 Ausblick


Rheinwerk Computing

2.4 Standard-E/A-Funktionen  downtop

Um mit der Linux-Programmierung zu beginnen, habe ich Sie zu Beginn des Buches bereits darauf hingewiesen, dass die Voraussetzung in der Programmiersprache C gegeben sein muss. Und jedes gute Einsteiger-Buch zur C-Programmierung behandelt die grundlegenden Standard-E/A-Funktionen, und somit setze ich voraus, dass Sie damit schon vertraut sind. Daher werden Sie auf den folgenden Seiten nur eine Schnellübersicht zu den einzelnen Funktionen erhalten.

Die Funktionen, die hierbei beschrieben werden, sind in der Headerdatei <stdio.h> definiert und größtenteils von ANSI C vorgeschrieben. Der Vorteil dieser Funktionen gegenüber den elementaren ist, dass diese auch auf Betriebssystemen jenseits von Linux/UNIX vorhanden sind und Sie sich daher relativ wenig um Low-Level-E/A kümmern müssen, da mit optimal eingestellten Puffern gearbeitet wird.


Rheinwerk Computing

2.4.1 Der FILE-Zeiger  downtop

Der große Unterschied zwischen den elementaren und den Standard-E/A-Funktionen liegt darin, dass die Standardfunktionen einen Zeiger vom Typ FILE statt eines Filedeskriptors verwenden. Dabei handelt es sich um eine Struktur, die in etwa wie folgt aussieht:

typedef struct _iobuf {
  char*  _ptr;  
  int    _cnt;   
  char*  _base;  
  int    _flag;  
  int    _file;
  int    _charbuf;
  int    _bufsiz;
  char*  _tmpfname;
} FILE;

Darin sind Informationen enthalten wie:

gp  Anfangsadresse des Puffers
gp  Puffergröße
gp  aktueller Pufferzeiger
gp  Filedeskriptor
gp  Position des Schreib-/Lesezeigers
gp  Fehlerflag
gp  EOF-Flag

Wie Sie sicherlich bemerkt haben, verwenden die Standard-E/A-Funktionen auch einen Filedeskriptor. Daraus lässt sich schließen (Sie wissen es bereits), dass die Standardfunktionen auf den elementaren Funktionen aufgebaut sind.


Hinweis   Bei dem FILE-Zeiger spricht man auch von einem Datenstrom (englisch Stream).


Natürlich gibt es auch hierbei die drei vordefinierten Standardstreams, die jeder Prozess automatisch bereitstellt:

gp  FILE* stdin – Standard-engabestrom Iist voreingestellt auf die Tastatur.
gp  FILE* stdout – Standardausgabestrom ist voreingestellt auf den Monitor.
gp  FILE* stderr – Standardausgabestrom für Fehlermeldungen ist voreingestellt auf den Monitor.

Rheinwerk Computing

2.4.2 Öffnen und Schließen von Dateien  downtop

Hier die Funktionen zum Öffnen und Schließen unter der Verwendung des FILE-Zeigers:

FILE *fopen(const char *pfad, const char *mode);
FILE *fdopen(int fd, const char *mode);
FILE *freopen(const char *pfad, const char *mode, FILE *stream);
int fclose(FILE *stream);

Abgesehen von der Funktion fdopen() (es wurde bereits darüber geschrieben) sind alle Funktionen Teil des ANSI C-Standards. Bei allen Funktionen, mit Ausnahme von fclose(), wird im Falle eines Fehlers NULL, ansonsten der FILE-Zeiger zurückgeben.

Die Funktion fopen() öffnet eine Datei, die mit pfad angegeben wurde, im Modus mode. Die einzelnen Modi finden Sie in der gleich folgenden Tabelle aufgelistet.

Mit der Funktion freopen() können Sie eine Datei mit einem bereits existierenden Stream öffnen. Dabei wird versucht, erst diesen Stream (drittes Argument) zu schließen. Fehler beim Schließen werden dabei ignoriert! Anschließend wird versucht, diesen Stream der Datei pfad zuzuordnen. freopen() wird vorwiegend eingesetzt, um die Streams stdin, stdout und stderr umzuleiten.

Mit fclose() schließen Sie die Datei wieder. Zuvor werden alle noch nicht geschriebenen Daten im Ausgabepuffer in die entsprechende Datei geschrieben. Der Eingabepuffer hingegen wird geleert.

Hierzu jetzt die versprochene Tabelle mit den entsprechendegin Modi, die bei den eben erwähnten Funktionen für den Parameter mode verwendet werden können.


Tabelle 2.9    Modi zum Öffnen für den FILE-Zeiger

mode Lesen Schreiben Position Inhalt gelöscht Datei erzeugen Binär/Text
r ja nein Anfang nein nein Text
r+ ja ja Anfang nein nein Text
w nein ja Anfang ja ja Text
w+ ja ja Anfang ja ja Text
a nein ja Ende nein ja Text
a+ ja ja Ende nein ja Text
rb ja nein Anfang nein nein Binär
rb+, r+b ja ja Anfang nein nein Binär
wb nein ja Anfang ja ja Binär
wb+, w+b ja ja Anfang ja ja Binär
ab nein ja Ende nein ja Binär
ab+, a+b ja ja Ende nein ja Binär


Rheinwerk Computing

2.4.3 Formatierte Ausgabe  downtop

Zur formatierten Ausgabe auf einem Stream steht Ihnen die ganze printf()-Familie zur Verfügung. Mit diesen Funktionen dürfte auch niemand Probleme haben, wenn er nur geringe Erfahrungen in C hat. Hier der Überblick zu den nötigsten printf-Varianten und deren Bedeutung:


Tabelle 2.10    printf()-Varianten zur formatierten Ausgabe

Syntax Bedeutung
int printf( const char *format, ... ); Formatiert das Schreiben auf stdout.
int fprintf( FILE *stream, const char *format, ... ); Formatiert das Schreiben in einem Stream.
int sprintf( char *string, const char *format, ... ); Formatiert das Schreiben in einen String.
int snprintf( char *string, size_t size, const char format, ... ); Formatiert das Schreiben in einen String mit Längenbegrenzung (size).

Alle Funktionen geben die Anzahl der erfolgreich geschriebenen Zeichen oder bei einem Fehler einen negativen Wert zurück. Außerdem wird empfohlen, sprintf() zu vermeiden, da diese Funktion keine Längenüberprüfung vornimmt und somit anfällig für Buffer Overflows (und dadurch Stack Smashes) ist. Verwenden Sie stattdessen die n-Version snprintf(), sofern diese vorhanden ist. Sollte dies nicht der Fall sein, so empfiehlt sich ein »portables printf«, das Sie Ihrem Projekt hinzufügen können.

Neben diesen printf-Versionen gibt es noch die v-Versionen, womit der Funktion eine in der Länge variable Argumentenliste übergeben wird. Hier also die v-Versionen von printf:


Tabelle 2.11    Weitere printf()-Versionen mit <stdarg.h>

Syntax Bedeutung
int vprintf( const char *format, va_list ap ); Formatiert das Schreiben auf stdout mit Argumentenzeiger.
int vfprintf( FILE *stream, const char *format, va_list ap ); Formatiert das Schreiben in einem Stream mit Argumentenzeiger.
int vsprintf( char *string, const char *format, va_list ap ); Formatiert das Schreiben in einen String mit Argumentenzeiger.
int vsnprintf( char *string, size_t size, const char format, va_list ap ); Formatiert das Schreiben in einen String mit Argumentenzeiger inklusive einer Längenbegrenzung (size).

Bei den v-Versionen der printf-Familie müssen Sie die Headerdatei <stdarg.h> mit einbinden. Auch bei diesen printf-Versionen wird die Anzahl der erfolgreich geschriebenen Zeichen oder bei einem Fehler ein negativer Wert zurückgegeben.


Hinweis   Es ist noch anzumerken, dass es außerhalb des ANSI C-Standards noch eine Reihe weiterer printf() gibt wie z. B. asprintf(), vasprintf(), asnprintf(), vasnprintf().



Rheinwerk Computing

2.4.4 Formatierte Eingabe  downtop

Das Gegenstück zur printf-Familie ist die scanf-Familie, die zur formatierten Eingabe aus einem Stream konzipiert wurde. Auch hierbei gibt es verschiedene Versionen, die normale, die f-Versionen und die s-Verisonen.


Hinweis   Funktionen, die mit f beginnen, beziehen sich auf einen beliebigen Stream. Die Funktionen mit s stehen für die String-Versionen, und v steht für den Argumentenlistenzeiger. Die Versionen ohne eine Bezeichnung verwenden in der Regel den Standardstream, was bei scanf() stdin und bei printf() stdout wäre. Man sieht also, die Leute vom ANSI C-Komitee haben sich schon etwas bei der Namenskonvention gedacht. Natürlich können f-Versionen auch für die Standardstreams verwendet werden.


Hier ein Überblick zu den scanf-Versionen zur formatierten Eingabe:


Tabelle 2.12    scanf()-Varianten zur formatierten Eingabe

Syntax Bedeutung
int scanf( const char *format, ... ); Formatiertes Lesen von stdin
int fscanf( FILE *stream, const char *format,... ); Formatiertes Lesen aus einem beliebigen Stream
int sscanf( const char *string, const char *format, ... ); Formatiertes Lesen aus einem String

Alle Funktionen geben die Anzahl der gelesenen Zeichen oder bei einem Fehler EOF zurück.


Rheinwerk Computing

2.4.5 Binäres Lesen und Schreiben  downtop

Als wahrer Zwitter lassen sich die Funktionen fread() und fwrite() bezeichnen, da diese Funktionen weder zu 100 % in die höhere noch in die niedrigere Ebene zu passen scheinen. Die Daten werden dabei im Binärmodus mit einer festen Satzstruktur bearbeitet. Damit können Sie mit fread() und fwrite() ganze Speicherblöcke lesen bzw. schreiben. Hier die Syntax dazu:

#include <stdio.h>
size_t fread(void *ptr, size_t blkgroesse,
             size_t blkanzahl, FILE *stream);
size_t fwrite(const void *ptr, size_t blkgroesse,
               size_t blkanzahl, FILE *stream);

Beide Funktionen geben bei Erfolg die Anzahl der gelesenen bzw. geschriebenen Blöcke (nicht Bytes) zurück. Das erste Argument ist der Puffer, aus dem gelesen oder in dem geschrieben werden soll. Mit dem zweiten Argument geben Sie die Blockgröße an, die gelesen bzw. geschrieben werden soll. Das dritte Argument erwartet die Anzahl der Blöcke mit Blockgröße, und das letzte Argument ist der Stream, woraus gelesen bzw. wohin geschrieben werden soll. Eine Fehlerüberprüfung sollten Sie mit den Funktionen feof() und ferror() einrichten, um zu erfahren, was schief gelaufen ist.


Rheinwerk Computing

2.4.6 Zeichen- und zeilenweise Ein-/Ausgabe  downtop

Zur zeichen- und zeilenweisen Ein-/Ausgabe ist eine Menge Funktionen vorhanden. Diese Funktionen gibt es in zwei Geschmacksrichtungen, eine Sorte, die mit Zeichen handelt, und die andere, die mit Strings arbeitet. Hier die Syntax dieser Funktionen:

#include <stdio.h>
int fgetc( FILE *stream );
char *fgets(char *s, int size, FILE *stream );
int getc( FILE *stream );
int getchar(void );
char *gets( char *s );
int ungetc( int c, FILE *stream );
int fputc( int c, FILE *stream );
int fputs( const char *s, FILE *stream );
int putc( int c, FILE *stream );
int putchar( int c );
int puts( char *s );

Jede Funktion, die ein int liefert, gibt bei einem Fehler einen negativen Wert (EOF) zurück. Die Funktionen, die einen Zeiger auf ein char liefert, geben entweder die Anfangsadresse eines Strings zurück oder bei einem Fehler NULL. In der folgenden Tabelle sind diese Funktionen und ihre Eigenschaften nochmals zusammengefasst.


Tabelle 2.13    Zeichen- und zeilenweise E/A-Funktionen

Funktion E/A Größe Stream Newline
fgetc Eingabe Zeichen alle
fgets Eingabe Zeile alle behalten
getc Eingabe Zeichen alle
getchar Eingabe Zeichen stdin
gets Eingabe Zeile stdin entfernt
ungetc weder noch Zeichen alle
fputc Ausgabe Zeichen alle
fputs Ausgabe Zeile alle ohne
putc Ausgabe Zeichen alle
putchar Ausgabe Zeichen stdout
puts Ausgabe Zeile stdout mit

Es wird außerdem empfohlen, ganz auf die Funktion gets() zu verzichten und stattdessen die Funktion fgets() zu verwenden. gets() hat keine Längenbegrenzung und ist somit auch für den Buffer Overflows anfällig. Beachten Sie außerdem, dass fgets() das Newline-Zeichen anders behandelt als gets(). Weil beim Einlesen von der Standardeingabe mit fgets() auch das '\n'-Zeichen mit eingelesen wird, verwenden einige Programmierer, sei es aus Faulheit oder mangelndem Wissen, die Funktion gets() – die kein Newline-Zeichen anfügt.


Rheinwerk Computing

2.4.7 Status der Ein-/Ausgabe überprüfen  downtop

Mit den Funktionen feof() und ferror() können Sie den aktuellen Status eines Streams überprüfen. Hier die Syntax dazu:

#include <stdio.h>
int feof( FILE *stream );
int ferror( FILE *stream );
void clearerr( FILE *stream );

Die Funktion feof() gibt einen Wert ungleich 0 zurück, wenn das EOF-Flag gesetzt ist. Ebenso gibt die Funktion ferror() einen Wert ungleich 0 zurück, wenn das Fehlerflag gesetzt ist. Wollen Sie einen der beiden Funktionen nochmals auf einem Stream verwenden, müssen Sie das EOF-Flag bzw. das Fehlerflag mit der Funktion clearerr() wieder löschen.


Rheinwerk Computing

2.4.8 Stream positionieren  downtop

Das Positionieren des Dateizeigers funktioniert in der Regel ähnlich wie bei der niedrigeren Ebene. Im Prinzip verwendet man dabei auch die niedrigere Ebene, um den Schreib-/Lesezeiger zu versetzen. Hier ein Überblick über die Funktionen.


Tabelle 2.14    Dateiposition

Syntax Bedeutung
int fseek( FILE *stream, long offset, int wie ); Schreib-/Lesezeiger positionieren
long ftell( FILE *stream ); Position des Schreib-/Lesezeigers abfragen
void rewind( FILE *stream ); Schreib-/Lesezeiger wieder zurück an den Anfang positionieren
int fgetpos( FILE *stream, fpos_t *pos ); Position des Schreib-/Lesezeigers abfragen (2. Möglichkeit)
int fsetpos(FILE *stream, fpos_t *pos ); Schreib-/Lesezeiger positionieren (2. Möglichkeit)

Die Funktion fseek() funktioniert analog wie die Funktion lseek() der niedrigeren Ebene, nur dass hierbei statt eines Filedeskriptors ein FILE-Zeiger verwendet wird. Auch hierbei hängt es vom dritten Parameter ab, wie der zweite Parameter interpretiert werden soll. Dabei sind die gleichen Konstanten zu verwenden wie schon bei der Funktion lseek():


Tabelle 2.15    Konstanten für »wie«

Konstante Bedeutung
SEEK_SET Den Schreib-/Lesezeiger vom Anfang der Datei um abstand Bytes versetzen. abstand darf dabei keine negative Zahl sein.
SEEK_CUR Den Schreib-/Lesezeiger von der aktuellen Position der Datei um abstand Bytes versetzen. abstand darf dabei sowohl eine positive als auch eine negative Zahl sein.
SEEK_END Den Schreib-/Lesezeiger vom Ende der Datei um abstand Bytes versetzen. abstand darf dabei sowohl eine positive als auch eine negative Zahl sein.


Hinweis   Auch wenn fseek() hier dieselben Konstanten verwendet wie die Low-Level-Funktion lseek(), sollten Sie niemals Low-Level und High-Level-Funktionen in einer Anwendung vermischen, sofern man nicht Vorkehrungen dazu getroffen hat (z. B. durch fflush()), denn wie vorher erläutert, positioniert fseek() aufgrund der Pufferung nicht sofort.


Der erste Parameter ist der FILE-Zeiger der geöffneten Datei, wo der Schreib-/Lesezeiger versetzt werden soll. Bei Erfolg gibt fseek() 0, ansonsten bei einem Fehler ungleich 0 zurück.

Mit ftell() können Sie die aktuelle Position des Schreib-/Lesezeigers abfragen. Zurückgegeben wird dabei entweder die aktuelle Position in Bytes oder bei einem Fehler -1. Die aktuelle Position wird dabei vom Dateianfang zurückgegeben. fseek() und ftell() unterstützen trotz des o. g. LARGEFILE-Supports nur 32 Bit (wegen ihrer Prototypen). Dagegen kann ftello() / fseeko() helfen.

Mit der Funktion rewind() können Sie den Schreib-/Lesezeiger wieder auf den Dateianfang zurücksetzen, aber fseek(fp, 0, SEEK_SET) macht dasselbe und passt besser zu den anderen fseek() in Ihrer Anwendung.

Eine zweite Möglichkeit zur Positionierung des FILE-Zeigers haben Sie mit fsetpos(). Dabei können Sie den Schreib-/Lesezeiger auf die Position des Zeigers pos setzen. Diese Adresse sollten Sie allerdings zuvor mit der Funktion fgetpos() ermittelt haben. Diese Funktion setzt ebenfalls die EOF- und Fehlerflags zurück.

Mit fgetpos() ermitteln Sie die Position des aktuellen Schreib-/Lesezeigers. Dieser Wert befindet sich anschließend in der Adresse des Zeigers pos. Diesen Zeiger sollten Sie dann nur noch verwenden, um mit der Funktion fsetpos() den Schreib-/Lesezeiger wieder auf seinen ursprünglichen Wert zurückzusetzen.

Beide Funktionen, fgetpos() und fsetpos(), geben bei Erfolg 0 und bei einem Fehler ungleich 0 zurück.


Rheinwerk Computing

2.4.9 Puffer kontrollieren  downtop

Dem Programmierer stehen drei grundlegende Möglichkeiten zur Einstellung des Puffers der Standard-E/A-Funktionen zur Verfügung, ungepuffert, zeilengepuffert und voll gepuffert. Des Weiteren gibt es noch die Möglichkeit, alle Inhalte eines nicht geleerten Puffers in eine Datei zu übertragen. Hier die Funktionen, womit Sie den Puffer kontrollieren können:

#include <stdio.h>
int fflush(FILE *stream);
int setbuf(FILE *stream, char *buf);
int setvbuf(FILE *stream, char *buf, int mode, size_t size);

Die Funktion setbuf() wird nur noch aus Kompatibilitätsgründen erhalten und soll daher hier nicht näher erläutert werden. Mit der Funktion setvbuf() können Sie einen expliziten Puffer einstellen. Dazu müssen Sie nur für den Parameter mode eine der folgenden Konstanten einsetzen:


Tabelle 2.16    Konstanten für die Einstellung des Puffers mit setvbuf()

Puffertyp (modus) Bedeutung
_IOLBF Datei wird zeilenweise gepuffert .
_IONBF Ein-/Ausgabe wird gar nicht gepuffert .
_IOFBF Ein-/Ausgabe wird voll gepuffert.

Natürlich gilt, wenn für mode die Konstante _IONBF gesetzt wird, werden die Argumente buf und size ignoriert. Ansonsten geben Sie bei den Konstanten _IOLBF und _IOFBF mit buf die Pufferadresse und mit size die Puffergröße an. Verwenden Sie für buf den NULL-Zeiger, stellt die Funktion einen eigenen Puffer mit entsprechender Größe zur Verfügung. Diese Größe kann entweder der Wert von st_blksize der Struktur stat oder die Konstante BUFSIZ der Headerdatei <stdio.h> sein.

Bei alten BSD-Programmen kann es vorkommen, dass Sie die Funktionen setlinebuf() und setbuffer() sichten. Diese Funktionen gelten als veraltet, und es wird ebenfalls geraten, die Funktion setvbuf() zu verwenden.

Voreingestellte Puffer

Der ANSI C-Standard schreibt Folgendes für die Pufferung vor:

gp  stderr darf niemals voll gepuffert werden.
gp  stdin und stdout dürfen nur dann voll gepuffert sein, wenn diese nicht auf ein interaktives Gerät (z. B. Tastatur) zeigen.

In SVR 4 hingegen sind noch folgende Vorschriften implementiert:

gp  Normale Streams, die auf ein Terminal eingestellt sind, sind immer zeilengepuffert. Wenn sich diese Streams auf kein Terminal beziehen, wird Vollpufferung verwendet.
gp  stderr ist immer ungepuffert (siehe »ANSI C« oben, Punkt 1).

Flushing

Um den Inhalt von einem (möglicherweise nicht geleertem) Puffer zu leeren, können Sie die Funktion fflush() verwenden. Wenden Sie fflush() auf einen Stream an, aus dem gelesen wird, liegt ein undefiniertes Verhalten vor. Ebenfalls können Sie fflush() mit dem NULL-Zeiger als Argument aufrufen. In diesem Fall werden alle Ausgabepuffer, woraus nicht gelesen wird, übertragen.

Es gibt außerdem folgende Möglichkeiten, wie ein Puffer automatisch entleert wird. Wenn:

gp  der Puffer voll ist,
gp  der Stream geschlossen wird (fclose),
gp  das Programm normal beendet wird,
gp  eine neue Zeile geschrieben wird und der Stream zeilengepuffert ist.

Rheinwerk Computing

2.4.10 Datei löschen und umbenennen  downtop

Mit der Funktion remove() können Sie eine Datei entfernen, und mit rename() können Sie eine Datei umbenennen. Hier die Syntax der beiden Funktionen:.

#include <stdio.h>
int remove( const char *pfad );
int rename( const char *pfad_alt, const char *pfad_neu );

Beide Funktionen erwarten als erstes Argument den Pfadnamen einer existierenden Datei. Bei der Funktion rename() wird als zweites Argument angegeben, durch welchen Namen pfad_alt ersetzt werden soll. Bei Erfolg geben beide Funktionen 0 und bei einem Fehler -1 zurück.


Hinweis   Auf Dateien verhält sich remove() identisch zur Funktion unlink(), und auf Verzeichnissen ist remove() mit rmdir() äquivalent.



Rheinwerk Computing

2.4.11 Temporäre Dateien erstellen  toptop

Zum Erstellen von temporären Dateien können Sie entweder die ANSI C-Funktionen tmpfile() und tmpnam() verwenden oder die in UNIX implementierten Funktionen mkstemp() und mktemp().

#include <stdio.h>
FILE *tmpfile(void);
char *tmpnam(char *s);
#include <unistd. h.>
int mkstemp(char *template) ;
char *mktemp(char *template) ;

Die Funktion tmpfile() öffnet eine temporäre Datei. Mit tmpnam() kann ein Dateiname erstellt werden, der als Name für die temporäre Datei verwendet wird. Wird die Funktion tmpnam() mit dem NULL-Zeiger als Argument verwendet, wird die Datei in einem static-Speicherbereich untergebracht (was nicht thread-safe ist), und die Adresse wird als Funktionswert wiedergegeben. Das bedeutet, dass nachfolgende Aufrufe der Funktion tmpnam() dieselbe Adresse einnehmen. Aus diesem Grund sollte zuerst umkopiert werden, um die alte Adresse nicht zu überschreiben. Wird tmpnam() ohne den NULL-Zeiger aufgerufen, wird für s ein Adressbereich adressiert, der L_tmpnam Zeichen aufnehmen kann. L_tmpnam ist ebenso in der Headerdatei <stdio.h> deklariert.

Die Funktion mktemp() erzeugt einen eindeutigen, temporären Dateinamen. Dieser Name wird aus template erzeugt. Dazu müssen die letzten sechs Buchstaben des Parameters template XXXXXX sein, diese werden dann durch eine Zeichenfolge ersetzt, die diesen Dateinamen eindeutig macht. Die Funktion mktemp() gibt bei Erfolg einen Zeiger auf template zurück. Bei einem Fehler ist der Rückgabewert NULL. Der Fehlercode EINVAL wird zurückgegeben, wenn die letzten sechs Buchstaben von template nicht XXXXXX waren.

Es besteht allerdings ein (und nicht nur dieses) Sicherheitsloch bei dieser Funktion. Zwischen der Zeit, wo der Pfadname konstruiert und die Datei mit open() geöffnet wird, kann ein anderer Prozess eine Datei oder einen Link mit demselben Namen erzeugen. Um dieses Problem zu umgehen, sollten Sie den so erzeugten temporären Dateinamen beim Öffnen mit open() mit dem Flag O_EXCL öffnen oder gleich die Funktion mkstemp() verwenden. Das Flag O_EXCL garantiert Ihnen, dass diese Datei nur dann erzeugt wird, wenn der Name noch nicht existiert.

Die Funktion mkstemp()die einzige sicherere Alternative – erzeugt einen temporären Dateinamen und öffnet diese Datei mittels open() und dem Flag 0 EXCL gleich für Sie. Bei Erfolg gibt Ihnen diese Funktion einen Filedeskriptor zum Lesen und Schreiben auf diese temporäre Datei zurück. Dank des Flags O_EXCL ist sichergestellt, dass die so erzeugte temporäre Datei wirklich einzigartig ist. Die geöffnete Datei verwendet den Modus 0600 und ist standardmäßig nur dem Eigentümer vorbehalten. Wenn andere User darauf zugreifen sollen (dürfen), müssen Sie das ändern (z. B. mit fchmod(), fchown()). mkstemp() liefert bei einem Fehler -1 zurück, wenn die Datei nicht erzeugt oder geöffnet werden kann.

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