]>
git.scottworley.com Git - overonion/blob - reverse_lib.c
2 #define _FILE_OFFSET_BITS 64
10 #include <sys/types.h>
14 void reverse_file(const char* input_filename
, FILE* output_stream
) {
15 int fd
= open(input_filename
, O_RDONLY
);
16 if (fd
== -1) err(EX_NOINPUT
, "Could not open specified file");
19 if (fstat(fd
, &stats
) == -1) err(EX_NOINPUT
, "Could not stat input");
21 long page_size
= sysconf(_SC_PAGE_SIZE
);
22 off_t pages
= (stats
.st_size
- 1) / page_size
+ 1;
23 long map_size
= pages
* page_size
;
24 char *m
= mmap(NULL
, map_size
, PROT_READ
, MAP_SHARED
, fd
, 0);
25 if (m
== MAP_FAILED
) err(EX_NOINPUT
, "Could not mmap input");
27 for (off_t p
= stats
.st_size
- 1; p
>= 0; p
--) {
28 if (fputc(m
[p
], output_stream
) == EOF
) errx(EX_IOERR
, "Could not write");
31 if (munmap(m
, map_size
) == -1) err(EX_IOERR
, "Could not unmap input");
32 if (close(fd
) == -1) err(EX_IOERR
, "Could not close input");
35 /* Create a temporary file in $TMPDIR, or /tmp if TMPDIR is not set.
36 * Caller must free temp_filename and fclose temp_file. Succeeds or terminates
38 static void make_temporary_file(char** temp_filename
, FILE** temp_file
) {
39 char* TMPDIR
= getenv("TMPDIR");
43 if (asprintf(temp_filename
, "%s/reverse.XXXXXX", TMPDIR
) == -1) {
44 errx(EX_OSERR
, "Could not assemble temporary filename");
46 int fd
= mkstemp(*temp_filename
);
47 if (fd
== -1) err(EX_IOERR
, "Could not make a temporary file");
48 *temp_file
= fdopen(fd
, "w");
49 if (*temp_file
== NULL
) err(EX_IOERR
, "Could not open temporary file");
52 /* Copy data from input to output until EOF is reached. */
53 static void copy(FILE* input
, FILE* output
) {
57 if (ferror(input
)) errx(EX_IOERR
, "Could not read");
58 if (!feof(input
)) errx(EX_IOERR
, "Unexpected end of file");
61 if (fputc(c
, output
) == EOF
) errx(EX_IOERR
, "Could not write");
65 void reverse_stream(FILE* input_stream
, FILE* output_stream
) {
68 make_temporary_file(&temp_filename
, &temp_file
);
70 copy(input_stream
, temp_file
);
71 if (fclose(temp_file
) != 0) err(EX_IOERR
, "Could not close temporary file");
73 reverse_file(temp_filename
, output_stream
);
75 if (unlink(temp_filename
) == -1) err(EX_IOERR
, "Could not remove temporary file");