Browse Source

just about feature complete, can clean a bad status file, delete packages in their entirety from a bootstrap now as well, also added usage information etc

Kevin Bradley 5 years ago
parent
commit
e196610a1b

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


+ 265 - 25
bootstrapTool/main.m

@@ -20,7 +20,7 @@
 
 typedef NS_ENUM(NSInteger, BSPackageFileType)
 {
-
+    
     BSPackageFileTypeFile,
     BSPackageFileTypeDirectory,
     BSPackageFileTypeBlock,
@@ -240,7 +240,7 @@ typedef NS_ENUM(NSInteger, BSPackageFileType)
             }
         }
     }
-
+    
     if ([[currentPackage allKeys] count] > 4)
     {
         self = [super init];
@@ -259,7 +259,7 @@ typedef NS_ENUM(NSInteger, BSPackageFileType)
     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);
@@ -277,7 +277,7 @@ typedef NS_ENUM(NSInteger, BSPackageFileType)
             //DLog(@"%@ doesnt respond to %@", self, mappedProp);
             
         }
-       
+        
         
     }];
     
@@ -301,10 +301,10 @@ typedef NS_ENUM(NSInteger, BSPackageFileType)
         
         DLog(@"overwriting file: %@", theFile);
     }
-        FILE *fd = fopen([theFile UTF8String], "w+");
-        const char *text = self.UTF8String;
-        fwrite(text, strlen(text) + 1, 1, fd);
-        fclose(fd);
+    FILE *fd = fopen([theFile UTF8String], "w+");
+    const char *text = self.UTF8String;
+    fwrite(text, strlen(text) + 1, 1, fd);
+    fclose(fd);
     
 }
 
@@ -334,7 +334,7 @@ typedef NS_ENUM(NSInteger, BSPackageFileType)
 @implementation PackageFile
 
 - (void)_setFileTypeFromRaw:(NSString *)rawType {
-
+    
     _fileType = [PackageFile readableFileTypeForRawMode:rawType];
     _type = [PackageFile fileTypeForRawMode:rawType];
     
@@ -403,7 +403,7 @@ typedef NS_ENUM(NSInteger, BSPackageFileType)
     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;
@@ -482,7 +482,7 @@ typedef NS_ENUM(NSInteger, BSPackageFileType)
     __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];
@@ -515,7 +515,7 @@ typedef NS_ENUM(NSInteger, BSPackageFileType)
     ErrorReturn *er = [ErrorReturn new];
     er.returnStatus = returnValue;
     er.overwriteFiles = _overwriteArray;
-
+    
     return er;
 }
 
@@ -652,7 +652,7 @@ typedef NS_ENUM(NSInteger, BSPackageFileType)
     
     //@"drwxr-xr-x"
     NSString *fileTypeChar = [permissionsAndType substringWithRange:NSMakeRange(0, 1)];
-
+    
     NSString *octalPermissions = [self octalFromSymbols:permissionsAndType];
     NSString *octalUG = [self octalFromGroupSymbols:userGroup];
     NSString *fileName = [path lastPathComponent];
@@ -697,7 +697,7 @@ typedef NS_ENUM(NSInteger, BSPackageFileType)
         default:
             break;
     }
-
+    
     
     pf.permissions = octalPermissions;
     pf.owner = octalUG;
@@ -785,7 +785,7 @@ typedef NS_ENUM(NSInteger, BSPackageFileType)
     __block NSMutableArray *finalArray = [NSMutableArray new];
     
     [fileList enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
-       
+        
         PackageFile *file = [self packageFileFromLine:obj];
         if (file) {
             //DLog(@"%@", file);
@@ -793,7 +793,7 @@ typedef NS_ENUM(NSInteger, BSPackageFileType)
         }
         
     }];
-
+    
     Package *pkg = [Package new];
     pkg.files = finalArray;
     pkg.packageName = packageName;
@@ -895,7 +895,7 @@ typedef NS_ENUM(NSInteger, BSPackageFileType)
 
 @end
 
-#define OPTION_FLAGS "o:f:b:"
+#define OPTION_FLAGS "o:f:b:l:d:hc"
 
 
 char *progname;
@@ -905,10 +905,26 @@ static struct option longopts[] = {
     { "octal",                     required_argument,      NULL,   'o' },
     { "file",                      required_argument,      NULL,   'f' },
     { "bootstrap",                 required_argument,      NULL,   'b' },
-    { NULL,         0,                      NULL,   0 }
+    { "list",                      required_argument,      NULL,   'l' },
+    { "delete",                    required_argument,      NULL,   'd' },
+    { "help",                      no_argument,            NULL,   'h' },
+    { "clean",                     no_argument,            NULL,   'c' },
+    { NULL,                        0,                      NULL,    0  }
 };
 
-
+void cmd_help(){
+    printf("Usage: bootstrapTool [OPTIONS] FILE\n");
+    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("  -b, --bootstrap\t\tthe bootstrap folder\n");
+    printf("  -d, --delete\t\t\tthe package you want 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("\n");
+}
 
 int main(int argc, const char * argv[]) {
     @autoreleasepool {
@@ -922,6 +938,9 @@ int main(int argc, const char * argv[]) {
         NSString *octalFile = nil;
         NSString *debFile = nil;
         NSString *bootstrapPath = nil;
+        NSString *bootstrapListPath = nil;
+        NSString *deletePackage = nil;
+        BOOL clean = FALSE;
         while ((flag = getopt_long(argc, argv, OPTION_FLAGS, longopts, NULL)) != -1) {
             switch(flag) {
                 case 'o':
@@ -938,21 +957,240 @@ int main(int argc, const char * argv[]) {
                     bootstrapPath = [NSString stringWithUTF8String:optarg];
                     break;
                     
+                case 'l':
+                    
+                    bootstrapListPath = [NSString stringWithUTF8String:optarg];
+                    break;
+                    
+                case 'd':
+                    
+                    deletePackage = [NSString stringWithUTF8String:optarg];
+                    break;
+                    
+                case 'c':
+                    
+                    clean = TRUE;
+                    break;
+                    
+                default:
+                    cmd_help();
+                    return -1;
                     
             }
         }
         
         //DLog(@"folder: %@ project: %@", folder, project);
         
+        if (clean && bootstrapPath) {
+            
+            NSString *statusFile = [bootstrapPath stringByAppendingPathComponent:@"Library/dpkg/status"];
+            
+            NSString *listContents = [NSString stringWithContentsOfFile:statusFile encoding:NSUTF8StringEncoding error:nil];
+            //clean up any errant spaces
+            listContents = [listContents stringByReplacingOccurrencesOfString:@"\n\n\n" withString:@"\n\n"];
+            listContents = [listContents stringByReplacingOccurrencesOfString:@"\n\n\n\n" withString:@"\n\n"];
+            [listContents writeToFile:statusFile atomically:TRUE];
+            
+            DLog(@"\n [INFO] Cleaning status file: %@", statusFile);
+            
+            NSString *testStatusFile = [bootstrapPath stringByAppendingPathComponent:@"Library/dpkg/status"];
+            NSArray <DebPackageModel*> *installedPackages = [HelperClass statusInstalledPackagesFromFile:statusFile];
+            __block NSMutableString *newStatusFile = [NSMutableString new];
+            __block NSMutableArray *alreadyAdded = [NSMutableArray new];
+            
+            [installedPackages enumerateObjectsUsingBlock:^(DebPackageModel * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
+                
+                DLog(@"\n [INFO] Processing pacakge: %@", obj.package);
+                
+                if (![alreadyAdded containsObject:obj.package]){
+                    
+                    //duplicate check first
+                    NSArray *doubleCheck = [installedPackages filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"package == %@", obj.package]];
+                    
+                    if (doubleCheck.count > 1){
+                        
+                        NSSortDescriptor *sortDesc = [NSSortDescriptor sortDescriptorWithKey:@"version" ascending:FALSE];
+                        DebPackageModel *latestVersion = [[doubleCheck sortedArrayUsingDescriptors:@[sortDesc]] firstObject];
+                        DLog(@"\n [INFO] We found a duplicate package, choosing latestVersion: %@", latestVersion);
+                        
+                        
+                        [newStatusFile appendFormat:@"%@\n\n", latestVersion.rawString];
+                        [alreadyAdded addObject:obj.package];
+                        
+                    } else {
+                        
+                        
+                        [newStatusFile appendFormat:@"%@\n\n", obj.rawString];
+                        
+                    }
+                    
+                } else {
+                    
+                    DLog(@"\n [INFO] We already had this package, skipping older duplicate: %@\n", obj.package);
+                    
+                }
+                
+            
+                
+                
+                
+            }];
+            
+            testStatusFile = [testStatusFile stringByReplacingOccurrencesOfString:@"\n\n\n" withString:@"\n\n"];
+            
+            DLog(@"\n Writing new output file: %@\n", testStatusFile);
+            
+            [newStatusFile writeToFile:testStatusFile atomically:TRUE];
+            
+            DLog(@"\n Done!\n\n");
+            
+            return 0;
+            
+        }
+        
+        if (deletePackage && bootstrapPath) {
+            
+            __block NSString *postInstFile = nil;
+            
+            NSString *statusFile = [bootstrapPath stringByAppendingPathComponent:@"Library/dpkg/status"];
+            NSArray <DebPackageModel*> *installedPackages = [HelperClass statusInstalledPackagesFromFile:statusFile];
+            
+            DebPackageModel *model = [[installedPackages filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"package == %@", deletePackage]] lastObject];
+            
+            if (model) {
+                
+                
+                NSString *listName = [NSString stringWithFormat:@"%@.list", deletePackage];
+                NSString *infoPath = [bootstrapPath stringByAppendingPathComponent:@"Library/dpkg/info"];
+                NSString *listFile = [infoPath stringByAppendingPathComponent:listName];
+                
+                NSArray *listFiles = [FM contentsOfDirectoryAtPath:infoPath error:nil];
+                
+                NSPredicate *blockPred = [NSPredicate predicateWithBlock:^BOOL(id  _Nullable evaluatedObject, NSDictionary<NSString *,id> * _Nullable bindings) {
+                    
+                    if ([evaluatedObject containsString:deletePackage]){
+                        return TRUE;
+                    }
+                    return FALSE;
+                }];
+                
+                NSArray *relatedFiles = [listFiles filteredArrayUsingPredicate:blockPred]; //any files in dpkg/info/deletePackage.*
+                
+                DLog(@"\nWe have found the package, determining list details from: %@", listFile);
+                
+                NSString *listContents = [NSString stringWithContentsOfFile:listFile encoding:NSUTF8StringEncoding error:nil];
+                DLog(@"\nContents: %@\n", listContents);
+                
+
+                
+                DLog(@"\nFound package info files: %@\n", relatedFiles);
+                
+                NSArray *files = [listContents componentsSeparatedByString:@"\n"];
+                __block NSMutableArray *filesToProcess = [NSMutableArray new];
+                
+                [relatedFiles enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
+                    
+                    NSString *fullPath = [infoPath stringByAppendingPathComponent:obj];
+                    if([FM fileExistsAtPath:fullPath]){
+                        
+                        if ([[obj pathExtension] isEqualToString:@"postinst"]){
+                            postInstFile = fullPath;
+                        }
+                        [filesToProcess addObject:fullPath];
+                        
+                    }
+                    
+                }];
+                
+                [files enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
+                    
+                    NSString *fullPath = [bootstrapPath stringByAppendingPathComponent:obj];
+                    BOOL isDir = FALSE;
+                    if([FM fileExistsAtPath:fullPath isDirectory:&isDir]){
+                        
+                        if (!isDir){
+                            DLog(@"found file: %@", fullPath);
+                            [filesToProcess addObject:fullPath];
+                        }
+                        
+                    }
+                    
+                }];
+                
+                DLog(@"\nFiles to process: %@\n", filesToProcess);
+                
+                NSString *error = [NSString stringWithFormat:@" [WARNING] We are about to delete '%@' from the bootstrap, this cannot be undone!", deletePackage];
+                if(![HelperClass shouldContinueWithError:error]){
+                    
+                    return -1;
+                }
+                
+                [filesToProcess enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
+                   
+                    [FM removeItemAtPath:obj error:nil];
+                    
+                }];
+                
+                //TODO: delete the files here!
+                
+                
+                NSString *statusFile = [bootstrapPath stringByAppendingPathComponent:@"Library/dpkg/status"];
+                [FM copyItemAtPath:statusFile toPath:[statusFile stringByAppendingPathExtension:@"bak"] error:nil];
+
+                __block NSMutableString *newStatusFile = [NSMutableString new];
+                
+                [installedPackages enumerateObjectsUsingBlock:^(DebPackageModel * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
+                    
+                    if (obj != model){
+                        
+                        [newStatusFile appendFormat:@"%@\n\n", obj.rawString];
+                        
+                    } else {
+                        
+                        DLog(@"skipping the model we want to delete: %@", obj);
+                        
+                    }
+                    
+                }];
+                
+                [newStatusFile writeToFile:statusFile atomically:TRUE];
+                
+                
+                if (postInstFile) {
+                    
+                    DLog(@"\n [WARNING] We found a postinst file, will not run this due to potential unexpected consequences off of the target device, displaying contents so you can determine if any additional steps are necessary\n");
+                    
+                    DLog(@"\n\n%@ contents:\n%@\n\n", postInstFile, [NSString stringWithContentsOfFile:postInstFile encoding:NSUTF8StringEncoding error:nil]);
+                    
+                    
+                    
+                }
+                
+            }
+            
+            
+            return 0;
+        }
+        
         if (octalFile) {
             
             NSString *octal = [HelperClass octalFromSymbols:octalFile];
             DLog(@"%@", octal);
+            return 0;
+        }
+        
+        if (bootstrapListPath) {
+            
+            NSString *statusFile = [bootstrapListPath stringByAppendingPathComponent:@"Library/dpkg/status"];
+            NSArray *installedPackages = [HelperClass statusInstalledPackagesFromFile:statusFile];
+            DLog(@"%@", installedPackages);
+            return 0;
             
         }
         
-        if (debFile && bootstrapPath) {
         
+        if (debFile && bootstrapPath) {
+            
             NSString *statusFile = [bootstrapPath stringByAppendingPathComponent:@"Library/dpkg/status"];
             NSArray *installedPackages = [HelperClass statusInstalledPackagesFromFile:statusFile];
             
@@ -1021,7 +1259,7 @@ int main(int argc, const char * argv[]) {
             //DLog(@"list: %@", output.listfile);
             NSFileManager *man = [NSFileManager defaultManager];
             
-         
+            
             
             
             NSString *tmpPath = [pwd stringByAppendingPathComponent:output.packageName];
@@ -1061,7 +1299,7 @@ int main(int argc, const char * argv[]) {
                 
                 NSString *fullPath = [debian stringByAppendingPathComponent:obj];
                 if (![obj isEqualToString:@"control"]){
-                   
+                    
                     DLog(@"Copying file... %@\n\n", fullPath);
                     NSString *fileName = [NSString stringWithFormat:@"%@.%@", output.packageName, obj];
                     NSString *newPath = [bootstrapPath stringByAppendingPathComponent:@"Library/dpkg/info"];
@@ -1114,7 +1352,7 @@ int main(int argc, const char * argv[]) {
                         
                     }
                     
-                 
+                    
                     //DLog(@"\n\nwe down here??\n\n");
                     
                     //NSString *newString = [[HelperClass returnForProcess:[NSString stringWithFormat:@"/bin/cat %@", statusFile]] componentsJoinedByString:@"\n"];
@@ -1127,7 +1365,7 @@ int main(int argc, const char * argv[]) {
                     
                     
                     
-//                    [statusContents writeToFile:statusFile atomically:TRUE encoding:NSUTF8StringEncoding error:nil];
+                    //                    [statusContents writeToFile:statusFile atomically:TRUE encoding:NSUTF8StringEncoding error:nil];
                     
                     
                     
@@ -1146,8 +1384,10 @@ int main(int argc, const char * argv[]) {
             ///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"
             
             DLog(@"Done!\n\n");
-            
+            return 0;
         }
+        //if we got this far.. nothing happened, print help.
+        cmd_help();
         
     }
     return 0;