Created
August 20, 2010 22:20
-
-
Save atr000/541320 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* Copyright (c) 2007 Peter O'Gorman <peter@pogma.com> | |
| * | |
| * Permission is hereby granted, free of charge, to any person | |
| * obtaining a copy of this software and associated documentation | |
| * files (the "Software"), to deal in the Software without | |
| * restriction, including without limitation the rights to use, copy, | |
| * modify, merge, publish, distribute, sublicense, and/or sell copies | |
| * of the Software, and to permit persons to whom the Software is | |
| * furnished to do so, subject to the following conditions: | |
| * | |
| * The above copyright notice and this permission notice shall be | |
| * included in all copies or substantial portions of the Software. | |
| * | |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
| * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |
| * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |
| * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |
| * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
| * SOFTWARE. | |
| */ | |
| #include <sys/types.h> | |
| #include <inttypes.h> | |
| #include <fcntl.h> | |
| #include <sys/stat.h> | |
| #include <stdio.h> | |
| #include <unistd.h> | |
| #include <mach-o/fat.h> | |
| #include <mach-o/loader.h> | |
| #include <stdlib.h> | |
| #include <sys/errno.h> | |
| uint32_t cur_ver = 0; | |
| uint32_t com_ver = 0; | |
| int swap=0; | |
| /* This function stolen from Apple's ld64 sources - licensed APSL */ | |
| uint32_t version_num(const char * string) | |
| { | |
| unsigned long x = 0; | |
| unsigned long y = 0; | |
| unsigned long z = 0; | |
| char* end; | |
| x = strtoul(string, &end, 10); | |
| if ( *end == '.' ) { | |
| y = strtoul(&end[1], &end, 10); | |
| if ( *end == '.' ) { | |
| z = strtoul(&end[1], &end, 10); | |
| } | |
| } | |
| return (x << 16) | ( y << 8 ) | z; | |
| } | |
| void adjust_version(struct mach_header * in) | |
| { | |
| char * pointer; | |
| int x = in->ncmds; | |
| if ((in->magic == MH_MAGIC) || (in->magic == MH_CIGAM)) | |
| pointer = (char*)in + sizeof(struct mach_header); | |
| else if ((in->magic == MH_MAGIC_64) || (in->magic == MH_CIGAM_64)) | |
| pointer = (char*)in + sizeof(struct mach_header_64); | |
| else {fprintf(stderr,"dead\n"); exit(1);} | |
| if ((in->magic == MH_CIGAM) || (in->magic == MH_CIGAM_64)) | |
| swap=1; | |
| else swap=0; | |
| if (swap) { | |
| x=OSSwapInt32(in->ncmds); | |
| } | |
| do { | |
| if (swap) { | |
| if (LC_ID_DYLIB == OSSwapInt32(((struct load_command *)pointer)->cmd)) { | |
| pointer += sizeof(struct load_command); | |
| ((struct dylib *)pointer)->current_version = OSSwapInt32(cur_ver); | |
| ((struct dylib *)pointer)->compatibility_version = OSSwapInt32(com_ver); | |
| x = 0; | |
| } else { | |
| pointer += OSSwapInt32(((struct load_command *)pointer)->cmdsize); | |
| x--; | |
| } | |
| } else { | |
| if (LC_ID_DYLIB == ((struct load_command *)pointer)->cmd) { | |
| pointer += sizeof(struct load_command); | |
| ((struct dylib *)pointer)->current_version = cur_ver; | |
| ((struct dylib *)pointer)->compatibility_version = com_ver; | |
| x = 0; | |
| } else { | |
| pointer += ((struct load_command *)pointer)->cmdsize; | |
| x--; | |
| } | |
| } | |
| } while (x); | |
| } | |
| void usage(void) { | |
| fprintf(stderr,"Usage:\n%s <filename> <compatibility_version> <current_version>\n",getprogname()); | |
| } | |
| int main(int argc, const char * argv[]) | |
| { | |
| int fd = 0; | |
| ssize_t bytesread = 0; | |
| size_t bytes = 0; | |
| struct stat sbuf; | |
| void * buffer; | |
| if (argc != 4) { | |
| fprintf(stderr,"Incorrect number of arguments\n"); | |
| usage(); | |
| exit(1); | |
| } | |
| if (stat(argv[1],&sbuf)) { | |
| fprintf(stderr,"File does not exist\n"); | |
| usage(); | |
| exit(1); | |
| } | |
| com_ver = version_num(argv[2]); | |
| cur_ver = version_num(argv[3]); | |
| if (!(fd = open(argv[1],O_RDWR | O_EXCL ,sbuf.st_mode))) { | |
| fprintf(stderr,"OPen failed %s\n",strerror(errno)); | |
| exit (1); | |
| } | |
| bytes = sbuf.st_size; | |
| buffer = malloc(bytes); | |
| if (!buffer) { | |
| fprintf(stderr,"Failed to allocate %d bytes\n",bytes); | |
| exit(1); | |
| } | |
| do { | |
| bytesread = read(fd,buffer,bytes); | |
| if (bytesread == -1) { | |
| fprintf(stderr,"Error %s\n",strerror(errno)); | |
| exit(1); | |
| } | |
| else if (bytesread == 0) | |
| bytes = 0; | |
| else | |
| bytes -= bytesread; | |
| } while (bytes); | |
| if (lseek(fd,0,SEEK_SET)) { | |
| fprintf(stderr,"Failed to seek to beginning of file\n"); | |
| exit(1); | |
| } | |
| if ((((struct fat_header*)buffer)->magic == FAT_MAGIC) || | |
| (((struct fat_header*)buffer)->magic == FAT_CIGAM)) { | |
| struct fat_header * fh = (struct fat_header*)buffer; | |
| uint32_t num_arches = fh->nfat_arch; | |
| struct fat_arch * arch= (struct fat_arch *)((char*)buffer + sizeof(struct fat_header)); | |
| #ifdef __LITTLE_ENDIAN__ | |
| num_arches = OSSwapInt32(fh->nfat_arch); | |
| #endif | |
| do { | |
| #ifdef __LITTLE_ENDIAN__ | |
| adjust_version((struct mach_header*)((char*)buffer + OSSwapInt32(arch->offset))); | |
| #else | |
| adjust_version((struct mach_header*)((char*)buffer + arch->offset)); | |
| #endif | |
| arch++; | |
| num_arches--; | |
| } while(num_arches); | |
| } else | |
| adjust_version(buffer); | |
| bytes = 0; | |
| do { | |
| bytes += write(fd,buffer,sbuf.st_size - bytes); | |
| } while (sbuf.st_size - bytes); | |
| if (fd) close(fd); | |
| fd = 0; | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment