Advertisement
Guest User

Untitled

a guest
Dec 16th, 2017
64
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.15 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <errno.h>
  4.  
  5. #include <unistd.h>
  6. #include <sys/mman.h>
  7. #include <sys/types.h>
  8. #include <sys/stat.h>
  9. #include <fcntl.h>
  10.  
  11. enum
  12. {
  13.     LINE_NUM = 2,
  14.     DEC_BASE = 10,
  15.     EXIT_STATUS_SUCCESS = 0,
  16.     EXIT_STATUS_ERROR = 1
  17. };
  18.  
  19. enum Args
  20. {
  21.     ARG_SELF,
  22.     ARG_PATH,
  23.     ARG_LINES,
  24.     ARG_NUM = ARG_LINES + LINE_NUM
  25. };
  26.  
  27. void
  28. put_line(const unsigned char *file, ssize_t file_size, ssize_t off)
  29. {
  30.     while(off < file_size && file[off] != '\n') {
  31.         putchar_unlocked(file[off++]);
  32.     }
  33.     putchar_unlocked('\n');
  34. }
  35.  
  36. int
  37. main(int argc, char *argv[])
  38. {
  39.     int exit_status = EXIT_STATUS_SUCCESS;
  40.     errno = 0;
  41.     if (argc < ARG_NUM) {
  42.         fprintf(stderr, "error: Too few arguments. Expected %d, have %d\n", ARG_NUM - 1, argc - 1);
  43.         exit_status = EXIT_STATUS_ERROR;
  44.         goto exit0;
  45.     }
  46.  
  47.     int fd;
  48.     if ((fd = open(argv[ARG_PATH], O_RDONLY)) == -1) {
  49.         perror("open");
  50.         exit_status = EXIT_STATUS_ERROR;
  51.         goto exit0;
  52.     }
  53.  
  54.     long line[LINE_NUM];
  55.     for (int i = 0; i < LINE_NUM; ++i)
  56.     {
  57.         char *temp;
  58.         line[i] = strtol(argv[ARG_LINES + i], &temp, DEC_BASE);
  59.  
  60.         if (*temp) {
  61.             fprintf(stderr, "strtol: Invalid value of argument %d\n", ARG_LINES + i - 1);
  62.             exit_status = EXIT_STATUS_ERROR;
  63.             goto exit1;
  64.         } else if (errno) {
  65.             perror("strtol");
  66.             exit_status = EXIT_STATUS_ERROR;
  67.             goto exit1;
  68.         }
  69.     }
  70.  
  71.     if (line[0] <= 0 || line[1] <= 0) {
  72.         fprintf(stderr, "error: Non-positive argument\n");
  73.         exit_status = EXIT_STATUS_ERROR;
  74.         goto exit1;
  75.     }
  76.  
  77.     if (line[0] >= line[1]) {
  78.         goto exit1;
  79.     }
  80.  
  81.     struct stat stat_buf;
  82.     if (fstat(fd, &stat_buf)) {
  83.         perror("fstat");
  84.         exit_status = EXIT_STATUS_ERROR;
  85.         goto exit1;
  86.     }
  87.     ssize_t filesize = 0;
  88.     if (__builtin_add_overflow(0, stat_buf.st_size, &filesize)) {
  89.         fprintf(stderr, "error: file too big\n");
  90.         exit_status = EXIT_STATUS_ERROR;
  91.         goto exit1;
  92.     }
  93.    
  94.     if (!filesize) {
  95.         goto exit1;
  96.     }
  97.  
  98.     unsigned char *file = mmap(NULL, filesize, PROT_READ, MAP_PRIVATE, fd, 0);
  99.     if (errno) {
  100.         perror("mmap");
  101.         exit_status = EXIT_STATUS_ERROR;
  102.         goto exit1;
  103.     }
  104.  
  105.     ssize_t off = 0, start = -1, end = -1;
  106.  
  107.     while (off < filesize) {
  108.         if (line[0] == 1) {
  109.             start = off;
  110.         }
  111.         if (line[1] == 1) {
  112.             end = off - 1;
  113.             break;
  114.         }
  115.  
  116.         while(off < filesize && file[off] != '\n') {
  117.             ++off;
  118.         }
  119.         if (off < filesize) {
  120.             ++off;
  121.         }
  122.  
  123.         --line[0];
  124.         --line[1];
  125.     }
  126.  
  127.     if (start == -1) {
  128.         goto exit2;
  129.     }
  130.  
  131.     if (end == -1) {
  132.         end = filesize - 1;
  133.     }
  134.  
  135.     while (end >= start) {
  136.         while (end > start && file[end - 1] != '\n') {
  137.             --end;
  138.         }
  139.         put_line(file, filesize, end--);
  140.     }
  141.  
  142. exit2:
  143.     munmap(file, filesize);
  144.  
  145. exit1:
  146.     close(fd);
  147.  
  148. exit0:
  149.     return exit_status;
  150. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement