123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389 |
- //
- // 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 <sys/utsname.h>
- #import "HelperClass.h"
- #define OPTION_FLAGS "o:i:ld:hcrb"
- char *progname;
- char *path;
- static struct option longopts[] = {
- { "octal", required_argument, NULL, 'o' },
- { "input", required_argument, NULL, 'i' },
- { "list", no_argument, NULL, 'l' },
- { "delete", required_argument, NULL, 'd' },
- { "help", no_argument, NULL, 'h' },
- { "clean", no_argument, NULL, 'c' },
- { "repackage", no_argument, NULL, 'r' },
- { "bump", no_argument, NULL, 'b' },
- { NULL, 0, NULL, 0 }
- };
- void cmd_help(){
- printf("Usage: bootstrapTool [OPTIONS] BOOTSTRAP_FOLDER\n");
- printf("Makes various modifications to a raw bootstrap folder\n\n");
-
- printf(" -h, --help\t\t\tprints usage information\n");
- printf(" -i, --input\t\t\tthe deb package to process\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\trepackage to fix bad locations and to change architecture\n");
- printf(" -b, --bump\t\trepackage and bump by one - number (ie 1.0-1 -> 1.0-2)\n");
- printf("\n");
- }
- int main(int argc, const char * argv[]) {
- @autoreleasepool {
-
- setuid(0);
- setgid(0);
- progname = basename(argv[0]);
- path = dirname(argv[0]);
- int flag;
- NSString *octalFile = nil;
- NSString *debFile = nil;
- NSString *bootstrapPath = nil;
- NSString *deletePackage = nil;
- BOOL listPackage = FALSE;
- BOOL repackage = FALSE;
- BOOL bump = FALSE;
- BOOL clean = FALSE;
- while ((flag = getopt_long(argc, argv, OPTION_FLAGS, longopts, NULL)) != -1) {
- switch(flag) {
- case 'o':
- octalFile = [NSString stringWithUTF8String:optarg];
- break;
-
- case 'i':
-
- debFile = [NSString stringWithUTF8String:optarg];
- break;
-
- case 'l':
-
- listPackage = TRUE;
- break;
-
- case 'd':
-
- deletePackage = [NSString stringWithUTF8String:optarg];
- break;
-
- case 'b':
-
- bump = TRUE;
-
- break;
-
- case 'r':
-
- repackage = TRUE;
- break;
-
- case 'c':
-
- clean = TRUE;
- break;
-
- default:
- cmd_help();
- return -1;
-
- }
- }
-
- if (argc-optind == 1) {
- argc -= optind;
- argv += optind;
-
- bootstrapPath = [NSString stringWithUTF8String:argv[0]];
- NSLog(@"bootstrap path: %@?", bootstrapPath);
- //return 0;
- }
-
- if (bump == TRUE && debFile) {
-
- DLog(@"\n [INFO] Bumping version number for file: %@...\n", debFile);
- InputPackage *output = [HelperClass packageForDeb:debFile];
- [output bumpVersionInCurrentDirectory];
- return 0;
- }
-
- if (repackage == TRUE && debFile) {
-
- DLog(@"\n [INFO] Repackaging file: %@...\n", debFile);
- InputPackage *output = [HelperClass packageForDeb:debFile];
- [output repackageInCurrentDirectoryWithArch:@"appletvos-arm64"];
- return 0;
- }
-
-
- //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 <StatusPackageModel*> *installedPackages = [HelperClass statusInstalledPackagesFromFile:statusFile];
- __block NSMutableString *newStatusFile = [NSMutableString new];
- __block NSMutableArray *alreadyAdded = [NSMutableArray new];
-
- [installedPackages enumerateObjectsUsingBlock:^(StatusPackageModel * _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];
- StatusPackageModel *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;
-
- } else if (clean) {
-
- DLog(@"\nYou need to choose a bootstrap path to clean!\n\n");
- return 1;
-
- }
-
- if (deletePackage && bootstrapPath) {
-
- __block NSString *postRmFile = nil;
-
- NSString *statusFile = [bootstrapPath stringByAppendingPathComponent:@"Library/dpkg/status"];
- NSArray <StatusPackageModel*> *installedPackages = [HelperClass statusInstalledPackagesFromFile:statusFile];
-
- StatusPackageModel *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:@"postrm"]){
- postRmFile = 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:^(StatusPackageModel * _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 (postRmFile) {
-
- DLog(@"\n [WARNING] We found a postrm 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", postRmFile, [NSString stringWithContentsOfFile:postRmFile encoding:NSUTF8StringEncoding error:nil]);
-
-
-
- }
-
- }
-
-
- return 0;
- } else if (deletePackage) {
-
- DLog(@"\nYou need to choose a bootstrap path to delete from!\n\n");
- return 1;
-
- }
-
- if (octalFile) {
-
- if([[NSFileManager defaultManager] fileExistsAtPath:octalFile]) {
-
- NSDictionary *attrs = [FM attributesOfItemAtPath:octalFile error:nil];
- NSNumber *posixPerms = attrs[NSFilePosixPermissions];
- DLog(@"perms: %@", posixPerms);
- return 0;
-
- }
- NSString *octal = [HelperClass octalFromSymbols:octalFile];
- DLog(@"%@", octal);
- return 0;
- }
-
- if (listPackage && bootstrapPath) {
-
- NSString *statusFile = [bootstrapPath stringByAppendingPathComponent:@"Library/dpkg/status"];
- NSArray *installedPackages = [HelperClass statusInstalledPackagesFromFile:statusFile];
- DLog(@"%@", installedPackages);
- return 0;
-
- } else if (listPackage) {
-
- DLog(@"\nYou need to choose a bootstrap path to list packages from!\n\n");
- return 1;
- }
-
-
- if (debFile && bootstrapPath) {
-
-
- DLog(@"\nProcessing file: %@\n", debFile);
- InputPackage *output = [HelperClass packageForDeb:debFile];
- return [output installToBootstrapPath:bootstrapPath];
-
- } else if (debFile) {
- DLog(@"\nYou need to choose a bootstrap path to install the package to!\n\n");
- return 1;
- }
- //if we got this far.. nothing happened, print help.
- cmd_help();
-
- }
- return 0;
- }
|