+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+#include <inttypes.h>
+#include <sys/mman.h>
+
+#include "map-unshare.h"
+
+#define MAXFLAGS 10
+
+#define STRING(x) STRING2(x)
+#define STRING2(x) #x
+
+void map_unshare(void) {
+ char lbuf[4096];
+ FILE *maps = fopen("/proc/self/maps", "r");
+ assert(maps);
+ while (fgets(lbuf,sizeof(lbuf),maps)) {
+ uintptr_t mstart,mend;
+ unsigned long inum;
+ char flagstr[MAXFLAGS+1];
+ int pathoffset;
+
+ int ll = strlen(lbuf);
+ assert(ll>=1);
+ assert(lbuf[ll-1]=='\n');
+ lbuf[--ll]=0;
+
+ pathoffset=-1;
+ sscanf(lbuf,"%"SCNxPTR"-%"SCNxPTR" %"STRING(MAXFLAGS)"s"
+ " %*"SCNxPTR" %*x:%*x %lu %n",
+ &mstart,&mend, flagstr, &inum, &pathoffset);
+ assert(pathoffset>=0 && pathoffset<=ll);
+ const char *orgpath = lbuf+pathoffset;
+ fprintf(stderr,"%"PRIxPTR"-%"PRIxPTR" %s %lu %s: ",
+ mstart,mend,flagstr,inum,orgpath);
+ int prot =
+ (!!strchr(flagstr,'x') * PROT_EXEC) |
+ (!!strchr(flagstr,'r') * PROT_READ) |
+ (!!strchr(flagstr,'w') * PROT_WRITE);
+ int flags =
+ (!!strchr(flagstr,'p') * MAP_PRIVATE) |
+ (!!strchr(flagstr,'s') * MAP_SHARED);
+
+#define SKIP(why) { fprintf(stderr,"skip, %s\n",(why)); continue; }
+
+ if (mstart==mend) SKIP("zero length");
+ if (!(prot & PROT_READ)) SKIP("unreadable");
+ if ((prot & PROT_WRITE) && (flags & MAP_SHARED)) SKIP("shared write");
+ if (orgpath[0] != '/') SKIP("no path");
+
+ FILE *copyf = tmpfile();
+ assert(copyf);
+
+ size_t length = mend-mstart;
+ void *startp = (void*)mstart;
+
+ fputs("copy ",stderr);
+ size_t done = fwrite(startp, 1, length, copyf);
+ assert(done == length);
+ int r = fflush(copyf);
+ assert(!r);
+
+ fputs("mmap ",stderr);
+ void *mapped;
+ mapped = mmap(startp, length, prot, MAP_SHARED|MAP_FIXED, fileno(copyf), 0);
+ assert(mapped = startp);
+ fclose(copyf);
+
+ fputs("done.\n",stderr);
+ }
+ assert(!ferror(maps));
+ fclose(maps);
+}