Mercurial > ~dholland > hg > ag > index.cgi
view insertsums/insertsums.c @ 2:4b08ee1ecb99
Adjust install notes to clarify that Wine applies only to the Windows build.
(Thanks to Perry Metzger for test-driving.)
author | David A. Holland |
---|---|
date | Sun, 26 Apr 2009 17:58:26 -0400 |
parents | 13d2b8934445 |
children |
line wrap: on
line source
/* * AnaGram, A System for Syntax Directed Programming * Copyright 2006 David A. Holland. All Rights Reserved. * See the file COPYING for license and usage terms. */ /* * insertsums - patch checksum data block into binary * usage: insertsums sums.dat sums.ctl * * The patch area is a region of size TARGETSIZE that the * checksum program finds for us. We check to make sure it * contains the right magic string before patching over it, * just in case. * * Everything is XOR'd with PADBYTE as something of a paranoia * measure against viruses. * * XXX the definitions of TARGETSIZE and TARGETLABEL should * be shared with the AG code. PADBYTE too. * * This module is new code as of June 2006 and should be much more * portable than the old stuff. */ #include <assert.h> #include <ctype.h> #include <errno.h> #include <fcntl.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #ifndef O_BINARY #define O_BINARY 0 #define O_TEXT 0 #endif #define TARGETSIZE 512 #define TARGETLABEL "Checksum data:\n" #define PADBYTE 0xae static char info[TARGETSIZE]; static const char *me; static const char label[] = TARGETLABEL; //////////////////////////////////////////////////////////// static void setme(const char *av0) { me = strrchr(av0, '/'); if (me) { me++; } else { me = av0; } } static void die(const char *fmt, ...) { va_list ap; fprintf(stderr, "%s: ", me); va_start(ap, fmt); vfprintf(stderr, fmt, ap); fputc('\n', stderr); exit(EXIT_FAILURE); } //////////////////////////////////////////////////////////// static int isnumber(const char *s) { size_t i; for (i=0; s[i]; i++) { if (!isdigit((unsigned char) s[i])) { return 0; } } // protect against possible overflow, just in case return i<10; } //////////////////////////////////////////////////////////// static void putsums(const char *file, long offset) { char buf[TARGETSIZE]; ssize_t len; int fd; fd = open(file, O_RDWR); if (fd<0) { die("%s: %s", file, strerror(errno)); } if (lseek(fd, offset, SEEK_SET)<0) { die("%s: lseek: %s", file, strerror(errno)); } len = read(fd, buf, sizeof(buf)); if (len < 0) { die("%s: read: %s", file, strerror(errno)); } if ((size_t)len != TARGETSIZE) { die("%s: read: short count (past EOF?)", file); } if (memcmp(buf, label, strlen(label))!=0) { die("%s: patch area label is missing", file); } if (lseek(fd, offset, SEEK_SET)<0) { die("%s: lseek: %s", file, strerror(errno)); } len = write(fd, info, sizeof(info)); if (len < 0) { die("%s: write: %s", file, strerror(errno)); } if ((size_t)len != TARGETSIZE) { die("%s: write: short count", file); } if (close(fd)<0) { die("%s: close: %s", file, strerror(errno)); } //printf("%s: patched %s\n", me, file); } static void storesums(const char *ctlfile) { char buf[128]; FILE *f; int lineno = 0; f = fopen(ctlfile, "rt"); if (!f) { die("%s: fopen failed", ctlfile); } while (fgets(buf, sizeof(buf), f)) { /* format is: pathname offset */ char *words[3], *s; int nwords = 0; lineno++; if (*buf=='#') { continue; } for (s = strtok(buf, " \t\r\n"); s; s = strtok(NULL, " \t\r\n")) { if (nwords >= 3) { break; } words[nwords++] = s; } if (nwords != 2 || !isnumber(words[1])) { die("%s: Invalid line %d", ctlfile, lineno); } putsums(words[0], atol(words[1])); } if (ferror(f)) { die("%s: read error", ctlfile); } fclose(f); } //////////////////////////////////////////////////////////// static void hidesums(void) { size_t i; for (i=strlen(label); i<sizeof(info); i++) { info[i] = (char) (PADBYTE ^ (unsigned char)info[i]); } } //////////////////////////////////////////////////////////// static void loadsums(const char *sumpath) { ssize_t readlen; size_t loadpos, maxlen, infolen; int fd; assert(strlen(label) < TARGETSIZE); strcpy(info, label); loadpos = strlen(info); maxlen = sizeof(info) - loadpos; fd = open(sumpath, O_TEXT|O_RDONLY); if (fd < 0) { die("%s: %s", sumpath, strerror(errno)); } readlen = read(fd, info+loadpos, maxlen); if (readlen < 0) { die("%s: read: %s", sumpath, strerror(errno)); } if (readlen == 0) { die("%s: read: empty file?", sumpath); } close(fd); infolen = loadpos+readlen; if (infolen >= sizeof(info)) { die("%s: Too much information!", sumpath); /* :-) */ } //printf("%s: %lu bytes prepared\n", me, (unsigned long) infolen); while (infolen < sizeof(info)) { info[infolen++] = 0; } } //////////////////////////////////////////////////////////// static void usage(void) { die("Usage: %s sums.dat sums.ctl", me); } int main(int argc, char *argv[]) { setme(argv[0]); if (argc != 3) { usage(); } loadsums(argv[1]); hidesums(); storesums(argv[2]); return EXIT_SUCCESS; }