#include #include #include #include #include #include #include #include #include int debug = 0; unsigned char *file_map; /*--- unsigned char file_name[1024]; ---*/ /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ unsigned char *memsearch(unsigned char *buffer, __off_t *len, unsigned char *search, unsigned int search_len) { unsigned char *_search = search; unsigned int _search_len = search_len; __off_t _len = *len; while(*len) { _search = search; _search_len = search_len; _len = *len; if(buffer < file_map) { printf("INTERNAL ERROR\n"); exit(-1); } while((*buffer == *_search) && (_len > 0) && (_search_len > 0)) { buffer++; _search++; _len--; _search_len--; } if(_len == 0) { *len = 0; return NULL; } if(_search_len == 0) { /*--- gefunden ---*/ return buffer - search_len; } *len = _len; buffer++; (*len)--; } return NULL; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int patch_one_file(char *path, unsigned char *search, unsigned char *replace) { struct stat stat_value; unsigned char *pos; int fd; int ret; __off_t rest_len; unsigned int null_bytes = 0; unsigned int search_len = (unsigned int)strlen((const char *)search); unsigned int replace_len = (unsigned int)strlen((const char *)replace); if(replace_len > search_len) { fprintf(stderr, "[%s] search-len < replace-len\n", __FUNCTION__); exit(-1); } /*--- if(strstr(path, "autom4te.cfg")) { debug = 1; } ---*/ /*--- if(strstr(path, "strip")) { debug = 1; } ---*/ fd = open(path, O_RDWR, 0666); if(fd < 0) { fprintf(stderr, "[%s] unable to open %s for RDWR: %s\n", __FUNCTION__, path, strerror(errno)); return -errno; } ret = fstat(fd, &stat_value); if(ret < 0) { fprintf(stderr, "[%s] unable to query file attributes for file %s: %s\n", __FUNCTION__, path, strerror(errno)); return -errno; } rest_len = stat_value.st_size; if(rest_len < search_len) { goto nothing_to_do; } file_map = mmap(NULL, (size_t)stat_value.st_size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, fd, 0); if(file_map == (void *)-1) { fprintf(stderr, "[%s] unable to map file %s (size %ld): %s\n", __FUNCTION__, path, stat_value.st_size, strerror(errno)); return -errno; } /*--- printf("[%s] \"%s\" mapped (%ld bytes)\n", __FUNCTION__, path, stat_value.st_size); ---*/ pos = file_map; do { int local_len; int tail_len; unsigned char *p; if(rest_len < search_len) break; pos = memsearch(pos, &rest_len, search, search_len); if(pos) { local_len = (unsigned int)strlen((char *)pos); tail_len = local_len - search_len; if(debug) { printf("found: pos=0x%p tail_len=0x%x rest_len=0x%x\n", pos, tail_len, (int)rest_len); printf("\tfrom (%d bytes): %s\n", local_len, pos); } memcpy(pos, replace, replace_len); if(tail_len) { memcpy(pos + replace_len, pos + search_len, tail_len); } *(pos + replace_len + tail_len) = '\0'; #if 0 printf("\n'%s' zero rest (%d Bytes) 0x%lx - 0x%lx\n", path, search_len - replace_len, file_map - (pos + replace_len + tail_len), file_map - (pos + search_len + tail_len)); #endif for(p = (pos + replace_len + tail_len) ; p < (pos + search_len + tail_len) ; ) *p++ = '\0'; /*--- printf("\t to (%ld bytes): %s\n", strlen((char *)pos), pos); ---*/ } } while(pos); /*--------------------------------------------------------------------------------------*\ * check NULL bytes at end \*--------------------------------------------------------------------------------------*/ pos = file_map + stat_value.st_size - 1; if(debug) { printf("file size %ld, last bytes %x %x %x %x \n", stat_value.st_size, pos[-3], pos[-2], pos[-1], pos[0]); } if(*pos == 0x00) { while((*pos == '\0') && (pos > file_map)) { null_bytes++; pos--; } /*--- if(null_bytes) { ---*/ /*--- printf("file '%s' has %d NULL bytes\n", path, null_bytes); ---*/ /*--- } ---*/ } munmap(file_map, stat_value.st_size); nothing_to_do: close(fd); if(null_bytes && (null_bytes >= (search_len - replace_len))) { int old, new; char *new_name = malloc(strlen(path) + 20); char *buffer; int count; sprintf(new_name, "%s.tmp.%d", path, getpid()); if(rename(path, new_name)) { fprintf(stderr, "rename %s failed\n", new_name); exit(-1); } old = open(new_name, O_RDONLY, 0); if(old < 0) { fprintf(stderr, "open %s failed\n", new_name); exit(-1); } new = open(path, O_WRONLY | O_CREAT, stat_value.st_mode); if(new < 0) { fprintf(stderr, "open %s failed\n", path); exit(-1); } buffer = malloc(stat_value.st_size); count = read(old, buffer, stat_value.st_size - null_bytes); if(debug) { printf("read %d bytes from %s\n", count, new_name); } if(count > 0) { count = write(new, buffer, count); if(debug) { printf("write %d bytes to %s errno %d %s\n", count, path, errno, strerror(errno)); } if(count > 0) { close(old); unlink(new_name); } } close(new); free(new_name); free(buffer); } return 0; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int main(int argc, char *argv[]) { if(argc != 4) return -1; /*--- strcpy(file_name, argv[1]); ---*/ return patch_one_file(argv[1], (unsigned char *)argv[2], (unsigned char *)argv[3]); }