|
I-PROGRAMMIEREN1 WS 0203 - Vorlesung mit Übung
|
Bisher wurden drei Möglichkeiten vorgestellt, wie ein C-Programm mit seiner Umgebung Daten austauschen kann:
Über den Bildschirm (bekannt als 'stdout').
Durch Argumente auf der Befehlszeile
Mittels der Tastatur (bekannt als 'stdin')
Eine vierte Möglichkeit, mit der Umgebung Daten auszutauschen, ist jene über das Lesen und Schreiben von Dateien. Dies soll Gegenstand der heutigen Vorlesung sein.
Bei der Behandlung der Dateioperationen unter C muss man sich vor Augen halten, dass in C der Austausch von Daten zwischen Geräten wie Tastatur, Bildschirm, Plattenspeichern, und allen anderen peripheren Geräten in einheitlicher Weise mit dem Konzept der Streams beschrieben wird. Dies bedeutet, ob Datei, Device oder was auch immer, in C wird ein Stream geöffnet (mit fopen()), und zwar entweder zum
Lesen ("r", read),
zum Anhängen ("a", append) oder
zum Schreiben ("w", write).
Fügt man ein "b" an, dann bedeutet dies beim Modus, dass der Stream nicht als Text-Stream geöffnet werden soll, sondern als Bit-Stream.
Es gibt drei Standard-Streams, die immer geöffnet werden:
stdin für die Standardeingabe von der Tastatur,
stdout für die Standardausgabe auf den Bildschirm und
stderr, der Standardfehlerkanal, der auch auf den Bildschirm geleitet wird.
Man kann allerdings weitere Streams erzeugen und sie mit einem Namen belegen. Dabei muss man beachten, dass man die maximale Länge von Namen (FILENAME_MAX) nicht überschreitet.
Liefert fopen einen NULL-Pointer zurück, dann ist etwas falsch gelaufen und man sollte sofort klären (mit der Funktion ferror), was geschehen ist. Andernfalls kann man weiter arbeiten. Der Filepointer fp, der verschieden ist von NULL, ist ein Filedescriptor, der von anderen Funktionen als Name des Streams solange benutzt werden kann, bis die Funktion fclose(fp) ihn wieder 'ausser Kraft setzt'.
Ist es gelungen, einen Stream erfolgreich z.B. zum Lesen zu öffnen, dann kann man mit der Funktion fgetc(fp) oder dem Makro getc(fp) den Inhalt des Streams zeichenweise auslesen (die C-Bibliothek hällt weitere Funktionen zum Lesen bereit). Entdecken fgetc() oder getc() das Ende des Streams oder einen Fehler, dann liefern sie EOF= -1 als Ergebnis zurück, andernfalls den Integerwert des gelesenen Zeichens.
Dateien in C (Anmerkung: die Position des Zeichens '+' im Feld 'MODE' von fopen() ist 'zwischen' den beiden anderen Optionen, nicht davor, wie im Bild fälschlich angegeben)
Wer genauere Informationen zu den einzelnen Funktionen haben will, kann unter UNIX bzw. LINUX diese einfach per 'man FUNKTIONSNAME' abfragen. Auf die Frage 'man fopen' z.B. bekommt man folgende Informationen:
NAME fopen, fdopen, freopen - stream open functions SYNOPSIS #include <stdio.h> FILE *fopen(const char *path, const char *mode); FILE *fdopen(int fildes, const char *mode); FILE *freopen(const char *path, const char *mode, FILE *stream); DESCRIPTION The fopen function opens the file whose name is the string pointed to by path and associates a stream with it. The argument mode points to a string beginning with one of the following sequences (Additional characters may follow these sequences.): r Open text file for reading. The stream is positioned at the beginning of the file. r+ Open for reading and writing. The stream is positioned at the beginning of the file. w Truncate file to zero length or create text file for writing. The stream is positioned at the beginning of the file. w+ Open for reading and writing. The file is created if it does not exist, otherwise it is truncated. The stream is positioned at the beginning of the file. a Open for appending (writing at end of file). The file is created if it does not exist. The stream is positioned at the end of the file. a+ Open for reading and appending (writing at end of file). The file is cre ated if it does not exist. The stream is positioned at the end of the file. The mode string can also include the letter ``b'' either as a last character or as a character between the characters in any of the two-character strings described above. This is strictly for compatibility with ANSI X3.159-1989 (``ANSI C'') and has no effect; the ``b'' is ignored on all POSIX conforming systems, including Linux. (Other systems may treat text files and binary files differently, and adding the ``b'' may be a good idea if you do I/O to a binary file and expect that your program may be ported to non-Unix environments.) Any created files will have mode S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH (0666), as modified by the process' umask value (see umask(2). Reads and writes may be intermixed on read/write streams in any order. Note that ANSI C requires that a file positioning function intervene between output and input, unless an input operation encounters end-of-file. (If this condition is not met, then a read is allowed to return the result of writes other than the most recent.) Therefore it is good practice (and indeed sometimes necessary under Linux) to put an fseek or fgetpos operation between write and read operations on such a stream. This operation may be an apparent no-op (as in fseek(..., 0L, SEEK_CUR) called for its synchronizing side effect. Opening a file in append mode (a as the first character of mode) causes all subse quent write operations to this stream to occur at end-of-file, as if preceded by an fseek(stream,0,SEEK_END); call. The fdopen function associates a stream with the existing file descriptor, fildes. The mode of the stream (one of the values "r", "r+", "w", "w+", "a", "a+") must be compatible with the mode of the file descriptor. The file position indicator of the new stream is set to that belonging to fildes, and the error and end-of-file indicators are cleared. Modes "w" or "w+" do not cause truncation of the file. The file descriptor is not dup'ed, and will be closed when the stream created by fdopen is closed. The result of applying fdopen to a shared memory object is unde fined. The freopen function opens the file whose name is the string pointed to by path and associates the stream pointed to by stream with it. The original stream (if it exists) is closed. The mode argument is used just as in the fopen function. The file descriptor is not dup'ed, and will be closed when the stream created by fdopen is closed. The result of applying fdopen to a shared memory object is unde fined. The freopen function opens the file whose name is the string pointed to by path and associates the stream pointed to by stream with it. The original stream (if it exists) is closed. The mode argument is used just as in the fopen function. The primary use of the freopen function is to change the file associated with a stan dard text stream (stderr, stdin, or stdout). RETURN VALUE Upon successful completion fopen, fdopen and freopen return a FILE pointer. Other wise, NULL is returned and the global variable errno is set to indicate the error. ERRORS EINVAL The mode provided to fopen, fdopen, or freopen was invalid. The fopen, fdopen and freopen functions may also fail and set errno for any of the errors specified for the routine malloc(3). The fopen function may also fail and set errno for any of the errors specified for the routine open(2). The fdopen function may also fail and set errno for any of the errors specified for the routine fcntl(2). The freopen function may also fail and set errno for any of the errors specified for the routines open(2), fclose(3) and fflush(3). CONFORMING TO The fopen and freopen functions conform to ANSI X3.159-1989 (``ANSI C''). The fdopen function conforms to IEEE Std1003.1-1988 (``POSIX.1'').
Frage nach 'fclose' mit 'man fclose':
NAME fclose - close a stream SYNOPSIS #include <stdio.h> int fclose(FILE *stream); DESCRIPTION The fclose function dissociates the named stream from its underlying file or set of functions. If the stream was being used for output, any buffered data is written first, using fflush(3). RETURN VALUE Upon successful completion 0 is returned. Otherwise, EOF is returned and the global variable errno is set to indicate the error. In either case any further access (including another call to fclose()) to the stream results in undefined behaviour. ERRORS EBADF The filedescriptor underlying stream is not valid. The fclose function may also fail and set errno for any of the errors specified for the routines close(2), write(2) or fflush(3). NOTES Note that fclose only flushes the user space buffers provided by the C library. To ensure that the data is physically stored on disk the kernel buffers must be flushed too, e.g. with sync(2) or fsync(2). CONFORMING TO The fclose function conforms to ANSI X3.159-1989 (``ANSI C''). SEE ALSO close(2), fcloseall(3), fflush(3), fopen(3), setbuf(3)
Auf die Frage 'man fgetc' z.B. bekommt man folgende Informationen:
NAME fgetc, fgets, getc, getchar, gets, ungetc - input of characters and strings SYNOPSIS #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); DESCRIPTION fgetc() reads the next character from stream and returns it as an unsigned char cast to an int, or EOF on end of file or error. getc() is equivalent to fgetc() except that it may be implemented as a macro which evaluates stream more than once. getchar() is equivalent to getc(stdin). gets() reads a line from stdin into the buffer pointed to by s until either a ter minating newline or EOF, which it replaces with '\0'. No check for buffer overrun is performed (see BUGS below). fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s. Reading stops after an EOF or a newline. If a newline is read, it is stored into the buffer. A '\0' is stored after the last character in the buffer. ungetc() pushes c back to stream, cast to unsigned char, where it is available for subsequent read operations. Pushed - back characters will be returned in reverse order; only one pushback is guaranteed. ungetc() pushes c back to stream, cast to unsigned char, where it is available for subsequent read operations. Pushed - back characters will be returned in reverse order; only one pushback is guaranteed. Calls to the functions described here can be mixed with each other and with calls to other input functions from the stdio library for the same input stream. For non-locking counterparts, see unlocked_stdio(3). RETURN VALUE fgetc(), getc() and getchar() return the character read as an unsigned char cast to an int or EOF on end of file or error. gets() and fgets() return s on success, and NULL on error or when end of file occurs while no characters have been read. ungetc() returns c on success, or EOF on error. CONFORMING TO ANSI - C, POSIX.1 BUGS Never use gets(). Because it is impossible to tell without knowing the data in advance how many characters gets() will read, and because gets() will continue to store characters past the end of the buffer, it is extremely dangerous to use. It has been used to break computer security. Use fgets() instead. It is not advisable to mix calls to input functions from the stdio library with low - level calls to read() for the file descriptor associated with the input stream; the results will be undefined and very probably not what you want.
Das folgende einfache Beispiel demonstriert das Öffnen einer Textdatei zum Lesen mittels der Funktion fgetc().
/************************* * * i-progr1-th7-dateiread.c * * author: gdh * first: ws01 * last: nov-11,02 * * idea: Öffnen einer Datei zum Lesen im Textmodus * Ausgabe auf Bildschirm * * - Das Programm erfragt vom Benutzer einen Dateinamen mit fgets() * - Mit diesem Dateinamen wird dann die Datei zum Lesen geöfnet * - Die geöffnete Datei wird mit fgetc() asugelesen und die gelesenen Werte werden in * auf dem Bildschirm ausgegeben * * compilation: gcc -o dateiread dateiread.c * usage: dateiread * ***************************/ #include <stdio.h> #include <string.h> #include <errno.h> main(void){ int c; FILE *fp; /* Zeiger vom Typ FILE für Dateioperationen */ char dname[FILENAME_MAX]; /* Feld für Dateinamen mit maximal möglicher Länge */ /*****************************************/ /* ECKWERTE ZU FILENAME_MAX und FOPEN_MAX*/ /*****************************************/ printf("FOPEN_MAX = %d\n",FOPEN_MAX); printf("FILENAME_MAX = %d\n",FILENAME_MAX); /*********************************/ /* EINGABE DATEINAME */ /*********************************/ printf("BITTE DATEINAMN eingeben: "); fgets(dname, FILENAME_MAX, stdin); dname[strlen(dname)-1]='\0'; /* Steuerzeichen '\n' von fgets() durch '\0' ersetzen */ /*********************************/ /* DATEI WIRD ZUM LESEN GEOEFFNET */ /*********************************/ errno = 0; /* errno ist Fehlervariable; wird vom System gesetzt, wenn Fehler */ fp = fopen(dname, "r"); if (errno != 0 ){ /******************************/ /* FEHLERBEHANDLUNG */ /******************************/ fprintf(stderr, "open_file(\"%s\") failed: %s\n", dname, strerror(errno)); } /* strerror() ist eine Fehlerfunktion, die die Fehlernummer kommentiert ausgibt */ else{ /*********************************/ /* AUSLESEN DER DATEI */ /*********************************/ c = fgetc(fp); while (c != EOF){ printf("%c",c); c = fgetc(fp); } }/* End of else */ /*********************************/ /* DATEI WIRD GESCHLOSSEN */ /*********************************/ printf("VOR SCHLIESSUNG DATEI\n"); errno =0; if (fclose(fp) != 0) { fprintf(stderr, "close_file failed: %s\n", strerror(errno)); return (1); } else { return (0); } }
Im Programm wird die Fehlervariable 'errno' benutzt. Im Nicht-Fehlerfall hat sie den Wert '0' bzw. sie muss vor Benutzung von Funktionen, die Fehlermeldungen erzeugen können, explizit auf 0 gesetzt werden. Nach Aufruf einer Funktion, die Fehlermeldungen in errno setzen kann, ist errno abzufragen. Dazu kann man die Funktion strerror() benutzen; diese übersetzt die Fehlernummer in einen kurzen erklärenden Text und gibt diesen auf dem Bildschirm aus. Weitere erklärungen zu 'errno' und 'strerror()' kann man wieder über 'man ...' abfragen.
NAME errno - number of last error SYNOPSIS #include <errno.h> extern int errno; DESCRIPTION The integer errno is set by system calls (and some library functions) to indicate what went wrong. Its value is significant only when the call returned an error (usually -1), and a library function that does succeed is allowed to change errno. Sometimes, when -1 is also a legal return value one has to zero errno before the call in order to detect possible errors. errno is defined by the ISO C standard to be a modifiable lvalue of type int, and must not be explicitly declared; errno may be a macro. errno is thread-local; set ting it in one thread does not affect its value in any other thread. Valid error numbers are all non-zero; errno is never set to zero by any library function. All the error names specified by POSIX.1 must have distinct values. POSIX.1 (1996 edition) lists the following symbolic error names. Of these, EDOM and ERANGE are in the ISO C standard. ISO C Amendment 1 defines the additional error number EILSEQ for coding errors in multibyte or wide characters. E2BIG Arg list too long EACCES Permission denied EAGAIN Resource temporarily unavailable EBADF Bad file descriptor EBADMSG Bad message EBUSY Resource busy ECANCELED Operation canceled ECHILD No child processes EDEADLK Resource deadlock avoided EDOM Domain error EEXIST File exists EFAULT Bad address EFBIG File too large EINPROGRESS Operation in progress EINTR Interrupted function call EINVAL Invalid argument EIO Input/output error EISDIR Is a directory EMFILE Too many open files EMLINK Too many links EMSGSIZE Inappropriate message buffer length ENAMETOOLONG Filename too long ENFILE Too many open files in system ENODEV No such device ENOENT No such file or directory ENOEXEC Exec format error ENOLCK No locks available ENOMEM Not enough space ENOSPC No space left on device ENOSYS Function not implemented ENOTDIR Not a directory ENOTEMPTY Directory not empty ENOTSUP Not supported ENOTTY Inappropriate I/O control operation ENXIO No such device or address EPERM Operation not permitted EPIPE Broken pipe ERANGE Result too large ENOTEMPTY Directory not empty ENOTSUP Not supported ENOTTY Inappropriate I/O control operation ENXIO No such device or address EPERM Operation not permitted EPIPE Broken pipe ERANGE Result too large EROFS Read-only file system ESPIPE Invalid seek ESRCH No such process ETIMEDOUT Operation timed out EXDEV Improper link Many other error numbers are returned by various Unix implementations. System V returns ETXTBSY (Text file busy) if one tries to exec() a file that is currently open for writing. Linux also returns this error if one tries to have a file both memory mapped with VM_DENYWRITE and open for writing. SEE ALSO perror(3), strerror(3)
Die Anfrage 'man strerror' liefert:
NAME strerror, strerror_r - return string describing error code SYNOPSIS #include <string.h> char *strerror(int errnum); int strerror_r(int errnum, char *buf, size_t n); DESCRIPTION The strerror() function returns a string describing the error code passed in the argument errnum, possibly using the LC_MESSAGES part of the current locale to select the appropriate language. This string must not be modified by the applica tion, but may be modified by a subsequent call to perror() or strerror(). No library function will modify this string. The strerror_r() function is similar to strerror(), but is thread safe. It returns the string in the user-supplied buffer buf of length n. RETURN VALUE The strerror() function returns the appropriate error description string, or an unknown error message if the error code is unknown. The value of errno is not changed for a successful call, and is set to a nonzero value upon error. The str error_r() function returns 0 on success and -1 on failure, setting errno. ERRORS EINVAL The value of errnum is not a valid error number. ERANGE Insufficient storage was supplied to contain the error description string. CONFORMING TO SVID 3, POSIX, BSD 4.3, ISO/IEC 9899:1990 (C89). SEE ALSO errno(3), perror(3), strsignal(3)
In diesem Beispiel betrachten wir den Fall, dass man Text an eine Datei anhängen will. Falls die angegebene Datei noch nicht existiert, wird sie neu angelegt. Existiert sie, wird der Text automatisch an das aktuelle Ende der Datei angehängt. Nach der Eingabe wird ein Kontrollausdruck der neuen kompletten Datei gegeben. Zu diesem Zweck muss aber der Filepointer zunächst auf den Anfang der Datei zurückgesetzt werdem, damit der Kontrollausdruck vom Anfang der Datei liest. Die hierbei benutzten Befehle sinddie folgenden:
fgets(dname, FILENAME_MAX, stdin) zum Einlesen des Dateinamens von der Tastatur
fgets(texteingabe, TEXT_MAX, stdin) zum Einlesen der texteingabe von der Tastatur
fp = fopen(dname, "a+") zum Öffnen einer Datei im Modus 'Anhängen ('append') mit dem Zusatz ('+'), dass sie auch lesbar sein soll
fputs(texteingabe, fp) Schreiben des Textes aus der Variablen 'texteingabe' in die Datei
rewind(fp) Zurücksetzen des Filepointers auf den Anfang der Datei
Für mehr Informationen zu den Funktionen fputs() und rewind() siehe wieder die man-Einträge:
NAME fputc, fputs, putc, putchar, puts - output of characters and strings SYNOPSIS #include <stdio.h> 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(const char *s); DESCRIPTION fputc() writes the character c, cast to an unsigned char, to stream. fputs() writes the string s to stream, without its trailing '\0'. putc() is equivalent to fputc() except that it may be implemented as a macro which evaluates stream more than once. putchar(c); is equivalent to putc(c,stdout). puts() writes the string s and a trailing newline to stdout. Calls to the functions described here can be mixed with each other and with calls to other output functions from the stdio library for the same output stream. For non-locking counterparts, see unlocked_stdio(3). RETURN VALUE fputc(), putc() and putchar() return the character written as an unsigned char cast to an int or EOF on error. puts() and fputs() return a non-negative number on success, or EOF on error. CONFORMING TO ANSI - C, POSIX.1 BUGS It is not advisable to mix calls to output functions from the stdio library with low - level calls to write() for the file descriptor associated with the same out put stream; the results will be undefined and very probably not what you want. SEE ALSO write(2), ferror(3), fopen(3), fseek(3), fwrite(3), gets(3), scanf(3), unlocked_stdio(3)
NAME fgetpos, fseek, fsetpos, ftell, rewind - reposition a stream SYNOPSIS #include <stdio.h> int fseek(FILE *stream, long offset, int whence); long ftell(FILE *stream); void rewind(FILE *stream); int fgetpos(FILE *stream, fpos_t *pos); int fsetpos(FILE *stream, fpos_t *pos); DESCRIPTION The fseek function sets the file position indicator for the stream pointed to by stream. The new position, measured in bytes, is obtained by adding offset bytes to the position specified by whence. If whence is set to SEEK_SET, SEEK_CUR, or SEEK_END, the offset is relative to the start of the file, the current position indicator, or end-of-file, respectively. A successful call to the fseek function clears the end-of-file indicator for the stream and undoes any effects of the ungetc(3) function on the same stream. The ftell function obtains the current value of the file position indicator for the stream pointed to by stream. The rewind function sets the file position indicator for the stream pointed to by stream to the beginning of the file. It is equivalent to: (void)fseek(stream, 0L, SEEK_SET) except that the error indicator for the stream is also cleared (see clearerr(3)). The fgetpos and fsetpos functions are alternate interfaces equivalent to ftell and fseek (with whence set to SEEK_SET), setting and storing the current value of the file offset into or from the object referenced by pos. On some non-UNIX systems an fpos_t object may be a complex object and these routines may be the only way to portably reposition a text stream. RETURN VALUE The rewind function returns no value. Upon successful completion, fgetpos, fseek, fsetpos return 0, and ftell returns the current offset. Otherwise, -1 is returned and the global variable errno is set to indicate the error. ERRORS EBADF The stream specified is not a seekable stream. EINVAL The whence argument to fseek was not SEEK_SET, SEEK_END, or SEEK_CUR. The function fgetpos, fseek, fsetpos, and ftell may also fail and set errno for any of the errors specified for the routines fflush(3), fstat(2), lseek(2), and mal loc(3). CONFORMING TO The fgetpos, fsetpos, fseek, ftell, and rewind functions conform to ANSI X3.159-1989 (``ANSI C''). SEE ALSO lseek(2), fseeko(3)
/************************* * * i-progr1-th7-dateiappend.c * * author: gdh * first: - * last: nov-12,02 * * idea: Öffnen einer Datei zum Anhängen von Daten im Textmodus * * - Das Programm erfragt vom Benutzer einen Dateinamen mit fgets() * - Dann wird eine Texteingabe angefordert * - Mit dem Dateinamen wird dann die Datei zum Anhängen geöffnet * - und der eingelesene Text wird an die Datei angehängt * * compilation: gcc -o dateiappend dateiappend.c * usage: dateiappend * ***************************/ #include <stdio.h> #include <string.h> #include <errno.h> #define TEXT_MAX 1000 main(void){ int c,i; FILE *fp; /* Zeiger vom Typ FILE für Dateioperationen */ char dname[FILENAME_MAX]; /* Feld für Dateinamen mit maximal möglicher Länge */ char texteingabe[TEXT_MAX]; /* Feld für TEXTEINGABE mit maximal möglicher Länge */ /*****************************************/ /* ECKWERTE ZU FILENAME_MAX und FOPEN_MAX*/ /*****************************************/ printf("FOPEN_MAX = %d\n",FOPEN_MAX); printf("FILENAME_MAX = %d\n",FILENAME_MAX); /*********************************/ /* EINGABE DATEINAME */ /*********************************/ printf("BITTE DATEINAMN eingeben: "); fgets(dname, FILENAME_MAX, stdin); dname[strlen(dname)-1]='\0'; /* Steuerzeichen '\n' von fgets() durch '\0' ersetzen */ /*********************************/ /* EINGABE TEXT */ /*********************************/ printf("BITTE TEXT eingeben: "); fgets(texteingabe, TEXT_MAX, stdin); texteingabe[strlen(texteingabe)-1]='\0'; /* Steuerzeichen '\n' von fgets() durch '\0' ersetzen */ /***************************************/ /* DATEI WIRD ZUM ANHAENGEN GEOEFFNET */ /***************************************/ errno = 0; /* errno ist Fehlervariable; wird vom System gesetzt, wenn Fehler */ fp = fopen(dname, "a+"); /* Datei wird zum Anhängen und Lesen geöffnet */ if (errno != 0 ){ /******************************/ /* FEHLERBEHANDLUNG */ /******************************/ fprintf(stderr, "open_file(\"%s\") failed: %s\n", dname, strerror(errno)); } /* strerror() ist eine Fehlerfunktion, die die Fehlernummer kommentiert ausgibt */ else{ /************************************/ /* ANHAENGEN DER DATEN AN DIE DATEI */ /************************************/ printf("TEXT WIRD JETZT ABGESPEICHERT\n\n"); if( fputs(texteingabe, fp) == EOF ) printf("\n.\nERROR on writing the file\n\n"); /************************************/ /* AUSLESEN DER DATEI ZUR KONTROLLE */ /*************************************/ printf("AUSLESEN DER DATEI ZUR KONTROLLE\n\n"); rewind(fp); /* Setzt den Filepointer wieder auf den Anfang */ c = fgetc(fp); while (c != EOF) { printf("%c",c); c = fgetc(fp); } }/* End of else */ /*********************************/ /* DATEI WIRD GESCHLOSSEN */ /*********************************/ printf("\n\nVOR SCHLIESSUNG DATEI\n"); errno =0; if (fclose(fp) != 0) { fprintf(stderr, "close_file failed: %s\n", strerror(errno)); return (1); } else { printf("\n\nNACH SCHLIESSUNG DER DATEI\n"); return (0); } }
Es soll an dieser stelle nur darauf hingewiessen werden, dass man von C aus auch Dateien mit remove() entfernen bzw. mit rename() auch umbenennen kann.
NAME rename - change the name or location of a file SYNOPSIS #include <stdio.h> int rename(const char *oldpath, const char *newpath); DESCRIPTION rename renames a file, moving it between directories if required. Any other hard links to the file (as created using link(2)) are unaffected. If newpath already exists it will be atomically replaced (subject to a few condi tions - see ERRORS below), so that there is no point at which another process attempting to access newpath will find it missing. If newpath exists but the operation fails for some reason rename guarantees to leave an instance of newpath in place. However, when overwriting there will probably be a window in which both oldpath and newpath refer to the file being renamed. If oldpath refers to a symbolic link the link is renamed; if newpath refers to a symbolic link the link will be overwritten. RETURN VALUE On success, zero is returned. On error, -1 is returned, and errno is set appropri ately. ERRORS EISDIR newpath is an existing directory, but oldpath is not a directory. EXDEV oldpath and newpath are not on the same filesystem. ENOTEMPTY or EEXIST newpath is a non-empty directory, i.e., contains entries other than "." and "..". EBUSY The rename fails because oldpath or newpath is a directory that is in use by some process (perhaps as current working directory, or as root directory, or because it was open for reading) or is in use by the system (for example as mount point), while the system considers this an error. (Note that there is no requirement to return EBUSY in such cases - there is nothing wrong with doing the rename anyway - but it is allowed to return EBUSY if the system cannot otherwise handle such situations.) EINVAL The new pathname contained a path prefix of the old, or, more generally, an attempt was made to make a directory a subdirectory of itself. EMLINK oldpath already has the maximum number of links to it, or it was a directory and the directory containing newpath has the maximum number of links. ENOTDIR A component used as a directory in oldpath or newpath is not, in fact, a directory. Or, oldpath is a directory, and newpath exists but is not a directory. EFAULT oldpath or newpath points outside your accessible address space. EACCES Write access to the directory containing oldpath or newpath is not allowed for the process's effective uid, or one of the directories in oldpath or newpath did not allow search (execute) permission, or oldpath was a direc tory and did not allow write permission (needed to update the .. entry). EPERM or EACCES The directory containing oldpath has the sticky bit set and the process's effective uid is neither that of root nor the uid of the file to be deleted nor that of the directory containing it, or newpath is an existing file and the directory containing it has the sticky bit set and the process's effec tive uid is neither that of root nor the uid of the file to be replaced nor that of the directory containing it, or the filesystem containing pathname does not support renaming of the type requested. ENAMETOOLONG oldpath or newpath was too long. ENOENT A directory component in oldpath or newpath does not exist or is a dan gling symbolic link. ENOMEM Insufficient kernel memory was available. EROFS The file is on a read-only filesystem. ELOOP Too many symbolic links were encountered in resolving oldpath or newpath. ENOSPC The device containing the file has no room for the new directory entry. CONFORMING TO POSIX, 4.3BSD, ANSI C BUGS On NFS filesystems, you can not assume that if the operation failed the file was not renamed. If the server does the rename operation and then crashes, the retransmitted RPC which will be processed when the server is up again causes a failure. The application is expected to deal with this. See link(2) for a similar problem. SEE ALSO link(2), unlink(2), symlink(2), mv(1)
NAME remove - delete a name and possibly the file it refers to SYNOPSIS #include <stdio.h> int remove(const char *pathname); DESCRIPTION remove deletes a name from the filesystem. It calls unlink for files, and rmdir for directories. If the removed name was the last link to a file and no processes have the file open the file is deleted and the space it was using is made available for reuse. If the name was the last link to a file but any processes still have the file open the file will remain in existence until the last file descriptor referring to it is closed. If the name referred to a symbolic link the link is removed. If the name referred to a socket, fifo or device the name for it is removed but processes which have the object open may continue to use it. RETURN VALUE On success, zero is returned. On error, -1 is returned, and errno is set appropri ately. ERRORS EFAULT pathname points outside your accessible address space. EACCES Write access to the directory containing pathname is not allowed for the process's effective uid, or one of the directories in pathname did not allow search (execute) permission. EACCES Write access to the directory containing pathname is not allowed for the process's effective uid, or one of the directories in pathname did not allow search (execute) permission. EPERM The directory containing pathname has the sticky-bit (S_ISVTX) set and the process's effective uid is neither the uid of the file to be deleted nor that of the directory containing it. ENAMETOOLONG pathname was too long. ENOENT A directory component in pathname does not exist or is a dangling symbolic link. ENOTDIR A component used as a directory in pathname is not, in fact, a directory. ENOMEM Insufficient kernel memory was available. EROFS pathname refers to a file on a read-only filesystem. CONFORMING TO ANSI C, SVID, AT&T, POSIX, X/OPEN, BSD 4.3 BUGS Infelicities in the protocol underlying NFS can cause the unexpected disappearance of files which are still being used. NOTE Under libc4 and libc5, remove was an alias for unlink (and hence would not remove directories). SEE ALSO unlink(2), rename(2), open(2), rmdir(2), mknod(2), mkfifo(3), link(2), rm(1), unlink(8)
Bilden sie ein Team von 3 Mitgliedern
Erstellung Sie gemeinsam einen Texte mit Namen und Matr.Nr. der AutorenInnen. Abgabe einer Kopie des Textes an den Dozenten vor Beginn der Vorlesung am Di (1 Woche nach Aufgabenstellung). Falls die Aufgabe ausführbaren Programmcode enthält wäre die zusätzliche Übergabe des Quelltextes auf Diskette oder per email wünschenswert, aber nicht verbindlich. Im Falle von Programmcode muss im Programmtext auch nochmals Name und Matr.Nr. erscheinen.
Präsentation der Lösung als Team vor der gesamten Gruppe. Präsentationszeit (abhängig von der Gesamtzahl der Teams) 3-5 Min. Mögliche Punkte: 1-2 im Normalfall. Bei besonders guten Leistungen bis zu 3 Punkten.
Versuchen Sie in dem Text Antworten auf folgende Aufgaben zu formulieren:
Das Thema Sicherheit ist heutzutage sehr wichtig. Ein Teilbereich in diesem Thema sind z.B. 'sichere' Passwörter. Es soll ein einfaches Programm geschrieben werden, das demonstrieren soll, wie leicht bzw. wie schwer es ist, ein Passwort zu knacken. Realisieren Sie folgenden experimentellen Aufbau:
Legen sie eine Textdatei an, in der sie eine Reihe von Passwörter hineinschreiben, getrennt durch SPACE (=Leerzeichen, ASCII-Kode dezimal 32). Benutzen sie nur Kleinbuchstaben 'a,b, ..., z'. Beginnen sie mit der Länge 2, und steigern Sie die Länge bis zu einer Zahl, die Ihren Computer eine von Ihnen festgelegte maximale Zeit rechnen lässt.
Das Programm selbst soll folgende Aufgaben erfüllen:
Sie lesen das nächste Wort w aus Ihrer Testdatei mit den Passwörtern
Mit dem Zufallsgenerator rand() erzeugen Sie ein hypothetisches Wort w' von der gleichen Länge wie das Testwort w
Falls (w' == w) WAHR, dann schreiben Sie die Anzahl der Versuche, die der Zufallsgenerator benötigt hat, um w zu 'erkennen', in eine Ergabnisdatei mit folgendem Format: TESTWORT : BENÖTIGTE ANZAHL VON VERSUCHEN;
Falls (w' == w) FALSCH, dann erzeugen Sie ein neues hypothetisches Wort w' von der gleichen Länge wie das Testwort w und prüfen auf Erfolg.
Wenn sie alle Testworte aus Ihrer Datei abgearbeitet haben bzw. bis Ihr Computer die maximale Anzahl von Durchgängen erreicht hat, die Sie zulassen wollen, dann geben Sie die Ergebnisdatei mit allen Ergebissen auf dem Bildschirm aus.