diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/strip.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/strip.c')
-rwxr-xr-x | sys/src/cmd/strip.c | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/sys/src/cmd/strip.c b/sys/src/cmd/strip.c new file mode 100755 index 000000000..79644c6f6 --- /dev/null +++ b/sys/src/cmd/strip.c @@ -0,0 +1,170 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <mach.h> + +void +error(char* fmt, ...) +{ + va_list arg; + char *e, s[256]; + + va_start(arg, fmt); + e = seprint(s, s+sizeof(s), "%s: ", argv0); + e = vseprint(e, s+sizeof(s), fmt, arg); + e = seprint(e, s+sizeof(s), "\n"); + va_end(arg); + + write(2, s, e-s); +} + +static void +usage(void) +{ + error("usage: %s -o ofile file\n\t%s file ...\n", argv0, argv0); + exits("usage"); +} + +static int +strip(char* file, char* out) +{ + Dir *dir; + int fd, i; + Fhdr fhdr; + Exec *exec; + ulong mode; + void *data; + vlong length; + + if((fd = open(file, OREAD)) < 0){ + error("%s: open: %r", file); + return 1; + } + + if(!crackhdr(fd, &fhdr)){ + error("%s: %r", file); + close(fd); + return 1; + } + for(i = MIN_MAGIC; i <= MAX_MAGIC; i++){ + if(fhdr.magic == _MAGIC(0, i) || fhdr.magic == _MAGIC(HDR_MAGIC, i)) + break; + } + if(i > MAX_MAGIC){ + error("%s: not a recognizeable binary", file); + close(fd); + return 1; + } + + if((dir = dirfstat(fd)) == nil){ + error("%s: stat: %r", file); + close(fd); + return 1; + } + + length = fhdr.datoff+fhdr.datsz; + if(length == dir->length){ + if(out == nil){ /* nothing to do */ + error("%s: already stripped", file); + free(dir); + close(fd); + return 0; + } + } + if(length > dir->length){ + error("%s: strange length", file); + close(fd); + free(dir); + return 1; + } + + mode = dir->mode; + free(dir); + + if((data = malloc(length)) == nil){ + error("%s: malloc failure", file); + close(fd); + return 1; + } + seek(fd, 0LL, 0); + if(read(fd, data, length) != length){ + error("%s: read: %r", file); + close(fd); + free(data); + return 1; + } + close(fd); + + exec = data; + exec->syms = 0; + exec->spsz = 0; + exec->pcsz = 0; + + if(out == nil){ + if(remove(file) < 0) { + error("%s: remove: %r", file); + free(data); + return 1; + } + out = file; + } + if((fd = create(out, OWRITE, mode)) < 0){ + error("%s: create: %r", out); + free(data); + return 1; + } + if(write(fd, data, length) != length){ + error("%s: write: %r", out); + close(fd); + free(data); + return 1; + } + close(fd); + free(data); + + return 0; +} + +void +main(int argc, char* argv[]) +{ + int r; + char *p; + + p = nil; + + ARGBEGIN{ + default: + usage(); + break; + case 'o': + p = ARGF(); + if(p == nil) + usage(); + break; + }ARGEND; + + switch(argc){ + case 0: + usage(); + return; + case 1: + if(p != nil){ + r = strip(*argv, p); + break; + } + /*FALLTHROUGH*/ + default: + r = 0; + while(argc > 0){ + r |= strip(*argv, nil); + argc--; + argv++; + } + break; + } + + if(r) + exits("error"); + exits(0); +} |