Browse Source

handy tool for safely extracting debs onto a bootstrap root

Kevin Bradley 5 years ago
parent
commit
2936a0d609

+ 274 - 0
bootstrapTool.xcodeproj/project.pbxproj

@@ -0,0 +1,274 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 48;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		3249302B20E4E29700E99767 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 3249302A20E4E29700E99767 /* main.m */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+		3249302520E4E29700E99767 /* CopyFiles */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 2147483647;
+			dstPath = /usr/share/man/man1/;
+			dstSubfolderSpec = 0;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 1;
+		};
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+		3249302720E4E29700E99767 /* bootstrapTool */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = bootstrapTool; sourceTree = BUILT_PRODUCTS_DIR; };
+		3249302A20E4E29700E99767 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		3249302420E4E29700E99767 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		3249301E20E4E29700E99767 = {
+			isa = PBXGroup;
+			children = (
+				3249302920E4E29700E99767 /* bootstrapTool */,
+				3249302820E4E29700E99767 /* Products */,
+			);
+			sourceTree = "<group>";
+		};
+		3249302820E4E29700E99767 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				3249302720E4E29700E99767 /* bootstrapTool */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		3249302920E4E29700E99767 /* bootstrapTool */ = {
+			isa = PBXGroup;
+			children = (
+				3249302A20E4E29700E99767 /* main.m */,
+			);
+			path = bootstrapTool;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+		3249302620E4E29700E99767 /* bootstrapTool */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 3249302E20E4E29700E99767 /* Build configuration list for PBXNativeTarget "bootstrapTool" */;
+			buildPhases = (
+				3249302320E4E29700E99767 /* Sources */,
+				3249302420E4E29700E99767 /* Frameworks */,
+				3249302520E4E29700E99767 /* CopyFiles */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = bootstrapTool;
+			productName = octalConversion;
+			productReference = 3249302720E4E29700E99767 /* bootstrapTool */;
+			productType = "com.apple.product-type.tool";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		3249301F20E4E29700E99767 /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				LastUpgradeCheck = 0900;
+				ORGANIZATIONNAME = nito;
+				TargetAttributes = {
+					3249302620E4E29700E99767 = {
+						CreatedOnToolsVersion = 9.0;
+						ProvisioningStyle = Automatic;
+					};
+				};
+			};
+			buildConfigurationList = 3249302220E4E29700E99767 /* Build configuration list for PBXProject "bootstrapTool" */;
+			compatibilityVersion = "Xcode 8.0";
+			developmentRegion = en;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+			);
+			mainGroup = 3249301E20E4E29700E99767;
+			productRefGroup = 3249302820E4E29700E99767 /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				3249302620E4E29700E99767 /* bootstrapTool */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXSourcesBuildPhase section */
+		3249302320E4E29700E99767 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				3249302B20E4E29700E99767 /* main.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+		3249302C20E4E29700E99767 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				CODE_SIGN_IDENTITY = "Mac Developer";
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				ENABLE_TESTABILITY = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu11;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"DEBUG=1",
+					"$(inherited)",
+				);
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				MACOSX_DEPLOYMENT_TARGET = 10.12;
+				MTL_ENABLE_DEBUG_INFO = YES;
+				ONLY_ACTIVE_ARCH = YES;
+				SDKROOT = macosx;
+			};
+			name = Debug;
+		};
+		3249302D20E4E29700E99767 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				CODE_SIGN_IDENTITY = "Mac Developer";
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				ENABLE_NS_ASSERTIONS = NO;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu11;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				MACOSX_DEPLOYMENT_TARGET = 10.12;
+				MTL_ENABLE_DEBUG_INFO = NO;
+				SDKROOT = macosx;
+			};
+			name = Release;
+		};
+		3249302F20E4E29700E99767 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CODE_SIGN_STYLE = Automatic;
+				DEVELOPMENT_TEAM = 9EUFEA5U7G;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Debug;
+		};
+		3249303020E4E29700E99767 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CODE_SIGN_STYLE = Automatic;
+				DEVELOPMENT_TEAM = 9EUFEA5U7G;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		3249302220E4E29700E99767 /* Build configuration list for PBXProject "bootstrapTool" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				3249302C20E4E29700E99767 /* Debug */,
+				3249302D20E4E29700E99767 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		3249302E20E4E29700E99767 /* Build configuration list for PBXNativeTarget "bootstrapTool" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				3249302F20E4E29700E99767 /* Debug */,
+				3249303020E4E29700E99767 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 3249301F20E4E29700E99767 /* Project object */;
+}

+ 7 - 0
bootstrapTool.xcodeproj/project.xcworkspace/contents.xcworkspacedata

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+   version = "1.0">
+   <FileRef
+      location = "self:/Users/kevinbradley/Projects/octalConversion/bootstrapTool.xcodeproj">
+   </FileRef>
+</Workspace>

BIN
bootstrapTool.xcodeproj/project.xcworkspace/xcuserdata/kevinbradley.xcuserdatad/UserInterfaceState.xcuserstate


+ 93 - 0
bootstrapTool.xcodeproj/xcuserdata/kevinbradley.xcuserdatad/xcschemes/bootstrapTool.xcscheme

@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "0900"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "3249302620E4E29700E99767"
+               BuildableName = "bootstrapTool"
+               BlueprintName = "bootstrapTool"
+               ReferencedContainer = "container:bootstrapTool.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      language = ""
+      shouldUseLaunchSchemeArgsEnv = "YES">
+      <Testables>
+      </Testables>
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "3249302620E4E29700E99767"
+            BuildableName = "bootstrapTool"
+            BlueprintName = "bootstrapTool"
+            ReferencedContainer = "container:bootstrapTool.xcodeproj">
+         </BuildableReference>
+      </MacroExpansion>
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      language = ""
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "3249302620E4E29700E99767"
+            BuildableName = "bootstrapTool"
+            BlueprintName = "bootstrapTool"
+            ReferencedContainer = "container:bootstrapTool.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "3249302620E4E29700E99767"
+            BuildableName = "bootstrapTool"
+            BlueprintName = "bootstrapTool"
+            ReferencedContainer = "container:bootstrapTool.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>

+ 22 - 0
bootstrapTool.xcodeproj/xcuserdata/kevinbradley.xcuserdatad/xcschemes/xcschememanagement.plist

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>SchemeUserState</key>
+	<dict>
+		<key>bootstrapTool.xcscheme</key>
+		<dict>
+			<key>orderHint</key>
+			<integer>0</integer>
+		</dict>
+	</dict>
+	<key>SuppressBuildableAutocreation</key>
+	<dict>
+		<key>3249302620E4E29700E99767</key>
+		<dict>
+			<key>primary</key>
+			<true/>
+		</dict>
+	</dict>
+</dict>
+</plist>

+ 782 - 0
bootstrapTool/main.m

@@ -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;
+}