Skip to content

Instantly share code, notes, and snippets.

@atr000
Created October 12, 2010 02:41
Show Gist options
  • Save atr000/621583 to your computer and use it in GitHub Desktop.
Save atr000/621583 to your computer and use it in GitHub Desktop.
// -*- 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