//
// Tools.m
// TeXDist2
//
// Created by coder on 08/12/06.
// Copyright 2006-2011 Laurens'Tribune. All rights reserved.
//
#import "Common.h"
#import "SystemVersion.h"
#import "Tools.h"
#import <sys/sysctl.h>
#import <sys/stat.h>
#define I386_STRING "i386"
#define X86_64_STRING "x86_64"
#define POWERPC_STRING "ppc"
#define POWERPC64_STRING "ppc64"
@implementation NSURL(Tools)
- (NSString *)Contents_Path4TeXDist2;
{
return [self.path stringByAppendingPathComponent:[Tools Contents_Component]];
}
- (NSString *)Programs_Path4TeXDist2;
{
return [self.path stringByAppendingPathComponent:[Tools Programs_RelativePath]];
}
- (NSString *)Programs_texbin_Path4TeXDist2;
{
return [self.path stringByAppendingPathComponent:[Tools Programs_texbin_RelativePath]];
}
- (NSString *)Programs_texbin_Destination4TeXDist2;
{
return [[NSFileManager defaultManager] destinationOfSymbolicLinkAtPath:self.Programs_texbin_Path4TeXDist2 error:NULL];
}
@end
@interface Tools()
@property (readonly,atomic,weak) NSDictionary * defaults;
@end
@implementation Tools
+ (NSBundle *)bundle;
{
return [NSBundle bundleForClass:[Tools class]];
}
+ (NSString *)Contents_Component;
{
return [[self Programs_RelativePath] stringByDeletingLastPathComponent];
}
+ (NSString *)Programs_RelativePath;
{
return kTeXDist2SetUpProgramsRelativeKey;
}
+ (NSString *)Programs_texbin_RelativePath;
{
return [[self Programs_RelativePath] stringByAppendingPathComponent:kTeXDist2_texbin];
}
+ (NSString *)rootRelativePath;
{
return kTeXDist2SetUpRootRelativeKey;
}
+ (NSString *)LTD_Path;
{
return kTeXDist2SetUpLibraryTeXKey;
}
+ (NSString *)LTD_DefaultTeX_Path;
{
return kTeXDist2SetUpDefaultTeXKey;
}
+ (NSString *)LTD_texdistmgr_Path;
{
return kTeXDist2SetUp_texdistmgr_Key;
}
+ (NSString *)ULB_texdistmgr_Path;
{
return kTeXDist2SetUp_ULB_texdistmgr_Key;
}
+ (NSString *)LTD_DefaultTeX_Contents_Path;
{
return [self LTD_texbin_Path].stringByDeletingLastPathComponent.stringByDeletingLastPathComponent;
}
+ (NSString *)LTD_DefaultTeX_Contents_Destination;
{
return [[NSFileManager defaultManager] destinationOfSymbolicLinkAtPath:[self LTD_DefaultTeX_Contents_Path] error:NULL];
}
+ (NSString *)texdistmgr_DestinationForName:(NSString *)name;
{
return [[[@"/Library/PreferencePanes/" stringByAppendingPathComponent:name]
stringByAppendingPathComponent:@"Contents"]
stringByAppendingPathComponent:@"Executables/texdistmgr"];
}
+ (NSString *)LTD_texbin_Path;
{
return [[self LTD_DefaultTeX_Path] stringByAppendingPathComponent:[Tools Programs_texbin_RelativePath]];
}
+ (NSString *)usr_texbin_Destination;
{
return kTeXDist2SetUp_usr_texbin_destination_Key;
}
+ (NSString *)Programs_texbin_Destination;
{
return kTeXDist2SetUp_Programs_texbin_destination_Key;
}
+ (NSString *)usr_texbin_Path;
{
return kTeXDist2SetUp_usr_texbin_Key;
}
+ (NSString *)Programs_texbin_Path;
{
return kTeXDist2SetUp_Programs_texbin_Key;
}
+ (NSString *)texdistExtension;
{
return kTeXDist2ExtensionKey;
}
+ (NSDictionary *)defaults;
{
return @{
kLSMinimumSystemVersionByArchitecture:@{
@POWERPC_STRING :[SystemVersion systemVersionWithString:@"10.0.0"],
@I386_STRING :[SystemVersion systemVersionWithString:@"10.4.4"],
@X86_64_STRING:[SystemVersion systemVersionWithString:@"10.4.7"],
@POWERPC64_STRING:[SystemVersion systemVersionWithString:@"10.4.7"]
},
kLSMaximumSystemVersionByArchitecture:@{
@POWERPC_STRING :[SystemVersion systemVersionWithString:@"10.6.0"],
@POWERPC64_STRING:[SystemVersion systemVersionWithString:@"10.6.0"]
},
kTeXDist2SetUpArchitectureNamesPriorityByArchKey:@{
@I386_STRING :@[@I386_STRING,@POWERPC_STRING],
@POWERPC_STRING :@[@POWERPC_STRING],
@X86_64_STRING:@[@X86_64_STRING,@I386_STRING,@POWERPC_STRING],
@POWERPC64_STRING:@[@POWERPC64_STRING,@POWERPC_STRING]
},
kTeXDist2SetUpArchitecturePrioritiesByArchKey:@{
@I386_STRING:@[
@I386_STRING"-darwin",
@I386_STRING,
@"x86-darwin",
@"x86",
@"universal-darwin",
@"universal",
@POWERPC_STRING"-darwin",
@POWERPC_STRING,
@"powerpc-darwin",
@"powerpc"
],
@POWERPC_STRING:@[
@POWERPC_STRING"-darwin",
@POWERPC_STRING,
@"powerpc-darwin",
@"powerpc",
@"universal-darwin",
@"universal"
],
@X86_64_STRING:@[
@X86_64_STRING"-darwin",
@X86_64_STRING,
@"universal_64-darwin",
@"universal_64",
@I386_STRING"-darwin",
@I386_STRING,
@"x86-darwin",
@"x86",
@"universal-darwin",
@"universal",
@POWERPC_STRING"-darwin",
@POWERPC_STRING,
@"powerpc-darwin",
@"powerpc"
],
@POWERPC64_STRING:@[
@POWERPC64_STRING"-darwin",
@POWERPC64_STRING,
@"powerpc64-darwin",
@"powerpc64",
@"universal_64-darwin",
@POWERPC_STRING"-darwin",
@POWERPC_STRING,
@"powerpc-darwin",
@"powerpc",
@"universal-darwin",
@"universal"
]
},
kTeXDist2SetUpExpectedProgramsKey:@[@"tex",@"etex",@"pdftex",@"pdfetex",@"xetex",@"luatex"],
@"READMEs":@[
@"For intel machines, universal identifiers must come before intel and ppc",
@"For ppc machines, ppc comes before universal",
@"For intel machines, rosetta is 32 bits only"
]
};
}
+ (NSArray *)expectedPrograms;
{
return self.defaults[kTeXDist2SetUpExpectedProgramsKey];
}
#import <mach/machine.h>
+ (cpu_type_t) CPUType;
{
cpu_type_t cpu_type;
size_t length = sizeof(cpu_type);
int value = 0;
sysctlbyname("hw.cputype", &cpu_type, &length, NULL, 0);
length = sizeof(value);
switch ((unsigned long)cpu_type&~CPU_ARCH_MASK) {
case CPU_TYPE_X86:
if (!sysctlbyname("hw.cpu64bit_capable", &value, &length, NULL, 0)) {
cpu_type |= CPU_ARCH_ABI64;
}
break;
case CPU_TYPE_POWERPC:
if (NOT sysctlbyname("hw.optional.64bitops", &value, &length, NULL, 0)) {
cpu_type |= CPU_ARCH_ABI64;
}
break;
default:
[Logger logWithLevel:kTeXDist2MsgLevelERR
format:@"TeXDist2 ERROR: unknown CPU type %lul",(unsigned long)cpu_type];
break;
}
return cpu_type;
}
+ (NSString *)archForCPU:(cpu_type_t)CPUType;
{
switch (CPUType) {
#define SWITCH_CASE(ID) case CPU_TYPE_##ID:return [[NSString stringWithFormat:@"%s",#ID] lowercaseString]
#if 0
SWITCH_CASE(VAX);
SWITCH_CASE(MC680x0);
SWITCH_CASE(MC98000);
SWITCH_CASE(HPPA);
SWITCH_CASE(MC88000);
SWITCH_CASE(SPARC);
SWITCH_CASE(I860);
#endif
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
SWITCH_CASE(X86_64);
case CPU_TYPE_POWERPC64:return @POWERPC64_STRING;
#endif
SWITCH_CASE(I386);
case CPU_TYPE_POWERPC:return @POWERPC_STRING;
default: return @"default";
}
}
+ (NSString *)arch;
{
return [self archForCPU:self.CPUType];
}
+ (cpu_type_t) CPUForArch:(NSString *)arch;
{
if ([arch isEqual:@POWERPC_STRING]) {
return CPU_TYPE_POWERPC;
}
if ([arch isEqual:@POWERPC64_STRING]) {
return CPU_TYPE_POWERPC64;
}
if ([arch isEqual:@I386_STRING] OR [arch isEqual:@"x86"]) {
return CPU_TYPE_X86;
}
if ([arch isEqual:@X86_64_STRING]) {
return CPU_TYPE_X86_64;
}
return CPU_TYPE_ANY;
}
+ (NSArray *)architectureNamesOfCPU:(cpu_type_t)CPUType;
{
return self.defaults[kTeXDist2SetUpArchitectureNamesPriorityByArchKey][[self archForCPU:CPUType]]?:@[];
}
+ (NSArray *)architectureNames;
{
static NSArray * Ns = nil;
static dispatch_once_t once;
dispatch_once(&once,^{
NSMutableArray * MRA = [NSMutableArray array];
for (NSString * arch in [self architectureNamesOfCPU:self.CPUType]) {
SystemVersion * minSV = self.minimumSystemVersionsByArch[arch]?:[SystemVersion firstSystemVersion];
SystemVersion * maxSV = self.maximumSystemVersionsByArch[arch]?:[SystemVersion lastSystemVersion];
if ( (NSOrderedAscending != [[SystemVersion runningSystemVersion] compare:minSV])
AND (NSOrderedAscending == [[SystemVersion runningSystemVersion] compare:maxSV]) ) {
[MRA addObject:arch];
}
}
Ns = MRA.copy;
assert(Ns.count>0);
});
return Ns;
}
+ (NSArray *)archNames;
{
static NSArray * Ns = nil;
static dispatch_once_t once;
dispatch_once(&once,^{
NSMutableArray * MRA = [NSMutableArray array];
for (NSString * arch in [self architectureNamesOfCPU:self.CPUType]) {
SystemVersion * minSV = self.minimumSystemVersionsByArch[arch]?:[SystemVersion firstSystemVersion];
SystemVersion * maxSV = self.maximumSystemVersionsByArch[arch]?:[SystemVersion lastSystemVersion];
if ( (NSOrderedAscending != [[SystemVersion runningSystemVersion] compare:minSV])
AND (NSOrderedAscending == [[SystemVersion runningSystemVersion] compare:maxSV]) ) {
[MRA addObject:arch];
}
}
Ns = MRA.copy;
assert(Ns.count>0);
});
return Ns;
}
+ (SystemVersion *)minimumSystemVersion;
{
return self.defaults[kLSMinimumSystemVersionByArchitecture][self.arch]?:[SystemVersion firstSystemVersion];
}
+ (SystemVersion *)maximumSystemVersion;
{
return self.defaults[kLSMaximumSystemVersionByArchitecture][self.arch]?:[SystemVersion lastSystemVersion];
}
+ (NSDictionary *)minimumSystemVersionsByArch;
{
return self.defaults[kLSMinimumSystemVersionByArchitecture];
}
+ (NSDictionary *)maximumSystemVersionsByArch;
{
return self.defaults[kLSMaximumSystemVersionByArchitecture];
}
+ (NSDictionary *)architecturePriorityByArch;
{
static NSDictionary * D = nil;
static dispatch_once_t once;
dispatch_once(&once,^{
NSMutableArray * excludedNames = [NSMutableArray array];
[self.defaults[kTeXDist2SetUpArchitecturePrioritiesByArchKey]
enumerateKeysAndObjectsUsingBlock:^(NSString * arch, NSArray * priorities, BOOL *stop) {
#pragma unused(stop)
if (NOT[self.archNames containsObject:arch]) {
[priorities enumerateObjectsUsingBlock:^(NSString * name, NSUInteger idx, BOOL *soustop){
#pragma unused(idx)
#pragma unused(soustop)
if (NOT [name rangeOfString:@"universal" options:NSCaseInsensitiveSearch].length) {
[excludedNames addObject:name];
};
}];
}
}
];
NSMutableDictionary * MD = [NSMutableDictionary dictionary];
[self.defaults[kTeXDist2SetUpArchitecturePrioritiesByArchKey]
enumerateKeysAndObjectsUsingBlock:^(NSString * arch, NSArray * priorities, BOOL *stop) {
#pragma unused(stop)
if ([self.archNames containsObject:arch]) {
NSMutableArray * mra = priorities.mutableCopy;
[mra removeObjectsInArray:excludedNames];
MD[arch]=mra.copy;
}
}
];
D = MD.copy;
});
return D;
}
+ (NSArray *)architecturePriority;
{
return self.defaults[kTeXDist2SetUpArchitecturePrioritiesByArchKey][self.arch]?:@[];
}
#ifndef TeXDist2_HELPER
+ (BOOL)isAlternateKeyDown;
{
return 0 != (kCGEventFlagMaskAlternate & CGEventSourceFlagsState(kCGEventSourceStateCombinedSessionState));
}
#endif
+ (BOOL) is_texdistmgr_OKForName:(NSString *)name;
{
NSFileManager * DFM = [NSFileManager defaultManager];
NSString * expected = [self texdistmgr_DestinationForName:name];
if ([DFM isExecutableFileAtPath:expected]) {
NSString * texdistmgr = [self LTD_texdistmgr_Path];
NSString * destination = [DFM destinationOfSymbolicLinkAtPath:texdistmgr error:NULL];
return [destination isEqual:expected];
}
return NO;
}
+ (BOOL) is_user_texdistmgr_OKForName:(NSString *)name;
{
NSFileManager * DFM = [NSFileManager defaultManager];
NSString * expected = [self texdistmgr_DestinationForName:name];
expected = [NSHomeDirectory() stringByAppendingPathComponent:expected];
if ([DFM isExecutableFileAtPath:expected]) {
NSString * texdistmgr = [self LTD_texdistmgr_Path];
texdistmgr = [NSHomeDirectory() stringByAppendingPathComponent:texdistmgr];
NSString * destination = [DFM destinationOfSymbolicLinkAtPath:texdistmgr error:NULL];
return [destination isEqual:expected];
}
return NO;
}
+ (BOOL) fix_texdistmgr_ForName:(NSString *)name error:(NSError **)RORef;
{
NSString * expected = [self texdistmgr_DestinationForName:name];
NSFileManager * DFM = [NSFileManager defaultManager];
BOOL result = [DFM createSymbolicLinkAtPath:[self LTD_texdistmgr_Path] withDestinationPath:expected error4TeXDist2:RORef];
return [DFM createSymbolicLinkAtPath:[self ULB_texdistmgr_Path] withDestinationPath:expected error4TeXDist2:RORef] AND result;
}
+ (BOOL) fix_user_texdistmgr_ForName:(NSString *)name error:(NSError **)RORef;
{
NSString * texdistmgr = [self LTD_texdistmgr_Path];
texdistmgr = [NSHomeDirectory() stringByAppendingPathComponent:texdistmgr];
NSString * expected = [self texdistmgr_DestinationForName:name];
expected = [NSHomeDirectory() stringByAppendingPathComponent:expected];
NSFileManager * DFM = [NSFileManager defaultManager];
return [DFM createSymbolicLinkAtPath:texdistmgr withDestinationPath:expected error4TeXDist2:RORef];
}
+ (BOOL) isResetOK;
{
NSFileManager * DFM = [NSFileManager defaultManager];
NSString * P = [Tools LTD_DefaultTeX_Path];
BOOL existsP = [DFM fileExistsAtPath:P followSymLinks4TeXDist2:NO];
NSString * Q = [Tools usr_texbin_Path];
BOOL existsQ = [DFM fileExistsAtPath:Q followSymLinks4TeXDist2:NO];
NSString * R = [Tools Programs_texbin_Path];
BOOL existsR = [DFM fileExistsAtPath:R followSymLinks4TeXDist2:NO];
return NOT existsP AND NOT existsQ AND NOT existsR;
}
+ (BOOL) resetOrReturnError:(NSError **)RORef;
{
NSFileManager * DFM = [NSFileManager defaultManager];
NSString * P = [Tools LTD_DefaultTeX_Path];
BOOL existsP = [DFM fileExistsAtPath:P followSymLinks4TeXDist2:NO];
NSString * Q = [Tools usr_texbin_Path];
BOOL existsQ = [DFM fileExistsAtPath:Q followSymLinks4TeXDist2:NO];
NSString * R = [Tools Programs_texbin_Path];
BOOL existsR = [DFM fileExistsAtPath:R followSymLinks4TeXDist2:NO];
NSError * ROR = nil;
if ((NOT existsP OR [DFM removeItemAtPath:P error:&ROR])
AND (NOT existsQ OR [DFM removeItemAtPath:Q error:&ROR])
AND (NOT existsR OR [DFM removeItemAtPath:R error:&ROR])) {
return YES;
}
TeXDist2ForwardLocalError(ROR,RORef,errTeXDist2ResetFailed);
return NO;
}
@end
#define kTeXDist2_isExecutableFileAtPath(THE_PATH)\
(([[[NSFileManager defaultManager] attributesOfItemAtPath:[THE_PATH stringByResolvingSymlinksInPath] error:NULL] filePosixPermissions]&(S_IXUSR|S_IXGRP|S_IXOTH))\
==(S_IXUSR|S_IXGRP|S_IXOTH))