chiark / gitweb /
fix typo, thanks to kees
[map-unshare.git] / map-unshare.c
1 #include <stdio.h>
2 #include <stdint.h>
3 #include <string.h>
4 #include <assert.h>
5 #include <inttypes.h>
6 #include <sys/mman.h>
7
8 #include "map-unshare.h"
9
10 #define MAXFLAGS 10
11
12 #define STRING(x) STRING2(x)
13 #define STRING2(x) #x
14
15 void map_unshare(void) {
16   char lbuf[4096];
17   FILE *maps = fopen("/proc/self/maps", "r");
18   assert(maps);
19   while (fgets(lbuf,sizeof(lbuf),maps)) {
20     uintptr_t mstart,mend;
21     unsigned long inum;
22     char flagstr[MAXFLAGS+1];
23     int pathoffset;
24
25     int ll = strlen(lbuf);
26     assert(ll>=1);
27     assert(lbuf[ll-1]=='\n');
28     lbuf[--ll]=0;
29
30     pathoffset=-1;
31     sscanf(lbuf,"%"SCNxPTR"-%"SCNxPTR" %"STRING(MAXFLAGS)"s"
32            " %*"SCNxPTR" %*x:%*x %lu %n",
33            &mstart,&mend, flagstr, &inum, &pathoffset);
34     assert(pathoffset>=0 && pathoffset<=ll);
35     const char *orgpath = lbuf+pathoffset;
36     fprintf(stderr,"%"PRIxPTR"-%"PRIxPTR" %s %lu %s: ",
37             mstart,mend,flagstr,inum,orgpath);
38     int prot =
39       (!!strchr(flagstr,'x') * PROT_EXEC) |
40       (!!strchr(flagstr,'r') * PROT_READ) |
41       (!!strchr(flagstr,'w') * PROT_WRITE);
42     int flags =
43       (!!strchr(flagstr,'p') * MAP_PRIVATE) |
44       (!!strchr(flagstr,'s') * MAP_SHARED);
45
46 #define SKIP(why) { fprintf(stderr,"skip, %s\n",(why)); continue; }
47
48     if (mstart==mend) SKIP("zero length");
49     if (!(prot & PROT_READ)) SKIP("unreadable");
50     if ((prot & PROT_WRITE) && (flags & MAP_SHARED)) SKIP("shared write");
51     if (orgpath[0] != '/') SKIP("no path");
52
53     FILE *copyf = tmpfile();
54     assert(copyf);
55
56     size_t length = mend-mstart;
57     void *startp = (void*)mstart;
58
59     fputs("copy ",stderr);
60     size_t done = fwrite(startp, 1, length, copyf);
61     assert(done == length);
62     int r = fflush(copyf);
63     assert(!r);
64
65     fputs("mmap ",stderr);
66     void *mapped;
67     mapped = mmap(startp, length, prot, MAP_SHARED|MAP_FIXED, fileno(copyf), 0);
68     assert(mapped == startp);
69     fclose(copyf);
70
71     fputs("done.\n",stderr);
72   }
73   assert(!ferror(maps));
74   fclose(maps);
75 }