Your Browser is not longer supported

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

{{viewport.spaceProperty.prod}}

Adapting existing programs to large files

&pagelevel(4)&pagelevel

If you wish to adapt existing programs to access large files, you must follow the procedures that are described in the section "Creating new programs", i.e. add the appropriate Define statements and the Include file unistd.h, replace the 32-bit functions (open(), lseek(), ...) with the corresponding 64-Bit functions open64(), lseek64(), ... and if necessary use the 64-bit data types. This may mean internal data structures may have to be modified in an incompatible way.

To clarify the problems associated with accessing large files, a small program prog32 is given below as an example. This program is subsequently converted so that it can access large files (Program example prog64 in "Adapting existing programs to large files").

Program example prog32

prog32 opens a specified file and outputs a maximum of 32 Bytes of this file starting from a specified point. For reasons of legibility, the input parameters check has been omitted.

/*
** prog.c
** 
** Parameter 1: Name of file to be read
** Parameter 2: Offset of data to be read in file
** 
*/
#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);
   }
}

Program example prog64

prog64 is derived from prog32 and converted so that it can access large files.

/*
** prog.c
**
** 1. Parameter: Name of file to be read
** 2. Parameter: Offset of data to be read in file
**
*/
#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);
   }
}

Applying prog32 and prog64

Both programs were applied to the following files in the /mnt33/dir1 directory:

$ 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

Results of some program runs:

$ 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