|
@@ -13,28 +13,12 @@
|
|
|
#include <stdlib.h>
|
|
|
#include <unistd.h>
|
|
|
#include <getopt.h>
|
|
|
-#import <objc/runtime.h>
|
|
|
-#import <sys/utsname.h>
|
|
|
-
|
|
|
|
|
|
+#import <sys/utsname.h>
|
|
|
|
|
|
-typedef NS_ENUM(NSInteger, BSPackageFileType)
|
|
|
-{
|
|
|
-
|
|
|
- BSPackageFileTypeFile,
|
|
|
- BSPackageFileTypeDirectory,
|
|
|
- BSPackageFileTypeBlock,
|
|
|
- BSPackageFileTypeCharacter,
|
|
|
- BSPackageFileTypeLink,
|
|
|
- BSPackageFileTypePipe,
|
|
|
- BSPackageFileTypeSocket,
|
|
|
- BSPackageFileTypeUnknown
|
|
|
-
|
|
|
-};
|
|
|
+#import "HelperClass.h"
|
|
|
|
|
|
|
|
|
-#define DLog(format, ...) CFShow((__bridge CFStringRef)[NSString stringWithFormat:format, ## __VA_ARGS__]);
|
|
|
-#define FM [NSFileManager defaultManager]
|
|
|
/*
|
|
|
|
|
|
fileType, @"fileType",octalPermissions, @"octalPermissions", octalUG, @"octalUG", size, @"size", date, @"date", time, @"time", linkDest, @"linkDest", fullPath, @"fullPath", nil];
|
|
@@ -42,858 +26,6 @@ typedef NS_ENUM(NSInteger, BSPackageFileType)
|
|
|
*/
|
|
|
|
|
|
|
|
|
-@interface NSObject (Additions)
|
|
|
-
|
|
|
--(NSArray *)ivars;
|
|
|
--(NSArray *)properties;
|
|
|
-
|
|
|
-@end
|
|
|
-
|
|
|
-@implementation NSObject (Additions)
|
|
|
-
|
|
|
-- (NSArray *)properties
|
|
|
-{
|
|
|
- u_int count;
|
|
|
- objc_property_t* properties = class_copyPropertyList(self.class, &count);
|
|
|
- NSMutableArray* propArray = [NSMutableArray arrayWithCapacity:count];
|
|
|
- for (int i = 0; i < count ; i++)
|
|
|
- {
|
|
|
- const char* propertyName = property_getName(properties[i]);
|
|
|
- NSString *propName = [NSString stringWithCString:propertyName encoding:NSUTF8StringEncoding];
|
|
|
- [propArray addObject:propName];
|
|
|
- }
|
|
|
- free(properties);
|
|
|
- return propArray;
|
|
|
-}
|
|
|
-
|
|
|
--(NSArray *)ivars
|
|
|
-{
|
|
|
- Class clazz = [self class];
|
|
|
- u_int count;
|
|
|
- Ivar* ivars = class_copyIvarList(clazz, &count);
|
|
|
- NSMutableArray* ivarArray = [NSMutableArray arrayWithCapacity:count];
|
|
|
- for (int i = 0; i < count ; i++)
|
|
|
- {
|
|
|
- const char* ivarName = ivar_getName(ivars[i]);
|
|
|
- [ivarArray addObject:[NSString stringWithCString:ivarName encoding:NSUTF8StringEncoding]];
|
|
|
- }
|
|
|
- free(ivars);
|
|
|
- return ivarArray;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-@end
|
|
|
-
|
|
|
-
|
|
|
-@interface DebPackageModel : NSObject
|
|
|
-
|
|
|
-@property (nonatomic, copy) NSString *name;
|
|
|
-@property (nonatomic, copy) NSString *package;
|
|
|
-@property (nonatomic, copy) NSString *source;
|
|
|
-@property (nonatomic, copy) NSString *version;
|
|
|
-@property (nonatomic, copy) NSString *priority;
|
|
|
-@property (nonatomic, copy) NSString *essential;
|
|
|
-@property (nonatomic, copy) NSArray *depends;
|
|
|
-@property (nonatomic, copy) NSString *maintainer;
|
|
|
-@property (nonatomic, copy) NSString *packageDescription; //cant be description, that is reservered
|
|
|
-@property (nonatomic, copy) NSString *homepage;
|
|
|
-@property (nonatomic, copy) NSString *author;
|
|
|
-@property (nonatomic, copy) NSString *icon;
|
|
|
-@property (nonatomic, copy) NSString *depiction;
|
|
|
-@property (nonatomic, copy) NSString *preDepends;
|
|
|
-@property (nonatomic, copy) NSString *breaks;
|
|
|
-@property (nonatomic, copy) NSString *status;
|
|
|
-@property (nonatomic, copy) NSString *tag;
|
|
|
-@property (nonatomic, copy) NSString *architecture;
|
|
|
-@property (nonatomic, copy) NSString *section;
|
|
|
-@property (nonatomic, copy) NSString *rawString;
|
|
|
-
|
|
|
-
|
|
|
-- (instancetype)initWithRawControlString:(NSString *)controlString;
|
|
|
-
|
|
|
-
|
|
|
-@end
|
|
|
-@implementation DebPackageModel
|
|
|
-
|
|
|
-- (NSString *)description {
|
|
|
-
|
|
|
- NSString *orig = [super description];
|
|
|
- return [NSString stringWithFormat:@"%@ = %@ (%@)", orig, self.package, self.version];
|
|
|
-}
|
|
|
-
|
|
|
-- (NSString*) fullDescription {
|
|
|
-
|
|
|
- NSString *orig = [super description];
|
|
|
- NSMutableDictionary *details = [NSMutableDictionary new];
|
|
|
- NSArray *props = [self properties];
|
|
|
- [props enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
|
|
|
-
|
|
|
- NSString *cv = [self valueForKey:obj];
|
|
|
- if (cv){
|
|
|
- details[obj] = cv;
|
|
|
- }
|
|
|
-
|
|
|
- }];
|
|
|
- return [NSString stringWithFormat:@"%@ = %@", orig, details];
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-+ (NSDictionary *)dependencyDictionaryFromString:(NSString *)depend
|
|
|
-{
|
|
|
- NSMutableCharacterSet *whitespaceAndPunctuationSet = [NSMutableCharacterSet characterSetWithCharactersInString:@"()"];
|
|
|
- [whitespaceAndPunctuationSet formUnionWithCharacterSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
|
|
-
|
|
|
- NSScanner *stringScanner = [[NSScanner alloc] initWithString:depend];
|
|
|
- stringScanner.charactersToBeSkipped = whitespaceAndPunctuationSet;
|
|
|
-
|
|
|
- NSString *name = nil;
|
|
|
- NSInteger i = 0;
|
|
|
- NSMutableDictionary *predicate = [NSMutableDictionary new];
|
|
|
- while ([stringScanner scanUpToCharactersFromSet:whitespaceAndPunctuationSet intoString:&name]) {
|
|
|
- // NSLog(@"%@ pass %li", name, (long)i);
|
|
|
- switch (i) {
|
|
|
- case 0 :
|
|
|
- predicate[@"package"] = name;
|
|
|
- break;
|
|
|
- case 1:
|
|
|
- predicate[@"predicate"] = name;
|
|
|
- break;
|
|
|
- case 2:
|
|
|
- predicate[@"requirement"] = name;
|
|
|
- break;
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
- i++;
|
|
|
- }
|
|
|
- return predicate;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-+ (NSArray *)dependencyArrayFromString:(NSString *)depends
|
|
|
-{
|
|
|
- NSMutableArray *cleanArray = [[NSMutableArray alloc] init];
|
|
|
- NSArray *dependsArray = [depends componentsSeparatedByString:@","];
|
|
|
- for (id depend in dependsArray)
|
|
|
- {
|
|
|
- NSArray *spaceDelimitedArray = [depend componentsSeparatedByString:@" "];
|
|
|
- NSString *isolatedDependency = [[spaceDelimitedArray objectAtIndex:0] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
|
|
- if ([isolatedDependency length] == 0)
|
|
|
- isolatedDependency = [[spaceDelimitedArray objectAtIndex:1] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
|
|
-
|
|
|
- NSDictionary *dependDict = [self dependencyDictionaryFromString:depend];
|
|
|
- //DLog(@"depend dict: %@", dependDict);
|
|
|
- [cleanArray addObject:dependDict];
|
|
|
- }
|
|
|
-
|
|
|
- return cleanArray;
|
|
|
-}
|
|
|
-
|
|
|
-+ (NSDictionary *)JSONKeyPathsByPropertyKey {
|
|
|
- return @{
|
|
|
- @"name": @"Name",
|
|
|
- @"package": @"Package",
|
|
|
- @"source": @"Source",
|
|
|
- @"version": @"Version",
|
|
|
- @"priority": @"Priority",
|
|
|
- @"essential": @"Essential",
|
|
|
- @"depends": @"Depends",
|
|
|
- @"maintainer": @"Maintainer",
|
|
|
- @"packageDescription": @"Description",
|
|
|
- @"homepage": @"Homepage",
|
|
|
- @"icon": @"Icon",
|
|
|
- @"author": @"Author",
|
|
|
- @"preDepends": @"Pre-Depends",
|
|
|
- @"breaks": @"Breaks",
|
|
|
- @"depiction": @"Depiction",
|
|
|
- @"tag": @"Tag",
|
|
|
- @"architecture": @"Architecture",
|
|
|
- @"section": @"Section",
|
|
|
- @"osMax": @"osMax",
|
|
|
- @"osMin": @"osMin",
|
|
|
- @"banner": @"Banner",
|
|
|
- @"topShelfImage": @"TopShelfImage"
|
|
|
- };
|
|
|
-}
|
|
|
-
|
|
|
-- (instancetype)initWithRawControlString:(NSString *)controlString
|
|
|
-{
|
|
|
- NSArray *packageArray = [controlString componentsSeparatedByString:@"\n"];
|
|
|
- NSMutableDictionary *currentPackage = [[NSMutableDictionary alloc] init];
|
|
|
- for (id currentLine in packageArray)
|
|
|
- {
|
|
|
- NSArray *itemArray = [currentLine componentsSeparatedByString:@": "];
|
|
|
- if ([itemArray count] >= 2)
|
|
|
- {
|
|
|
- NSString *key = [itemArray objectAtIndex:0];
|
|
|
- NSString *object = [itemArray objectAtIndex:1];
|
|
|
-
|
|
|
- if ([key isEqualToString:@"Depends"]) //process the array
|
|
|
- {
|
|
|
- NSArray *dependsObject = [DebPackageModel dependencyArrayFromString:object];
|
|
|
-
|
|
|
- [currentPackage setObject:dependsObject forKey:key];
|
|
|
-
|
|
|
- } else { //every other key, even if it has an array is treated as a string
|
|
|
-
|
|
|
- [currentPackage setObject:object forKey:key];
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if ([[currentPackage allKeys] count] > 4)
|
|
|
- {
|
|
|
- self = [super init];
|
|
|
- self.rawString = controlString;
|
|
|
- [self mapDictionaryToProperties:currentPackage];
|
|
|
- return self;
|
|
|
- }
|
|
|
- return nil;
|
|
|
-
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-- (void)mapDictionaryToProperties:(NSDictionary *)theProps {
|
|
|
-
|
|
|
- NSArray *ourProps = [self properties];
|
|
|
- NSArray *allKeys = [theProps allKeys];
|
|
|
- NSDictionary *mappedKeys = [DebPackageModel JSONKeyPathsByPropertyKey];
|
|
|
- [ourProps enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
|
|
|
-
|
|
|
- NSString *mappedProp = mappedKeys[obj];
|
|
|
-
|
|
|
- //DLog(@"allkeys: %@", allKeys);
|
|
|
-
|
|
|
- if ([allKeys containsObject:mappedProp]){
|
|
|
- if ([self respondsToSelector:NSSelectorFromString(obj)]){ //redudant
|
|
|
-
|
|
|
- id value = theProps[mappedProp];
|
|
|
- //DLog(@"setting value: %@ for key: %@ from mapped key: %@", value, obj, mappedProp);
|
|
|
- [self setValue:value forKey:obj];
|
|
|
-
|
|
|
- }
|
|
|
- } else {
|
|
|
-
|
|
|
- //DLog(@"%@ doesnt respond to %@", self, mappedProp);
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- }];
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-@end
|
|
|
-
|
|
|
-@interface NSString (Additions)
|
|
|
-
|
|
|
-- (void)writeToFileWithoutAttributes:(NSString *)theFile;
|
|
|
-
|
|
|
-
|
|
|
-@end
|
|
|
-
|
|
|
-@implementation NSString (Additions)
|
|
|
-
|
|
|
-- (void)writeToFileWithoutAttributes:(NSString *)theFile {
|
|
|
-
|
|
|
- if ([FM fileExistsAtPath:theFile]){
|
|
|
-
|
|
|
- DLog(@"overwriting file: %@", theFile);
|
|
|
- }
|
|
|
- FILE *fd = fopen([theFile UTF8String], "w+");
|
|
|
- const char *text = self.UTF8String;
|
|
|
- fwrite(text, strlen(text) + 1, 1, fd);
|
|
|
- fclose(fd);
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-@end
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-@interface PackageFile: NSObject
|
|
|
-
|
|
|
-@property (nonatomic, strong) NSString *fileType;
|
|
|
-@property (nonatomic, strong) NSString *permissions;
|
|
|
-@property (nonatomic, strong) NSString *owner;
|
|
|
-@property (nonatomic, strong) NSString *size;
|
|
|
-@property (nonatomic, strong) NSString *date;
|
|
|
-@property (nonatomic, strong) NSString *time;
|
|
|
-@property (nonatomic, strong) NSString *linkDestination;
|
|
|
-@property (nonatomic, strong) NSString *path;
|
|
|
-@property (nonatomic, strong) NSString *basename;
|
|
|
-@property (readwrite, assign) BSPackageFileType type;
|
|
|
-
|
|
|
-- (void)_setFileTypeFromRaw:(NSString *)rawType;
|
|
|
-
|
|
|
-@end
|
|
|
-
|
|
|
-@implementation PackageFile
|
|
|
-
|
|
|
-- (void)_setFileTypeFromRaw:(NSString *)rawType {
|
|
|
-
|
|
|
- _fileType = [PackageFile readableFileTypeForRawMode:rawType];
|
|
|
- _type = [PackageFile fileTypeForRawMode:rawType];
|
|
|
-
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- - denotes a regular file
|
|
|
- d denotes a directory
|
|
|
- b denotes a block special file
|
|
|
- c denotes a character special file
|
|
|
- l denotes a symbolic link
|
|
|
- p denotes a named pipe
|
|
|
- s denotes a domain socket
|
|
|
- */
|
|
|
-
|
|
|
-+ (NSString* )readableFileTypeForRawMode:(NSString *)fileTypeChar {
|
|
|
-
|
|
|
- NSString *fileType = nil;
|
|
|
-
|
|
|
- if ([fileTypeChar isEqualToString:@"-"])
|
|
|
- { fileType = @"file"; }
|
|
|
- else if ([fileTypeChar isEqualToString:@"d"])
|
|
|
- { fileType = @"directory"; }
|
|
|
- else if ([fileTypeChar isEqualToString:@"b"])
|
|
|
- { fileType = @"block"; }
|
|
|
- else if ([fileTypeChar isEqualToString:@"c"])
|
|
|
- { fileType = @"character"; }
|
|
|
- else if ([fileTypeChar isEqualToString:@"l"])
|
|
|
- { fileType = @"link"; }
|
|
|
- else if ([fileTypeChar isEqualToString:@"p"])
|
|
|
- { fileType = @"pipe"; }
|
|
|
- else if ([fileTypeChar isEqualToString:@"s"])
|
|
|
- { fileType = @"socket"; }
|
|
|
-
|
|
|
- return fileType;
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-+ (BSPackageFileType)fileTypeForRawMode:(NSString *)fileTypeChar {
|
|
|
-
|
|
|
- BSPackageFileType type = BSPackageFileTypeUnknown;
|
|
|
-
|
|
|
- if ([fileTypeChar isEqualToString:@"-"])
|
|
|
- { type = BSPackageFileTypeFile; }
|
|
|
- else if ([fileTypeChar isEqualToString:@"d"])
|
|
|
- { type = BSPackageFileTypeDirectory; }
|
|
|
- else if ([fileTypeChar isEqualToString:@"b"])
|
|
|
- { type = BSPackageFileTypeBlock; }
|
|
|
- else if ([fileTypeChar isEqualToString:@"c"])
|
|
|
- { type = BSPackageFileTypeCharacter; }
|
|
|
- else if ([fileTypeChar isEqualToString:@"l"])
|
|
|
- { type = BSPackageFileTypeLink; }
|
|
|
- else if ([fileTypeChar isEqualToString:@"p"])
|
|
|
- { type = BSPackageFileTypePipe; }
|
|
|
- else if ([fileTypeChar isEqualToString:@"s"])
|
|
|
- { type = BSPackageFileTypeSocket; }
|
|
|
-
|
|
|
- return type;
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-- (NSString*) description {
|
|
|
-
|
|
|
- NSString *orig = [super description];
|
|
|
- NSMutableDictionary *details = [NSMutableDictionary new];
|
|
|
- NSArray *props = [self properties];
|
|
|
- [props enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
|
|
|
-
|
|
|
- NSString *cv = [self valueForKey:obj];
|
|
|
- if (cv){
|
|
|
- details[obj] = cv;
|
|
|
- }
|
|
|
-
|
|
|
- }];
|
|
|
- return [NSString stringWithFormat:@"%@ = %@", orig, details];
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-@end
|
|
|
-
|
|
|
-@interface ErrorReturn: NSObject
|
|
|
-
|
|
|
-@property (nonatomic, strong) NSArray *overwriteFiles;
|
|
|
-@property (readwrite, assign) NSInteger returnStatus;
|
|
|
-
|
|
|
-
|
|
|
-@end
|
|
|
-
|
|
|
-@implementation ErrorReturn
|
|
|
-
|
|
|
-@end
|
|
|
-
|
|
|
-@interface Package: NSObject
|
|
|
-
|
|
|
-@property (nonatomic, strong) NSArray <PackageFile *> *files;
|
|
|
-@property (nonatomic, strong) NSArray *controlFiles;
|
|
|
-@property (nonatomic, strong) NSString *packageName;
|
|
|
-@property (nonatomic, strong) NSString *version;
|
|
|
-
|
|
|
-- (ErrorReturn *)errorReturnForBootstrap:(NSString *)bootstrapPath;
|
|
|
-- (NSString *)listfile;
|
|
|
-@end
|
|
|
-
|
|
|
-
|
|
|
-@implementation Package
|
|
|
-
|
|
|
-- (NSString*) description {
|
|
|
-
|
|
|
- NSString *orig = [super description];
|
|
|
- NSMutableDictionary *details = [NSMutableDictionary new];
|
|
|
- NSArray *props = [self properties];
|
|
|
- [props enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
|
|
|
-
|
|
|
- NSString *cv = [self valueForKey:obj];
|
|
|
- if (cv){
|
|
|
- details[obj] = cv;
|
|
|
- }
|
|
|
-
|
|
|
- }];
|
|
|
- return [NSString stringWithFormat:@"%@ = %@", orig, details];
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-- (NSString *)listfile {
|
|
|
-
|
|
|
- __block NSMutableArray *outFiles = [NSMutableArray new];
|
|
|
- [self.files enumerateObjectsUsingBlock:^(PackageFile * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
|
|
|
-
|
|
|
- if ([obj.fileType isEqualToString:@"link"]){ //does this need to handle things differently?
|
|
|
- [outFiles addObject:obj.path];
|
|
|
- } else {
|
|
|
- [outFiles addObject:obj.path];
|
|
|
- }
|
|
|
- }];
|
|
|
- return [outFiles componentsJoinedByString:@"\n"];
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-- (ErrorReturn *)errorReturnForBootstrap:(NSString *)bootstrapPath
|
|
|
-{
|
|
|
- NSArray *ignoreFiles = @[@".fauxsu", @".DS_Store"];
|
|
|
- NSArray *forbiddenRoots = @[@"etc", @"var", @"tmp"];
|
|
|
- NSFileManager *man = [NSFileManager defaultManager];
|
|
|
- __block NSInteger returnValue = 0; //0 = good to go 1 = over write warning, 2 = no go
|
|
|
- __block NSMutableArray *_overwriteArray = [NSMutableArray new];
|
|
|
- [self.files enumerateObjectsUsingBlock:^(PackageFile * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
|
|
|
-
|
|
|
- if ([obj.fileType isEqualToString:@"file"]){
|
|
|
-
|
|
|
- NSString *fullPath = [bootstrapPath stringByAppendingPathComponent:obj.path];
|
|
|
- if ([man fileExistsAtPath:fullPath] && ![ignoreFiles containsObject:obj.basename]){
|
|
|
-
|
|
|
- //DLog(@"[WARNING] overwriting a file that already exists and isn't DS_Store or .fauxsu: %@", fullPath);
|
|
|
- [_overwriteArray addObject:obj.path];
|
|
|
- //*stop = TRUE;//return FALSE;
|
|
|
- returnValue = 1;
|
|
|
- }
|
|
|
-
|
|
|
- NSArray *pathComponents = [obj.path pathComponents];
|
|
|
- if ([pathComponents count] > 1)
|
|
|
- {
|
|
|
- NSString *rootPath = [pathComponents objectAtIndex:1];
|
|
|
- if ([forbiddenRoots containsObject:rootPath])
|
|
|
- {
|
|
|
- DLog(@"\n [ERROR] package file: '%@' would overwrite symbolic link at '%@'! Exiting!\n\n", obj.path, rootPath);
|
|
|
- *stop = TRUE;
|
|
|
- returnValue = 2;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- }];
|
|
|
-
|
|
|
- ErrorReturn *er = [ErrorReturn new];
|
|
|
- er.returnStatus = returnValue;
|
|
|
- er.overwriteFiles = _overwriteArray;
|
|
|
-
|
|
|
- return er;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-@end
|
|
|
-
|
|
|
-@interface HelperClass: NSObject
|
|
|
-
|
|
|
-+ (BOOL)shouldContinueWithError:(NSString *)errorMessage;
|
|
|
-+ (NSArray *)returnForProcess:(NSString *)call;
|
|
|
-+ (Package *)packageForDeb:(NSString *)debFile;
|
|
|
-+ (NSString *)octalFromSymbols:(NSString *)theSymbols;
|
|
|
-
|
|
|
-@end
|
|
|
-
|
|
|
-@implementation HelperClass
|
|
|
-
|
|
|
-+ (NSArray <DebPackageModel*>*)statusInstalledPackagesFromFile:(NSString *)statusFile
|
|
|
-{
|
|
|
-
|
|
|
- if (![FM fileExistsAtPath:statusFile]) {
|
|
|
- return nil;
|
|
|
- }
|
|
|
- NSString *packageString = [NSString stringWithContentsOfFile:statusFile encoding:NSUTF8StringEncoding error:nil];
|
|
|
- NSArray *lineArray = [packageString componentsSeparatedByString:@"\n\n"];
|
|
|
- //DDLogInfo(@"lineArray: %@", lineArray);
|
|
|
- NSMutableArray *mutableList = [[NSMutableArray alloc] init];
|
|
|
- //NSMutableDictionary *mutableDict = [[NSMutableDictionary alloc] init];
|
|
|
- for (id currentItem in lineArray)
|
|
|
- {
|
|
|
-
|
|
|
- DebPackageModel *debModel = [[DebPackageModel alloc] initWithRawControlString:currentItem];
|
|
|
- if (debModel != nil)
|
|
|
- [mutableList addObject:debModel];
|
|
|
- }
|
|
|
-
|
|
|
- NSSortDescriptor *nameDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES
|
|
|
- selector:@selector(localizedCaseInsensitiveCompare:)];
|
|
|
- NSSortDescriptor *packageDescriptor = [[NSSortDescriptor alloc] initWithKey:@"package" ascending:YES
|
|
|
- selector:@selector(localizedCaseInsensitiveCompare:)];
|
|
|
- NSArray *descriptors = [NSArray arrayWithObjects:nameDescriptor, packageDescriptor, nil];
|
|
|
- NSArray *sortedArray = [mutableList sortedArrayUsingDescriptors:descriptors];
|
|
|
-
|
|
|
-
|
|
|
- mutableList = nil;
|
|
|
-
|
|
|
- return sortedArray;
|
|
|
-}
|
|
|
-
|
|
|
-+ (BOOL)shouldContinueWithError:(NSString *)errorMessage {
|
|
|
-
|
|
|
- NSString *errorString = [NSString stringWithFormat:@"\n%@ Are you sure you want to continue? [y/n]?", errorMessage];
|
|
|
-
|
|
|
- char c;
|
|
|
- printf("%s", [errorString UTF8String] );
|
|
|
- c=getchar();
|
|
|
- while(c!='y' && c!='n')
|
|
|
- {
|
|
|
- if (c!='\n'){
|
|
|
- printf("[y/n]");
|
|
|
- }
|
|
|
- c=getchar();
|
|
|
- }
|
|
|
-
|
|
|
- if (c == 'n')
|
|
|
- {
|
|
|
- DLog(@"\n smart move... exiting\n\n");
|
|
|
- return FALSE;
|
|
|
- } else if (c == 'y') {
|
|
|
- DLog(@"\n its your funeral....\n\n");
|
|
|
- }
|
|
|
-
|
|
|
- return TRUE;
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-+ (NSArray *)returnForProcess:(NSString *)call
|
|
|
-{
|
|
|
- if (call==nil)
|
|
|
- return 0;
|
|
|
- char line[200];
|
|
|
- //DDLogInfo(@"running process: %@", call);
|
|
|
- FILE* fp = popen([call UTF8String], "r");
|
|
|
- NSMutableArray *lines = [[NSMutableArray alloc]init];
|
|
|
- if (fp)
|
|
|
- {
|
|
|
- while (fgets(line, sizeof line, fp))
|
|
|
- {
|
|
|
- NSString *s = [NSString stringWithCString:line encoding:NSUTF8StringEncoding];
|
|
|
- s = [s stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
|
|
- [lines addObject:s];
|
|
|
- }
|
|
|
- }
|
|
|
- pclose(fp);
|
|
|
- return lines;
|
|
|
-}
|
|
|
-
|
|
|
-+ (PackageFile *)packageFileFromLine:(NSString *)inputLine {
|
|
|
- // "-rwxr-xr-x 0 root wheel 69424 Oct 22 03:56 ./Library/MobileSubstrate/DynamicLibraries/beigelist7.dylib\n",
|
|
|
-
|
|
|
- //-rwxr-xr-x root/staff 10860 2011-02-02 03:55 ./Library/Frameworks/CydiaSubstrate.framework/Commands/cycc
|
|
|
-
|
|
|
- inputLine = [inputLine stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
|
|
- inputLine = [inputLine stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"\t"]];
|
|
|
- NSMutableString *newString = [[NSMutableString alloc] initWithString:inputLine];
|
|
|
- [newString replaceOccurrencesOfString:@" " withString:@" " options:NSLiteralSearch range:NSMakeRange(0, [newString length])];
|
|
|
- [newString replaceOccurrencesOfString:@" " withString:@" " options:NSLiteralSearch range:NSMakeRange(0, [newString length])];
|
|
|
- [newString replaceOccurrencesOfString:@" " withString:@" " options:NSLiteralSearch range:NSMakeRange(0, [newString length])];
|
|
|
- [newString replaceOccurrencesOfString:@" " withString:@" " options:NSLiteralSearch range:NSMakeRange(0, [newString length])];
|
|
|
- [newString replaceOccurrencesOfString:@" " withString:@" " options:NSLiteralSearch range:NSMakeRange(0, [newString length])];
|
|
|
-
|
|
|
- NSArray *lineObjects = [newString componentsSeparatedByString:@" "];
|
|
|
-
|
|
|
- //NSLog(@"lineObjects: %@", lineObjects);
|
|
|
-
|
|
|
-
|
|
|
- /*
|
|
|
-
|
|
|
- "drwxr-xr-x",
|
|
|
- "root/wheel",
|
|
|
- 0,
|
|
|
- "2018-06-27",
|
|
|
- "01:21",
|
|
|
- "./"
|
|
|
- */
|
|
|
-
|
|
|
-
|
|
|
- NSString *permissionsAndType = [lineObjects objectAtIndex:0];
|
|
|
- NSString *userGroup = [lineObjects objectAtIndex:1];
|
|
|
- NSString *size = [lineObjects objectAtIndex:2];
|
|
|
- NSString *date = [lineObjects objectAtIndex:3];
|
|
|
- NSString *time = [lineObjects objectAtIndex:4];
|
|
|
- NSString *path = [lineObjects objectAtIndex:5];
|
|
|
-
|
|
|
- //@"drwxr-xr-x"
|
|
|
- NSString *fileTypeChar = [permissionsAndType substringWithRange:NSMakeRange(0, 1)];
|
|
|
-
|
|
|
- NSString *octalPermissions = [self octalFromSymbols:permissionsAndType];
|
|
|
- NSString *octalUG = [self octalFromGroupSymbols:userGroup];
|
|
|
- NSString *fileName = [path lastPathComponent];
|
|
|
- //NSString *fullPath = [NSString stringWithFormat:@"/%@", path];
|
|
|
- NSString *fullPath = [path substringFromIndex:1];
|
|
|
-
|
|
|
- PackageFile *pf = [PackageFile new];
|
|
|
- [pf _setFileTypeFromRaw:fileTypeChar];
|
|
|
-
|
|
|
- switch (pf.type) {
|
|
|
- case BSPackageFileTypeLink:
|
|
|
- {
|
|
|
-
|
|
|
- fullPath = [lineObjects objectAtIndex:7];
|
|
|
- NSString *linkDest = [NSString stringWithFormat:@"/%@", path];
|
|
|
- pf.permissions = octalPermissions;
|
|
|
- pf.owner = octalUG;
|
|
|
- pf.size = size;
|
|
|
- pf.time = time;
|
|
|
- pf.date = date;
|
|
|
- pf.path = fullPath;
|
|
|
- pf.basename = fileName;
|
|
|
- pf.linkDestination = linkDest;
|
|
|
-
|
|
|
- return pf;
|
|
|
- }
|
|
|
- break;
|
|
|
-
|
|
|
- case BSPackageFileTypeDirectory: //return for now
|
|
|
-
|
|
|
- //DLog(@"we dont want directory entries do we %@", lineObjects);
|
|
|
- pf.permissions = octalPermissions;
|
|
|
- pf.owner = octalUG;
|
|
|
- pf.size = size;
|
|
|
- pf.time = time;
|
|
|
- pf.date = date;
|
|
|
- pf.path = fullPath;
|
|
|
- pf.basename = fileName;
|
|
|
- return pf;
|
|
|
- break;
|
|
|
-
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- pf.permissions = octalPermissions;
|
|
|
- pf.owner = octalUG;
|
|
|
- pf.size = size;
|
|
|
- pf.time = time;
|
|
|
- pf.date = date;
|
|
|
- pf.path = fullPath;
|
|
|
- pf.basename = fileName;
|
|
|
- return pf;
|
|
|
- // return [NSDictionary dictionaryWithObjectsAndKeys:fileType, @"fileType",octalPermissions, @"octalPermissions", octalUG, @"octalUG", size, @"size", date, @"date", time, @"time", fileName, @"fileName", fullPath, @"fullPath", nil];
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-+ (NSString *)octalFromGroupSymbols:(NSString *)theSymbols
|
|
|
-{
|
|
|
- NSArray *groupArray = [theSymbols componentsSeparatedByString:@"/"];
|
|
|
- NSString *user = [groupArray objectAtIndex:0];
|
|
|
- NSString *group = [groupArray objectAtIndex:1];
|
|
|
-
|
|
|
- NSString *octalUser = nil;
|
|
|
- NSString *octalGroup = nil;
|
|
|
- //uid=0(root) gid=0(wheel) groups=0(wheel),1(daemon),2(kmem),3(sys),4(tty),5(operator),8(procview),9(procmod),20(staff),29(certusers),80(admin)
|
|
|
- if ([user isEqualToString:@"root"])
|
|
|
- {
|
|
|
- octalUser = @"0";
|
|
|
- } else if ([user isEqualToString:@"mobile"])
|
|
|
- {
|
|
|
- octalUser = @"501";
|
|
|
- }
|
|
|
- //obviously more cases!! FIXME:
|
|
|
-
|
|
|
- if ([group isEqualToString:@"staff"])
|
|
|
- {
|
|
|
- octalGroup = @"20";
|
|
|
- } else if ([group isEqualToString:@"admin"])
|
|
|
- {
|
|
|
- octalGroup = @"80";
|
|
|
- } else if ([group isEqualToString:@"wheel"])
|
|
|
- {
|
|
|
- octalGroup = @"0";
|
|
|
- } else if ([group isEqualToString:@"daemon"])
|
|
|
- {
|
|
|
- octalGroup = @"1";
|
|
|
- } else if ([group isEqualToString:@"kmem"])
|
|
|
- {
|
|
|
- octalGroup = @"2";
|
|
|
- } else if ([group isEqualToString:@"sys"])
|
|
|
- {
|
|
|
- octalGroup = @"3";
|
|
|
- } else if ([group isEqualToString:@"tty"])
|
|
|
- {
|
|
|
- octalGroup = @"4";
|
|
|
- } else if ([group isEqualToString:@"operator"])
|
|
|
- {
|
|
|
- octalGroup = @"5";
|
|
|
- } else if ([group isEqualToString:@"procview"])
|
|
|
- {
|
|
|
- octalGroup = @"8";
|
|
|
- } else if ([group isEqualToString:@"procmod"])
|
|
|
- {
|
|
|
- octalGroup = @"9";
|
|
|
- } else if ([group isEqualToString:@"certusers"])
|
|
|
- {
|
|
|
- octalGroup = @"29";
|
|
|
- } else
|
|
|
- {
|
|
|
- octalGroup = @"501"; //default to mobile
|
|
|
- }
|
|
|
- //uid=0(root) gid=0(wheel) groups=0(wheel),1(daemon),2(kmem),3(sys),4(tty),5(operator),8(procview),9(procmod),20(staff),29(certusers),80(admin)
|
|
|
- return [NSString stringWithFormat:@"%@:%@", octalUser, octalGroup];
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-+ (Package *)packageForDeb:(NSString *)debFile {
|
|
|
-
|
|
|
- NSString *packageName = [[self returnForProcess:[NSString stringWithFormat:@"/usr/local/bin/dpkg -f %@ Package", debFile]] componentsJoinedByString:@"\n"];
|
|
|
- NSString *packageVersion = [[self returnForProcess:[NSString stringWithFormat:@"/usr/local/bin/dpkg -f %@ Version", debFile]] componentsJoinedByString:@"\n"];
|
|
|
- NSArray <PackageFile *> *fileList = [self returnForProcess:[NSString stringWithFormat:@"/usr/local/bin/dpkg -c %@", debFile]];
|
|
|
-
|
|
|
- __block NSMutableArray *finalArray = [NSMutableArray new];
|
|
|
-
|
|
|
- [fileList enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
|
|
|
-
|
|
|
- PackageFile *file = [self packageFileFromLine:obj];
|
|
|
- if (file) {
|
|
|
- //DLog(@"%@", file);
|
|
|
- [finalArray addObject:file];
|
|
|
- }
|
|
|
-
|
|
|
- }];
|
|
|
-
|
|
|
- Package *pkg = [Package new];
|
|
|
- pkg.files = finalArray;
|
|
|
- pkg.packageName = packageName;
|
|
|
- pkg.version = packageVersion;
|
|
|
- return pkg;
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-+ (NSString *)octalFromSymbols:(NSString *)theSymbols
|
|
|
-{
|
|
|
- //NSLog(@"%@ %s", self, _cmd);
|
|
|
- NSString *U = [theSymbols substringWithRange:NSMakeRange(1, 3)];
|
|
|
- NSString *G = [theSymbols substringWithRange:NSMakeRange(4, 3)];
|
|
|
- NSString *O = [theSymbols substringWithRange:NSMakeRange(7, 3)];
|
|
|
- //NSLog(@"fileTypeChar: %@", fileTypeChar);
|
|
|
- //NSLog(@"U; %@", U);
|
|
|
- //NSLog(@"G; %@", G);
|
|
|
- //NSLog(@"O; %@", O);
|
|
|
-
|
|
|
- //USER
|
|
|
-
|
|
|
- int sIdBit = 0;
|
|
|
-
|
|
|
- int uOctal = 0;
|
|
|
-
|
|
|
- const char *uArray = [U cStringUsingEncoding:NSASCIIStringEncoding];
|
|
|
- int stringLength = [U length];
|
|
|
-
|
|
|
- int x;
|
|
|
- for( x=0; x<stringLength; x++ )
|
|
|
- {
|
|
|
- unsigned int aCharacter = uArray[x];
|
|
|
- if (aCharacter == 'r')
|
|
|
- {
|
|
|
- uOctal += 4;
|
|
|
- } else if (aCharacter == 'w')
|
|
|
- {
|
|
|
- uOctal += 2;
|
|
|
- } else if (aCharacter == 'x')
|
|
|
- {
|
|
|
- uOctal += 1;
|
|
|
- } else if (aCharacter == 's')
|
|
|
- {
|
|
|
- sIdBit += 4;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- //GROUP
|
|
|
-
|
|
|
- int gOctal = 0;
|
|
|
- const char *gArray = [G cStringUsingEncoding:NSASCIIStringEncoding];
|
|
|
- stringLength = [G length];
|
|
|
-
|
|
|
- int y;
|
|
|
- for( y=0; y<stringLength; y++ )
|
|
|
- {
|
|
|
- unsigned int aCharacter = gArray[y];
|
|
|
- if (aCharacter == 'r')
|
|
|
- {
|
|
|
- gOctal += 4;
|
|
|
- } else if (aCharacter == 'w')
|
|
|
- {
|
|
|
- gOctal += 2;
|
|
|
- } else if (aCharacter == 'x')
|
|
|
- {
|
|
|
- gOctal += 1;
|
|
|
- } else if (aCharacter == 's')
|
|
|
- {
|
|
|
- gOctal += 2;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- //OTHERS
|
|
|
- int z;
|
|
|
- int oOctal = 0;
|
|
|
- const char *oArray = [O cStringUsingEncoding:NSASCIIStringEncoding];
|
|
|
- stringLength = [O length];
|
|
|
-
|
|
|
-
|
|
|
- for( z=0; z<stringLength; z++ )
|
|
|
- {
|
|
|
- unsigned int aCharacter = oArray[z];
|
|
|
- if (aCharacter == 'r')
|
|
|
- {
|
|
|
- oOctal += 4;
|
|
|
- } else if (aCharacter == 'w')
|
|
|
- {
|
|
|
- oOctal += 2;
|
|
|
- } else if (aCharacter == 'x')
|
|
|
- {
|
|
|
- oOctal += 1;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- return [NSString stringWithFormat:@"%i%i%i%i", sIdBit, uOctal, gOctal, oOctal];
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-@end
|
|
|
|
|
|
#define OPTION_FLAGS "o:f:b:l:d:hc"
|
|
|
|
|
@@ -903,12 +35,13 @@ char *path;
|
|
|
|
|
|
static struct option longopts[] = {
|
|
|
{ "octal", required_argument, NULL, 'o' },
|
|
|
- { "file", required_argument, NULL, 'f' },
|
|
|
+ { "input", required_argument, NULL, 'i' },
|
|
|
{ "bootstrap", required_argument, NULL, 'b' },
|
|
|
{ "list", required_argument, NULL, 'l' },
|
|
|
{ "delete", required_argument, NULL, 'd' },
|
|
|
{ "help", no_argument, NULL, 'h' },
|
|
|
{ "clean", no_argument, NULL, 'c' },
|
|
|
+ { "repackage", required_argument, NULL, 'r' },
|
|
|
{ NULL, 0, NULL, 0 }
|
|
|
};
|
|
|
|
|
@@ -917,12 +50,12 @@ void cmd_help(){
|
|
|
printf("Makes various modifications to a raw bootstrap folder\n\n");
|
|
|
|
|
|
printf(" -h, --help\t\t\tprints usage information\n");
|
|
|
- printf(" -f, --file\t\t\tthe deb package file you with to install\n");
|
|
|
+ printf(" -i, --inoput\t\t\tthe deb package to install\n");
|
|
|
printf(" -b, --bootstrap\t\tthe bootstrap folder\n");
|
|
|
- printf(" -d, --delete\t\t\tthe package you want to delete\n");
|
|
|
+ printf(" -d, --delete\t\t\tthe package to delete\n");
|
|
|
printf(" -l, --list\t\t\tlist all the packages installed on this bootstrap\n");
|
|
|
printf(" -c, --clean\t\t\tclean a bad status file from duplicate entries\n");
|
|
|
-
|
|
|
+ printf(" -r, --repackage\t\t\trepackage to fix bad locations and to change architecture\n");
|
|
|
printf("\n");
|
|
|
}
|
|
|
|
|
@@ -940,6 +73,7 @@ int main(int argc, const char * argv[]) {
|
|
|
NSString *bootstrapPath = nil;
|
|
|
NSString *bootstrapListPath = nil;
|
|
|
NSString *deletePackage = nil;
|
|
|
+ NSString *repackage = nil;
|
|
|
BOOL clean = FALSE;
|
|
|
while ((flag = getopt_long(argc, argv, OPTION_FLAGS, longopts, NULL)) != -1) {
|
|
|
switch(flag) {
|
|
@@ -967,6 +101,11 @@ int main(int argc, const char * argv[]) {
|
|
|
deletePackage = [NSString stringWithUTF8String:optarg];
|
|
|
break;
|
|
|
|
|
|
+ case 'r':
|
|
|
+
|
|
|
+ repackage = [NSString stringWithUTF8String:optarg];
|
|
|
+ break;
|
|
|
+
|
|
|
case 'c':
|
|
|
|
|
|
clean = TRUE;
|
|
@@ -977,6 +116,37 @@ int main(int argc, const char * argv[]) {
|
|
|
return -1;
|
|
|
|
|
|
}
|
|
|
+ }
|
|
|
+
|
|
|
+ if (repackage) {
|
|
|
+
|
|
|
+ NSString *pwd = [[HelperClass returnForProcess:@"/bin/pwd"] componentsJoinedByString:@"\n"];
|
|
|
+ DLog(@"\nProcessing file: %@\n", repackage);
|
|
|
+ Package *output = [HelperClass packageForDeb:repackage];
|
|
|
+
|
|
|
+ DLog(@"\nFound package: '%@' at version: '%@'...\n", output.packageName, output.version );
|
|
|
+
|
|
|
+ NSString *tmpPath = [pwd stringByAppendingPathComponent:output.packageName];
|
|
|
+ NSString *debian = [tmpPath stringByAppendingPathComponent:@"DEBIAN"];
|
|
|
+ [FM createDirectoryAtPath:tmpPath withIntermediateDirectories:TRUE attributes:nil error:nil];
|
|
|
+ DLog(@"\nExtracting package contents for processing...\n");
|
|
|
+ [HelperClass returnForProcess:[NSString stringWithFormat:@"/usr/local/bin/dpkg -x %@ %@", debFile, tmpPath]];
|
|
|
+ [FM createDirectoryAtPath:debian withIntermediateDirectories:TRUE attributes:nil error:nil];
|
|
|
+ DLog(@"\nExtracting DEBIAN files for processing...\n");
|
|
|
+ [HelperClass returnForProcess:[NSString stringWithFormat:@"/usr/local/bin/dpkg -e %@ %@", debFile, debian]];
|
|
|
+
|
|
|
+ NSString *controlPath = [debian stringByAppendingPathComponent:@"control"];
|
|
|
+
|
|
|
+ NSMutableString *controlFile = [[NSMutableString alloc] initWithContentsOfFile:controlPath encoding:NSUTF8StringEncoding error:nil];
|
|
|
+
|
|
|
+ [controlFile replaceOccurrencesOfString:@"iphoneos-arm" withString:@"appletvos-arm64" options:NSLiteralSearch range:NSMakeRange(0, [controlFile length])];
|
|
|
+
|
|
|
+ [controlFile writeToFile:controlPath atomically:TRUE];
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
}
|
|
|
|
|
|
//DLog(@"folder: %@ project: %@", folder, project);
|
|
@@ -1258,10 +428,6 @@ int main(int argc, const char * argv[]) {
|
|
|
//DLog(@"%@", output);
|
|
|
//DLog(@"list: %@", output.listfile);
|
|
|
NSFileManager *man = [NSFileManager defaultManager];
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
NSString *tmpPath = [pwd stringByAppendingPathComponent:output.packageName];
|
|
|
NSString *debian = [tmpPath stringByAppendingPathComponent:@"DEBIAN"];
|
|
|
[man createDirectoryAtPath:tmpPath withIntermediateDirectories:TRUE attributes:nil error:nil];
|