Subversion Repositories sysadmin_scripts

Rev

Rev 58 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

#define _LARGEFILE64_SOURCE /* See feature_test_macros(7) */



       //void *mmap(void *addr, size_t length, int prot, int flags,/int fd, off_t offset);
       //int munmap(void *addr, size_t length);
       //void *memmove(void *dest, const void *src, size_t n);

//size_t pagesize = getpagesize();
//printf("System page size: %lu bytes\n", pagesize);
//char * region = mmap(

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <string.h>
#include <errno.h>

#define EXTENDSIZE 8
#define FILESIZE (NUMINTS * sizeof(int))

int
main(
  int argc,
  char **argv)
{
  int i;
  int fd;
  char *map;  /* mmapped array of char * */
  long extendSize;

  if (argc!=3) {
    fprintf(stderr,"?Require 2 param: filename spaceToInsert\n");
    exit(EXIT_FAILURE);
  }

  /* Open a file for writing.
   *  - Creating the file if it doesn't exist.
   *  - Truncating it to 0 size if it already exists. (not really needed)
   *
   * Note: "O_WRONLY" mode is not sufficient when mmaping.
   */
  fd = open(argv[1], O_RDWR, 0);    // | O_CREAT | O_TRUNC, (mode_t)0600);
  if (fd == -1) {
    perror("Error opening file for writing");
    exit(EXIT_FAILURE);
  }
  
  extendSize = atoi( argv[2] );
  
  if ( extendSize <= 0 ) {
     perror( "Extend size must be positive integer" );
     exit( EXIT_FAILURE );
  }


  struct stat fsize { 0 };

  if (fstat(fd, &fsize) < 0) {
    int saveErrno = errno;
    fprintf(stderr, "fstat(%d) returned errno=%d.", fd, saveErrno);
    exit(EXIT_FAILURE);
  }

  fprintf(stderr, "%%sizeof fstat.off_t is %d\n", sizeof(fsize.st_size));


  off_t eopos = lseek(fd, 0, SEEK_END); 

  if (eopos == -1) {
    close(fd);
    perror("Error calling lseek() to get file length");
    exit(EXIT_FAILURE);
  }

  fprintf(stderr, "%%Sought size is %ld\n", eopos);
  fprintf(stderr, "%%Adding head-end %ld bytes\n", extendSize );


  //result = lseek(fd, 0, SEEK_END);

  off_t neweopos = eopos + extendSize - 1;
  off_t seekres = lseek(fd, neweopos, SEEK_SET);
  if (seekres == -1) {
    close(fd); 
    perror("Error calling lseek() to 'expand' the file");
    exit(EXIT_FAILURE);
  } 
  int result = write(fd, "", 1); //Write a null bytes to expand file
  if (result != 1) {
    close(fd);
    perror("Error writing last byte of the file");
    exit(EXIT_FAILURE);
  }

  neweopos++;

  /* Now the file is ready to be mmapped.
   */
  map = (char*)mmap(0, neweopos, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
  if (map == MAP_FAILED) {
    close(fd);
    perror("Error mmapping the file");
    exit(EXIT_FAILURE);
  }
  
  /* Now move the file contents forward (just leave the original junk hanging around at beginning of file)
   */
  memmove(map + extendSize, map, eopos);

  /* free the mmapped memory
   */
  if (munmap(map, neweopos) == -1) {
    perror("Error un-mmapping the file");
    exit(EXIT_FAILURE);
    /* Decide here whether to close(fd) and exit() or not. Depends... */
  }
  
  
  // zero out the first extendSize bytes of file
  if ( fseek( fd, 0, SEEK_SET ) !== 0 ) {
     perror( "Error getting to beginning of file" );
     exit();
  }
  
  // write zeros
  while ( extendSize-- ) {
     fputc( 0, fd );
   }
  

  /* Un-mmaping doesn't close the file, so we still need to do that.
   */
  close(fd);
  return 0;
}