-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpread.c
More file actions
48 lines (37 loc) · 1.37 KB
/
pread.c
File metadata and controls
48 lines (37 loc) · 1.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#define _GNU_SOURCE
#include "common.h"
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <stdlib.h>
#include <unistd.h>
static const char USAGE[] = "USAGE: pread <PATH> <OFFSET> <SIZE>\n";
int my_pread(int argc, char **argv) {
ASSERT(argc == 3, EX_USAGE, USAGE);
errno = 0;
char *endptr;
unsigned long long offset = strtoull(argv[1], &endptr, 10);
ASSERT(*endptr == '\0' && errno == 0, EX_USAGE, "Invalid offset\n");
unsigned long long size = strtoll(argv[2], &endptr, 10);
ASSERT(*endptr == '\0' && errno == 0, EX_USAGE, "Invalid size\n");
int fd = open(argv[0], O_RDONLY);
ASSERT(fd != -1, EX_NOPERM, "open: %s\n", strerror(errno));
char buf[8192];
size_t cur_pointer = offset;
const size_t end_pointer = size + offset;
while (cur_pointer < end_pointer) {
size_t remaining = end_pointer - cur_pointer;
size_t read_chunk = remaining > sizeof(buf) ? sizeof(buf) : remaining;
ssize_t size = pread(fd, buf, read_chunk, cur_pointer);
ASSERT(size != -1, EX_IOERR, "pread: %s\n", strerror(errno));
ASSERT(size != 0, EX_IOERR, "pread: unexpected EOF\n");
cur_pointer += size;
size_t total_written = 0;
do {
ssize_t write_size = write(1, buf + total_written, size - total_written);
ASSERT(write_size != -1, EX_IOERR, "write: %s\n", strerror(errno));
total_written += write_size;
} while (total_written != read_chunk);
}
return EXIT_SUCCESS;
}