Your Browser is not longer supported

Please use Google Chrome, Mozilla Firefox or Microsoft Edge to view the page correctly
Loading...

{{viewport.spaceProperty.prod}}

Existierende Programme an große Dateien anpassen

&pagelevel(4)&pagelevel

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