Created
October 12, 2010 02:41
-
-
Save atr000/621583 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
// -*- c-basic-offset:2; tab-width:8; -*- | |
/* | |
* change-bundle-id.m | |
* | |
* Created by Chris Suter on 16/5/2008. | |
* Copyright 2008 Coriolis Systems. All rights reserved. | |
* | |
*/ | |
#import <Foundation/Foundation.h> | |
#import <stdio.h> | |
#import <assert.h> | |
#import <mach-o/fat.h> | |
#import <mach-o/loader.h> | |
#import <libkern/OSByteOrder.h> | |
#import <sys/stat.h> | |
#import <sys/mman.h> | |
int main (int argc, const char * argv[]) | |
{ | |
if (argc < 4) { | |
printf ("usage: %s <file> <bundle ID> <bundle name>\n" | |
" Updates the bundle ID held in Info.plist section of the mach-o file.\n", | |
argv[0]); | |
return 1; | |
} | |
[[NSAutoreleasePool alloc] init]; | |
NSString *newID = [NSString stringWithUTF8String:argv[2]]; | |
NSString *newName = [NSString stringWithUTF8String:argv[3]]; | |
int fd = open (argv[1], O_RDWR); | |
if (fd < 0) { | |
fprintf (stderr, "Failed to open `%s'\n", argv[1]); | |
return 1; | |
} | |
assert (fd >= 0); | |
struct stat sb; | |
if (fstat (fd, &sb) < 0) { | |
fprintf (stderr, "fstat failed\n"); | |
return 1; | |
} | |
void *file = mmap (NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); | |
if (!file) { | |
fprintf (stderr, "mmap failed\n"); | |
return 1; | |
} | |
struct fat_header *fat_hdr = (struct fat_header *)file; | |
struct mach_header *mach_hdr = NULL; | |
unsigned num_archs, arch_ndx = 0; | |
struct fat_arch *arch; | |
unsigned num_done = 0; | |
bool swap_mach; | |
bool swap_fat = fat_hdr->magic != FAT_MAGIC; | |
if (swap_fat && fat_hdr->magic != FAT_CIGAM) { | |
// See if it's thin file... | |
mach_hdr = (struct mach_header *)file; | |
if (mach_hdr->magic != MH_MAGIC && mach_hdr->magic != MH_CIGAM) { | |
fprintf (stderr, "Unexpected FAT or MACH-O header\n"); | |
return 1; | |
} | |
arch = NULL; | |
num_archs = 1; | |
goto thin_file; | |
} | |
num_archs = swap_fat ? OSSwapInt32 (fat_hdr->nfat_arch) : fat_hdr->nfat_arch; | |
arch = (struct fat_arch *)&fat_hdr[1]; | |
for (arch_ndx = 0; | |
arch_ndx < num_archs; | |
++arch_ndx, ++arch) { | |
mach_hdr = (struct mach_header *)((char *)file | |
+ (swap_fat ? OSSwapInt32 (arch->offset) : arch->offset)); | |
thin_file: | |
swap_mach = mach_hdr->magic != MH_MAGIC; | |
if (swap_mach && mach_hdr->magic != MH_CIGAM) { | |
fprintf (stderr, "Unexpected MACH-O header\n"); | |
return 1; | |
} | |
unsigned num_cmds = mach_hdr->ncmds; | |
if (swap_mach) | |
num_cmds = OSSwapInt32 (num_cmds); | |
struct load_command *lc = (struct load_command *)&mach_hdr[1]; | |
unsigned cmd_size; | |
for (unsigned cmd_ndx = 0; | |
cmd_ndx < num_cmds; | |
++cmd_ndx, lc = (struct load_command *)((char *)lc + cmd_size)) { | |
uint32_t cmd = swap_mach ? OSSwapInt32 (lc->cmd) : lc->cmd; | |
cmd_size = swap_mach ? OSSwapInt32 (lc->cmdsize) : lc->cmdsize; | |
if (cmd != LC_SEGMENT) | |
continue; | |
struct segment_command *sc = (struct segment_command *)lc; | |
if (memcmp (sc->segname, "__TEXT", 7)) | |
continue; | |
unsigned num_sects = swap_mach ? OSSwapInt32 (sc->nsects) : sc->nsects; | |
struct section *sect = (struct section *)&sc[1]; | |
for (unsigned sect_ndx = 0; sect_ndx < num_sects; ++sect_ndx, ++sect) { | |
if (memcmp (sect->sectname, "__info_plist", 13)) | |
continue; | |
uint32_t offset = swap_mach ? OSSwapInt32 (sect->offset) : sect->offset; | |
uint32_t size = swap_mach ? OSSwapInt32 (sect->size) : sect->size; | |
NSString *error; | |
// Got it. Now read it in and parse it | |
NSMutableDictionary *plist | |
= [NSPropertyListSerialization propertyListFromData: | |
[NSData dataWithBytesNoCopy:(char *)mach_hdr + offset | |
length:size | |
freeWhenDone:NO] | |
mutabilityOption:NSPropertyListMutableContainers | |
format:NULL | |
errorDescription:&error]; | |
if (!plist) { | |
fprintf (stderr, "Unable to parse property list\n"); | |
return 1; | |
} | |
[plist setObject:newID forKey:(NSString *)kCFBundleIdentifierKey]; | |
[plist setObject:newName forKey:(NSString *)kCFBundleNameKey]; | |
NSData *d = [NSPropertyListSerialization dataFromPropertyList:plist | |
format:kCFPropertyListXMLFormat_v1_0 | |
errorDescription:&error]; | |
assert (d); | |
if ([d length] > size) { | |
fprintf (stderr, "No room for new bundle ID\n"); | |
return 1; | |
} | |
memcpy ((char *)mach_hdr + offset, [d bytes], [d length]); | |
bzero ((char *)mach_hdr + offset + [d length], size - [d length]); | |
sect->size = swap_mach ? OSSwapInt32 ([d length]) : [d length]; | |
++num_done; | |
goto next_arch; | |
} // for (...sect_ndx...) | |
} // for (...cmd_ndx...) | |
next_arch: | |
; | |
} // for (...arch_ndx...) | |
printf ("Updated bundle ID for %u archictecture(s)\n", num_done); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment