Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <errno.h>
- #include <unistd.h>
- #include <sys/mman.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- enum
- {
- LINE_NUM = 2,
- DEC_BASE = 10,
- EXIT_STATUS_SUCCESS = 0,
- EXIT_STATUS_ERROR = 1
- };
- enum Args
- {
- ARG_SELF,
- ARG_PATH,
- ARG_LINES,
- ARG_NUM = ARG_LINES + LINE_NUM
- };
- void
- put_line(const unsigned char *file, ssize_t file_size, ssize_t off)
- {
- while(off < file_size && file[off] != '\n') {
- putchar_unlocked(file[off++]);
- }
- putchar_unlocked('\n');
- }
- int
- main(int argc, char *argv[])
- {
- int exit_status = EXIT_STATUS_SUCCESS;
- errno = 0;
- if (argc < ARG_NUM) {
- fprintf(stderr, "error: Too few arguments. Expected %d, have %d\n", ARG_NUM - 1, argc - 1);
- exit_status = EXIT_STATUS_ERROR;
- goto exit0;
- }
- int fd;
- if ((fd = open(argv[ARG_PATH], O_RDONLY)) == -1) {
- perror("open");
- exit_status = EXIT_STATUS_ERROR;
- goto exit0;
- }
- long line[LINE_NUM];
- for (int i = 0; i < LINE_NUM; ++i)
- {
- char *temp;
- line[i] = strtol(argv[ARG_LINES + i], &temp, DEC_BASE);
- if (*temp) {
- fprintf(stderr, "strtol: Invalid value of argument %d\n", ARG_LINES + i - 1);
- exit_status = EXIT_STATUS_ERROR;
- goto exit1;
- } else if (errno) {
- perror("strtol");
- exit_status = EXIT_STATUS_ERROR;
- goto exit1;
- }
- }
- if (line[0] <= 0 || line[1] <= 0) {
- fprintf(stderr, "error: Non-positive argument\n");
- exit_status = EXIT_STATUS_ERROR;
- goto exit1;
- }
- if (line[0] >= line[1]) {
- goto exit1;
- }
- struct stat stat_buf;
- if (fstat(fd, &stat_buf)) {
- perror("fstat");
- exit_status = EXIT_STATUS_ERROR;
- goto exit1;
- }
- ssize_t filesize = 0;
- if (__builtin_add_overflow(0, stat_buf.st_size, &filesize)) {
- fprintf(stderr, "error: file too big\n");
- exit_status = EXIT_STATUS_ERROR;
- goto exit1;
- }
- if (!filesize) {
- goto exit1;
- }
- unsigned char *file = mmap(NULL, filesize, PROT_READ, MAP_PRIVATE, fd, 0);
- if (errno) {
- perror("mmap");
- exit_status = EXIT_STATUS_ERROR;
- goto exit1;
- }
- ssize_t off = 0, start = -1, end = -1;
- while (off < filesize) {
- if (line[0] == 1) {
- start = off;
- }
- if (line[1] == 1) {
- end = off - 1;
- break;
- }
- while(off < filesize && file[off] != '\n') {
- ++off;
- }
- if (off < filesize) {
- ++off;
- }
- --line[0];
- --line[1];
- }
- if (start == -1) {
- goto exit2;
- }
- if (end == -1) {
- end = filesize - 1;
- }
- while (end >= start) {
- while (end > start && file[end - 1] != '\n') {
- --end;
- }
- put_line(file, filesize, end--);
- }
- exit2:
- munmap(file, filesize);
- exit1:
- close(fd);
- exit0:
- return exit_status;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement