|
@@ -0,0 +1,782 @@
|
|
|
+//
|
|
|
+// main.m
|
|
|
+// octalConversion
|
|
|
+//
|
|
|
+// Created by Kevin Bradley on 6/28/18.
|
|
|
+// Copyright © 2018 nito. All rights reserved.
|
|
|
+//
|
|
|
+#import <Foundation/Foundation.h>
|
|
|
+#include <stdio.h>
|
|
|
+#include <errno.h>
|
|
|
+#include <libgen.h>
|
|
|
+#include <string.h>
|
|
|
+#include <stdlib.h>
|
|
|
+#include <unistd.h>
|
|
|
+#include <getopt.h>
|
|
|
+#import <objc/runtime.h>
|
|
|
+#import <sys/utsname.h>
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+typedef NS_ENUM(NSInteger, BSPackageFileType)
|
|
|
+{
|
|
|
+
|
|
|
+ BSPackageFileTypeFile,
|
|
|
+ BSPackageFileTypeDirectory,
|
|
|
+ BSPackageFileTypeBlock,
|
|
|
+ BSPackageFileTypeCharacter,
|
|
|
+ BSPackageFileTypeLink,
|
|
|
+ BSPackageFileTypePipe,
|
|
|
+ BSPackageFileTypeSocket,
|
|
|
+ BSPackageFileTypeUnknown
|
|
|
+
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+#define DLog(format, ...) CFShow((__bridge CFStringRef)[NSString stringWithFormat:format, ## __VA_ARGS__]);
|
|
|
+
|
|
|
+/*
|
|
|
+
|
|
|
+ fileType, @"fileType",octalPermissions, @"octalPermissions", octalUG, @"octalUG", size, @"size", date, @"date", time, @"time", linkDest, @"linkDest", fullPath, @"fullPath", nil];
|
|
|
+
|
|
|
+ */
|
|
|
+
|
|
|
+
|
|
|
+@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 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;
|
|
|
+
|
|
|
+- (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
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
++ (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(@"\nsmart move... exiting\n");
|
|
|
+ return FALSE;
|
|
|
+ } else if (c == 'y') {
|
|
|
+ DLog(@"\nits your funeral....\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"];
|
|
|
+ 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;
|
|
|
+ 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:"
|
|
|
+
|
|
|
+
|
|
|
+char *progname;
|
|
|
+char *path;
|
|
|
+
|
|
|
+static struct option longopts[] = {
|
|
|
+ { "octal", required_argument, NULL, 'o' },
|
|
|
+ { "file", required_argument, NULL, 'f' },
|
|
|
+ { "bootstrap", required_argument, NULL, 'b' },
|
|
|
+ { NULL, 0, NULL, 0 }
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+int main(int argc, const char * argv[]) {
|
|
|
+ @autoreleasepool {
|
|
|
+
|
|
|
+ setuid(0);
|
|
|
+ setgid(0);
|
|
|
+ // insert code here...
|
|
|
+ progname = basename(argv[0]);
|
|
|
+ path = dirname(argv[0]);
|
|
|
+ int flag;
|
|
|
+ NSString *octalFile = nil;
|
|
|
+ NSString *debFile = nil;
|
|
|
+ NSString *bootstrapPath = nil;
|
|
|
+ while ((flag = getopt_long(argc, argv, OPTION_FLAGS, longopts, NULL)) != -1) {
|
|
|
+ switch(flag) {
|
|
|
+ case 'o':
|
|
|
+ octalFile = [NSString stringWithUTF8String:optarg];
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'f':
|
|
|
+
|
|
|
+ debFile = [NSString stringWithUTF8String:optarg];
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'b':
|
|
|
+
|
|
|
+ bootstrapPath = [NSString stringWithUTF8String:optarg];
|
|
|
+ break;
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //DLog(@"folder: %@ project: %@", folder, project);
|
|
|
+
|
|
|
+ if (octalFile) {
|
|
|
+
|
|
|
+ NSString *octal = [HelperClass octalFromSymbols:octalFile];
|
|
|
+ DLog(@"%@", octal);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if (debFile && bootstrapPath) {
|
|
|
+
|
|
|
+ DLog(@"\n\nProcessing file: %@\n", debFile);
|
|
|
+ Package *output = [HelperClass packageForDeb:debFile];
|
|
|
+
|
|
|
+ ErrorReturn *safePackage = [output errorReturnForBootstrap:bootstrapPath];
|
|
|
+
|
|
|
+ if (safePackage.returnStatus != 0) { //zero is success
|
|
|
+
|
|
|
+ if (safePackage.returnStatus == 1) //ovewrwrites, just warnings!
|
|
|
+ {
|
|
|
+
|
|
|
+ NSString *error = [NSString stringWithFormat:@" [WARNING] %@ may overwrite the following files: %@\n\n", debFile.lastPathComponent, [safePackage.overwriteFiles componentsJoinedByString:@"\n"]];
|
|
|
+
|
|
|
+ if(![HelperClass shouldContinueWithError:error]){
|
|
|
+
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ } else if (safePackage.returnStatus == 2) //bail!!"
|
|
|
+ {
|
|
|
+ return 2;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //NSString *runPath = [NSString stringWithUTF8String:path];
|
|
|
+ NSString *pwd = [[HelperClass returnForProcess:@"/bin/pwd"] componentsJoinedByString:@"\n"];
|
|
|
+ //DLog(@"run path: %@", runPath);
|
|
|
+ //DLog(@"pwd: %@", pwd);
|
|
|
+ //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];
|
|
|
+ [HelperClass returnForProcess:[NSString stringWithFormat:@"/usr/local/bin/dpkg -x %@ %@", debFile, tmpPath]];
|
|
|
+ NSString *listFile = [pwd stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.list", output.packageName]];
|
|
|
+ NSString *md5s = [pwd stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.md5sums", output.packageName]];
|
|
|
+ [output.listfile writeToFile:listFile atomically:TRUE encoding:NSUTF8StringEncoding error:nil];
|
|
|
+ NSString *runString = [NSString stringWithFormat:@"/usr/bin/find %@ -type f -not -path \"*.DS_Store*\" -exec /sbin/md5 -r {} \\; | /usr/bin/awk '{ print $1 \" \" $2 }' | /usr/bin/sed \"s|%@||g\"", tmpPath, tmpPath];
|
|
|
+ NSString *outputs = [[HelperClass returnForProcess:runString] componentsJoinedByString:@"\n"];
|
|
|
+ [outputs writeToFile:md5s atomically:TRUE encoding:NSUTF8StringEncoding error:nil];
|
|
|
+ [man createDirectoryAtPath:debian withIntermediateDirectories:TRUE attributes:nil error:nil];
|
|
|
+ [HelperClass returnForProcess:[NSString stringWithFormat:@"/usr/local/bin/dpkg -e %@ %@", debFile, debian]];
|
|
|
+ //NSString *nextPath = [tmpPath stringByAppendingPathComponent:@"DEBIAN"];
|
|
|
+
|
|
|
+ NSArray *files = [man contentsOfDirectoryAtPath:debian error:nil];
|
|
|
+ [files enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
|
|
|
+
|
|
|
+ NSString *fullPath = [debian stringByAppendingPathComponent:obj];
|
|
|
+ if (![obj isEqualToString:@"control"]){
|
|
|
+
|
|
|
+ DLog(@"fullPath: %@", fullPath);
|
|
|
+ NSString *fileName = [NSString stringWithFormat:@"%@.%@", output.packageName, obj];
|
|
|
+ NSString *newPath = [bootstrapPath stringByAppendingPathComponent:@"Library/dpkg/info"];
|
|
|
+ newPath = [newPath stringByAppendingPathComponent:fileName];
|
|
|
+ DLog(@"newPath: %@", newPath);
|
|
|
+ [man copyItemAtPath:fullPath toPath:newPath error:nil];
|
|
|
+ } else {
|
|
|
+
|
|
|
+ NSMutableString *controlFile = [[NSMutableString alloc] initWithContentsOfFile:fullPath encoding:NSUTF8StringEncoding error:nil];
|
|
|
+
|
|
|
+
|
|
|
+ [controlFile replaceOccurrencesOfString:@"iphoneos-arm" withString:@"appletvos-arm64" options:NSLiteralSearch range:NSMakeRange(0, [controlFile length])];
|
|
|
+ DLog(@"control file: %@", controlFile);
|
|
|
+
|
|
|
+ NSString *statusFile = [bootstrapPath stringByAppendingPathComponent:@"Library/dpkg/status"];
|
|
|
+
|
|
|
+ NSMutableString *statusContents = [[NSMutableString alloc] initWithContentsOfFile:statusFile encoding:NSUTF8StringEncoding error:nil];
|
|
|
+
|
|
|
+ DLog(@"status contents: %@", statusContents);
|
|
|
+
|
|
|
+ [statusContents appendFormat:@"%@\n", controlFile];
|
|
|
+
|
|
|
+ [statusContents writeToFile:statusFile atomically:TRUE encoding:NSUTF8StringEncoding error:nil];
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ }];
|
|
|
+
|
|
|
+ //finally actually install the package onto the bootstrap
|
|
|
+ [HelperClass returnForProcess:[NSString stringWithFormat:@"/usr/local/bin/dpkg -x %@ %@", debFile, bootstrapPath]];
|
|
|
+ //DLog(@"outputs: %@", outputs);
|
|
|
+
|
|
|
+ ///usr/bin/find "$TARGET_DIR" -type f -not -path "$TARGET_DIR/DEBIAN/*" -exec "/sbin/md5 -r" {} \; | /usr/bin/awk '{ print $1 " " $2 }' | /usr/bin/sed "s|$TARGET_DIR/||g"
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|