Changeset 308


Ignore:
Timestamp:
10/30/06 10:36:56 (13 years ago)
Author:
Nicholas Riley
Message:

main.c: Display architecture with -f.

launch.xcodeproj: Build in C99 mode.

README: Updated a few examples (the Resorcerer one still needs
fixing).

Location:
trunk/launch/launch
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/launch/launch/README

    r304 r308  
    6161-----------
    6262
    63 An Xcode project, 'launch.xcodeproj', is included.  A precompiled Universal
    64 binary is also provided.  'launch' was developed and tested under Mac OS X
    65 10.4.7 with Xcode 2.3, and does not require any additional software to
    66 build.
     63An Xcode project, 'launch.xcodeproj', is included.  A precompiled
     64Universal binary is also provided.  'launch' was developed and tested
     65under Mac OS X 10.4.8 with Xcode 2.4, and does not require any
     66additional software to build.
    6767
    6868USAGE
     
    8989
    9090% launch -f /Applications/Preview.app
    91 /Applications/Preview.app: Mac OS X application package 
     91/Applications/Preview.app: Mac OS X application package
    9292        type: 'APPL'    creator: 'prvw'
     93        architecture: Intel 80x86, PowerPC
    9394        bundle ID: com.apple.Preview
    94         version: 2.1.0
     95        version: 3.0.8
    9596        kind: Application
     97        content type ID: com.apple.application-bundle
    9698        contents: 1 item
    9799[...]
     
    120122
    121123% launch -f /Applications/Internet/OmniWeb.app
    122 /Applications/Internet/OmniWeb.app: Mac OS X application package
     124/Applications/Internet/OmniWeb.app: scriptable Mac OS X application package
    123125        type: 'APPL'    creator: 'OWEB'
    124         bundle ID: com.omnigroup.OmniWeb
    125         version: 4.5
    126         kind: Application
     126        architecture: PowerPC, Intel 80x86
     127        bundle ID: com.omnigroup.OmniWeb5
    127128
    128129Note that bundle IDs are not case-sensitive: com.barebones.BBEdit is
     
    227228 - -o: pass command-line arguments (broken, r. 4474993)
    228229 - display content type ID (UTI)   
     230 - display architecture of Mach-O files
    229231 - switched to new LSOpen APIs (now requires Mac OS X 10.4 or later)
    230232 - switched to new date formatting APIs (the old ones are deprecated)
  • trunk/launch/launch/launch.xcodeproj/project.pbxproj

    r305 r308  
    134134                                        i386,
    135135                                );
     136                                GCC_C_LANGUAGE_STANDARD = c99;
    136137                                MACOSX_DEPLOYMENT_TARGET = 10.4;
    137138                                PREBINDING = NO;
     
    147148                                        i386,
    148149                                );
     150                                GCC_C_LANGUAGE_STANDARD = c99;
    149151                                MACOSX_DEPLOYMENT_TARGET = 10.4;
    150152                                PREBINDING = NO;
  • trunk/launch/launch/main.c

    r305 r308  
    2121#include <unistd.h>
    2222#include <sys/stat.h>
     23#include <mach-o/fat.h>
     24#include <mach-o/arch.h>
     25#include <mach-o/loader.h>
    2326#include <Carbon/Carbon.h>
    2427#include <CoreServices/CoreServices.h>
     
    648651    CFRelease(typeStr);
    649652    return buffer;
     653}
     654
     655// based on Apple's "CheckExecutableArchitecture" sample code
     656
     657#define MAX_HEADER_BYTES 512
     658
     659void swapHeader(uint8_t *bytes, ssize_t length) {
     660    for (ssize_t i = 0 ; i < length ; i += 4)
     661        *(uint32_t *)(bytes + i) = OSSwapInt32(*(uint32_t *)(bytes + i));
     662}
     663
     664void printExecutableArchitectures(CFURLRef url, bool printOnFailure) {
     665    uint8_t path[PATH_MAX];
     666    if (printOnFailure)
     667        printf("\tarchitecture: ");
     668       
     669    if (!CFURLGetFileSystemRepresentation(url, true, path, PATH_MAX)) {
     670        if (printOnFailure) printf("(can't get executable)\n");
     671        return;
     672    }
     673   
     674    int fd = open((const char *)path, O_RDONLY, 0777);
     675    if (fd <= 0) {
     676        if (printOnFailure) printf("(can't read)\n");
     677        return;
     678    }
     679   
     680    uint8_t bytes[MAX_HEADER_BYTES];
     681    ssize_t length = read(fd, bytes, MAX_HEADER_BYTES);
     682    close(fd);
     683
     684    if (length < sizeof(struct mach_header_64)) {
     685        if (printOnFailure) printf("(can't read Mach-O header)\n");
     686        return;
     687    }
     688
     689    // Look for any of the six magic numbers relevant to Mach-O executables, and swap the header if necessary.
     690    uint32_t num_fat = 0, magic = *((uint32_t *)bytes);
     691    uint32_t max_fat = (length - sizeof(struct fat_header)) / sizeof(struct fat_arch);
     692    struct fat_arch one_fat = {0}, *fat;
     693    if (MH_MAGIC == magic || MH_CIGAM == magic) {
     694        struct mach_header *mh = (struct mach_header *)bytes;
     695        if (MH_CIGAM == magic) swapHeader(bytes, length);
     696        one_fat.cputype = mh->cputype;
     697        one_fat.cpusubtype = mh->cpusubtype;
     698        fat = &one_fat;
     699        num_fat = 1;
     700    } else if (MH_MAGIC_64 == magic || MH_CIGAM_64 == magic) {
     701        struct mach_header_64 *mh = (struct mach_header_64 *)bytes;
     702        if (MH_CIGAM_64 == magic) swapHeader(bytes, length);
     703        one_fat.cputype = mh->cputype;
     704        one_fat.cpusubtype = mh->cpusubtype;
     705        fat = &one_fat;
     706        num_fat = 1;
     707    } else if (FAT_MAGIC == magic || FAT_CIGAM == magic) {
     708        fat = (struct fat_arch *)(bytes + sizeof(struct fat_header));
     709        if (FAT_CIGAM == magic) swapHeader(bytes, length);
     710        num_fat = ((struct fat_header *)bytes)->nfat_arch;
     711        if (num_fat > max_fat) num_fat = max_fat;
     712    }
     713   
     714    if (num_fat == 0) {
     715        if (printOnFailure) printf("(none found)\n");
     716        return;
     717    }
     718   
     719    if (!printOnFailure)
     720        printf("\tarchitecture: ");
     721       
     722    for (int i = 0 ; i < num_fat ; i++) {
     723        if (i != 0) printf(", ");
     724        const NXArchInfo *arch = NXGetArchInfoFromCpuType(fat[i].cputype, fat[i].cpusubtype);
     725        if (arch == NULL) {
     726            printf("unknown (cputype %d, subtype %d)", fat[i].cputype, fat[i].cpusubtype);
     727            continue;
     728        }
     729        printf(arch->description);
     730    }
     731    printf("\n");
    650732}
    651733
     
    761843                    intVersion = CFBundleGetVersionNumber(bundle);
    762844                }
     845                CFURLRef executable = CFBundleCopyExecutableURL(bundle);
     846                if (executable != NULL) {
     847                    printExecutableArchitectures(executable, true);
     848                    CFRelease(executable);
     849                }
    763850                CFRelease(bundle);
    764851            }
     
    767854                CFRelease(bundleID);
    768855            }
    769         } else if (haveFSRef) {
    770             // try to get a version if we can, but don't complain if we can't
    771             SInt16 resFork = FSOpenResFile(&fsr, fsRdPerm);
    772             if (ResError() == noErr) {
    773                 VersRecHndl vers = (VersRecHndl)Get1Resource('vers', 1);
    774                 if (ResError() == noErr && vers != NULL) {
    775                     version = CFStringCreateWithPascalString(NULL, vers[0]->shortVersion, CFStringGetSystemEncoding()); // XXX use country code instead?
    776                     intVersion = ((NumVersionVariant)vers[0]->numericVersion).whole;
     856        } else {
     857            printExecutableArchitectures(url, false);
     858            if (haveFSRef) {
     859                // try to get a version if we can, but don't complain if we can't
     860                SInt16 resFork = FSOpenResFile(&fsr, fsRdPerm);
     861                if (ResError() == noErr) {
     862                    VersRecHndl vers = (VersRecHndl)Get1Resource('vers', 1);
     863                    if (ResError() == noErr && vers != NULL) {
     864                        version = CFStringCreateWithPascalString(NULL, vers[0]->shortVersion, CFStringGetSystemEncoding()); // XXX use country code instead?
     865                        intVersion = ((NumVersionVariant)vers[0]->numericVersion).whole;
     866                    }
    777867                }
     868                CloseResFile(resFork);
    778869            }
    779             CloseResFile(resFork);
    780870        }
    781        
     871
    782872        if (version != NULL) {
    783873            printf("\tversion: %s", utf8StringFromCFStringRef(version));
Note: See TracChangeset for help on using the changeset viewer.