Guest User

tavianator

a guest
Dec 22nd, 2010
155
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 2.62 KB | None | 0 0
  1. #include <unistd.h>
  2. #include <sys/types.h>
  3. #include <sys/stat.h>
  4. #include <sys/mman.h>
  5. #include <fcntl.h>
  6. #include <stdlib.h>
  7. #include <stdio.h>
  8. #include <string.h>
  9.  
  10. int
  11. main(int argc, char *argv[])
  12. {
  13.   /* Check the command-line arguments */
  14.   if (argc != 3) {
  15.     fprintf(stderr, "usage: %s <filename> <line number>\n", argv[0]);
  16.     return EXIT_FAILURE;
  17.   }
  18.  
  19.   /* Open the file in read-write mode */
  20.   int fd = open(argv[1], O_RDWR);
  21.   if (fd < 0) {
  22.     perror("open");
  23.     return EXIT_FAILURE;
  24.   }
  25.  
  26.   /* stat() the file to find the size */
  27.   struct stat stat_buf;
  28.   if (fstat(fd, &stat_buf) < 0) {
  29.     perror("fstat");
  30.     return EXIT_FAILURE;
  31.   }
  32.  
  33.   /* Map the file into the current process's address space -- only works on
  34.      regular files */
  35.   void *map = mmap(NULL, stat_buf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED,
  36.                    fd, 0);
  37.   if (map == MAP_FAILED) {
  38.     perror("mmap");
  39.     return EXIT_FAILURE;
  40.   }
  41.  
  42.   /* Get the line number to remove from the second argument */
  43.   int line = atoi(argv[2]);
  44.   if (line < 1) {
  45.     fprintf(stderr, "Line %d makes no sense.\n", line);
  46.     return EXIT_FAILURE;
  47.   }
  48.  
  49.   /* Find the nth line */
  50.   char *linen = map;
  51.   int i;
  52.   for (i = 1; i < line; ++i) {
  53.     /* Search for the next '\n' character.  Assumes Linux newline encoding */
  54.     linen = memchr(linen, '\n', stat_buf.st_size - (linen - (char *)map));
  55.     if (!linen) {
  56.       fprintf(stderr, "Line %d is past EOF.\n", line);
  57.       return EXIT_FAILURE;
  58.     }
  59.     /* Point to the character one past the newline */
  60.     ++linen;
  61.   }
  62.  
  63.   /* Find the (n + 1)th line */
  64.   char *linen1 = memchr(linen, '\n', stat_buf.st_size - (linen - (char *)map));
  65.   if (linen1) {
  66.     /* We found the end of the line, so swallow the newline */
  67.     ++linen1;
  68.  
  69.     /* Erase the line by copying the memory at linen1 to linen */
  70.     memmove(linen, linen1, stat_buf.st_size - (linen1 - (char *)map));
  71.  
  72.     /* Unmap the file */
  73.     if (munmap(map, stat_buf.st_size) < 0) {
  74.       perror("munmap");
  75.       return EXIT_FAILURE;
  76.     }
  77.  
  78.     /* Shrink the file by the size of the nth line */
  79.     if (ftruncate(fd, stat_buf.st_size - (linen1 - linen)) < 0) {
  80.       perror("ftruncate");
  81.       return EXIT_FAILURE;
  82.     }
  83.   } else {
  84.     /* The nth line was the last line, so unmap the file */
  85.     if (munmap(map, stat_buf.st_size) < 0) {
  86.       perror("munmap");
  87.       return EXIT_FAILURE;
  88.     }
  89.  
  90.     /* Chop off the last line */
  91.     if (ftruncate(fd, linen - (char *)map) < 0) {
  92.       perror("ftruncate");
  93.       return EXIT_FAILURE;
  94.     }
  95.   }
  96.  
  97.   /* Close the file */
  98.   close(fd);
  99.  
  100.   return EXIT_SUCCESS;
  101. }
Advertisement
Add Comment
Please, Sign In to add comment