More accurate string => off_t conversion
[pcu.git] / mincore.c
blobc3aa61811bd020499ff43c0155cfa4deb9dba16a
1 #include "compat-util.h"
3 static int usage(const char * argv0)
5 fprintf(stderr, "Usage: %s [-o OFFSET] [-l LENGTH] FILE...\n", argv0);
6 return 1;
9 static void mincore_stats(const char *path, off_t offset, off_t len)
11 char *map;
12 unsigned char *vec;
13 size_t vec_len;
14 size_t map_len;
15 off_t map_offset;
16 int fd;
17 size_t i;
18 static const char *fmt = sizeof(void *) == 8 ?
19 "%s: %016lx %x\n": "%s: %08lx %x\n";
21 if ((fd = open(path, O_RDONLY|O_NOATIME)) < 0) {
22 fprintf(stderr, "%s: open(): %s\n", path, strerror(errno));
23 return;
26 if (!len) {
27 struct stat sb;
29 if (fstat(fd, &sb) < 0) {
30 fprintf(stderr, "%s: fstat(%d): %s\n",
31 path, fd, strerror(errno));
32 goto err_close;
34 len = sb.st_size - offset;
37 vec_len = (len + page_size() - 1) / page_size();
38 if (!(vec = malloc(vec_len))) {
39 fprintf(stderr, "%s: malloc(%lu): %s\n",
40 path, (unsigned long)vec_len, strerror(errno));
41 goto err_close;
44 map_len = PAGE_ALIGN(len);
45 map_offset = PAGE_ALIGN_DOWN(offset + 1);
47 map = mmap(NULL, map_len, PROT_READ, MAP_SHARED, fd, map_offset);
48 if (!map) {
49 fprintf(stderr, "%s: mmap(%lu): %s\n",
50 path, (unsigned long)vec_len, strerror(errno));
51 goto err_free;
54 if (mincore(map, map_len, vec) < 0) {
55 fprintf(stderr, "%s: mincore(%lu): %s\n",
56 path, (unsigned long)vec_len, strerror(errno));
57 goto err_munmap;
60 for (i = 0; i < vec_len; ++i)
61 printf(fmt, path,
62 (unsigned long)(page_size() * i) + map_offset,
63 vec[i] & 1);
64 err_munmap:
65 munmap(map, map_len);
66 err_free:
67 free(vec);
68 err_close:
69 close(fd);
72 int main(int argc, char * const argv[])
74 off_t offset = 0;
75 off_t len = 0;
76 int argi = 1;
77 int opt;
79 while ((opt = getopt(argc, argv, "o:l:h")) != -1) {
80 char *err;
82 argi += 2;
83 switch(opt) {
84 case 'o':
85 offset = cstr_to_off_t(optarg, &err, 10);
86 if (*err || offset < 0) {
87 fprintf(stderr, "offset must be >= 0\n");
88 return 1;
90 break;
91 case 'l':
92 len = cstr_to_off_t(optarg, &err, 10);
93 if (*err || len < 0) {
94 fprintf(stderr, "length must be >= 0\n");
95 return 1;
97 break;
98 default:
99 return usage(argv[0]);
103 if (argi >= argc)
104 return usage(argv[0]);
106 for (; argi < argc; ++argi)
107 mincore_stats(argv[argi], offset, len);
108 return 0;