Wenn Sie existierende Programme für den Zugriff auf große Dateien anpassen möchten, dann müssen Sie dasselbe tun wie in Abschnitt "Neue Programme erstellen" beschrieben, d.h. die zugehörigen Define-Anweisungen sowie die Include-Datei unistd.h hinzufügen, 32-bit-Funktionen (open(), lseek(), ...) durch die entsprechenden 64-Bit-Funktionen open64(), lseek64(), ... ersetzen und ggf. die 64-bit-Datentypen verwenden. Dies hat unter Umständen zur Folge, dass interne Datenstrukturen inkompatibel geändert werden müssen.
Um die Problematik des Zugriffs auf große Dateien zu verdeutlichen, wird im Folgenden das kleines Beispielprogramm prog32 vorgestellt. Dieses Programm wird anschließend so umgestellt, dass es auf große Dateien zugreifen kann (Beispielprogramm prog64 in "Existierende Programme an große Dateien anpassen").
Beispielprogramm prog32
prog32 öffnet eine vorgegebene Datei und gibt von dieser Datei maximal 32 Bytes ab einer vorgegebenen Stelle aus. Zur leichteren Lesbarkeit wurde die Prüfung der Eingabeparameter weggelassen.
/* ** prog.c ** ** 1. Parameter: Name der zu lesenden Datei ** 2. Parameter: Offset der zu lesenden Daten innerhalb der Datei ** */ #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <sys/types.h> #include <sys/fcntl.h> #define BUFFER_LENGTH 8192 #define READ_LENGTH 32 char buffer[BUFFER_LENGTH]; int main(int argc, char *argv[]) { int fd; int len; int i; off_t filelen; off_t offset_in_file; offset_in_file = atol(argv[2]); printf ("reading from file <%s> with offset %d and length %d\n", argv[1], offset_in_file, READ_LENGTH); /* open file */ if ((fd = open (argv[1], O_RDONLY)) < 0) { printf ("open not successful, termination\n"); perror("ERRNO SET"); exit(EXIT_FAILURE); } /* now get the length of the file */ if ((filelen = lseek(fd, (off_t)0, SEEK_END)) == (off_t)(-1)) { printf ("lseek to end of file not successful, termination\n"); perror("ERRNO SET"); exit(EXIT_FAILURE); } if (offset_in_file > filelen) { printf ("offset %d is greater than filelength %d, termination\n", offset_in_file, filelen); exit(EXIT_FAILURE); } /* now seek to the offset to be read */ if (lseek(fd, offset_in_file - filelen, SEEK_CUR) == (off_t)(-1)) { printf ("lseek not successful, termination\n"); perror("ERRNO SET"); exit(EXIT_FAILURE); } /* read the data */ if ((len = read (fd, &buffer[0], READ_LENGTH)) <= 0 ) { printf ("read not successful, termination\n"); perror("ERRNO SET"); exit(EXIT_FAILURE); } else { /* now print the data that were read in hexadecimal form */ printf ("data of size %d (expected %d) were read\n", len, READ_LENGTH); for (i = 0; i < len; i++) { printf ("%02X ", buffer[i]); } printf ("\n"); } if (close(fd) != 0) { printf ("close not successful, termination\n"); perror("ERRNO SET"); exit(EXIT_FAILURE); } }
Beispielprogramm prog64
prog64 wird aus prog32 abgeleitet und so umgestellt, dass es auf große Dateien zugreifen kann.
/* ** prog.c ** ** 1. Parameter: Name der zu lesenden Datei ** 2. Parameter: Offset der zu lesenden Daten innerhalb der Datei ** */ #define _LARGEFILE64_SOURCE 1 #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <sys/types.h> #include <sys/fcntl.h> #define BUFFER_LENGTH 8192 #define READ_LENGTH 32 char buffer[BUFFER_LENGTH]; int main(int argc, char *argv[]) { int fd; int len; int i; off64_t filelen; off64_t offset_in_file; offset_in_file = atoll(argv[2]); printf ("reading from file <%s> with offset %lld and length %ld\n", argv[1], offset_in_file, READ_LENGTH); /* open file */ if ((fd = open64 (argv[1], O_RDONLY)) < 0) { printf ("open not successful, termination\n"); perror("ERRNO SET"); exit(EXIT_FAILURE); } /* now get the length of the file */ if ((filelen = lseek64(fd, (off64_t)0, SEEK_END)) == (off64_t)(-1)) { printf ("lseek to end of file not successful, termination\n"); perror("ERRNO SET"); exit(EXIT_FAILURE); } if (offset_in_file > filelen) { printf ("offset %lld is greater than filelength %lld, termination\n", offset_in_file, filelen); exit(EXIT_FAILURE); } /* now seek to the offset to be read */ if (lseek64(fd, offset_in_file - filelen, SEEK_CUR) == (off64_t)(-1)) { printf ("lseek not successful, termination\n"); perror("ERRNO SET"); exit(EXIT_FAILURE); } /* read the data */ if ((len = read (fd, &buffer[0], READ_LENGTH)) <= 0 ) { printf ("read not successful, termination\n"); perror("ERRNO SET"); exit(EXIT_FAILURE); } else { /* now print the data that were read in hexadecimal form */ printf ("data of size %d (expected %d) were read\n", len, READ_LENGTH); for (i = 0; i < len; i++) { printf ("%02X ", buffer[i]); } printf ("\n"); } if (close(fd) != 0) { printf ("close not successful, termination\n"); perror("ERRNO SET"); exit(EXIT_FAILURE); } }
Anwendung von prog32 und prog64
Die beiden Programme wurden auf folgende Dateien im Verzeichnis /mnt33/dir1 angewandt:
$ ls -l /mnt33/dir1 total 10245088 -rw-r--r-- 1 BACH OS315 2621440000 Feb 27 18:26 bigfile1 -rw-r--r-- 1 BACH OS315 2621440000 Mar 6 15:06 bigfile2 -rw-r--r-- 1 BACH OS315 18 Mar 15 13:56 smallfile1 -rw-r--r-- 1 BACH OS315 26 Mar 15 13:57 smallfile2 drwxr-xr-x 2 BACH OS315 2048 Mar 15 13:58 subdir1 drwxr-xr-x 2 BACH OS315 2048 Mar 15 13:58 subdir2
Ergebnisse einiger Programmläufe:
$ prog32 /mnt33/dir1/smallfile1 128 reading from file </mnt33/dir1/smallfile1> with offset 128 and length 32 offset 128 is greater than filelength 18, termination $ prog32 /mnt33/dir1/bigfile1 128 28 reading from file </mnt33/dir1/bigfile1> with offset 128 and length 32 lseek to end of file not successful, termination ERRNO SET: Value too large for defined data type $ prog64 /mnt33/dir1/smallfile1 128 reading from file </mnt33/dir1/smallfile1> with offset 128 and length 32 offset 128 is greater than filelength 18, termination
$ prog64 /mnt33/dir1/smallfile1 10 28 reading from file </mnt33/dir1/smallfile1> with offset 10 and length 32 data of size 8 (expected 32) were read 91 A5 A2 A5 A2 A5 95 15 $ prog64 /mnt33/dir1/bigfile1 128 0 reading from file </mnt33/dir1/bigfile1> with offset 128 and length 32 data of size 32 (expected 32) were read F3 F3 F3 F3 F3 F3 F3 F3 F3 F3 F3 F3 F3 F3 F3 F3 F3 F3 F3 F3 F3 F3 F3 F3 F3 F3 F3 F3 F3 F3 F3 F3 $ prog64 /mnt33/dir1/bigfile1 2500000000 reading from file </mnt33/dir1/bigfile1> with offset 2500000000 and length 32 data of size 32 (expected 32) were read F1 F1 F1 F1 F1 F1 F1 F1 F1 F1 F1 F1 F1 F1 F1 F1 F1 F1 F1 F1 F1 F1 F1 F1 F1 F1 F1 F1 F1 F1 F1 F1 $ prog64 /mnt33/dir1/bigfile1 500000000000 reading from file </mnt33/dir1/bigfile1> with offset 5000000000 and length 32 offset 5000000000 is greater than filelength 2621440000, termination