main.m 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783
  1. //
  2. // main.m
  3. // octalConversion
  4. //
  5. // Created by Kevin Bradley on 6/28/18.
  6. // Copyright © 2018 nito. All rights reserved.
  7. //
  8. #import <Foundation/Foundation.h>
  9. #include <stdio.h>
  10. #include <errno.h>
  11. #include <libgen.h>
  12. #include <string.h>
  13. #include <stdlib.h>
  14. #include <unistd.h>
  15. #include <getopt.h>
  16. #import <objc/runtime.h>
  17. #import <sys/utsname.h>
  18. typedef NS_ENUM(NSInteger, BSPackageFileType)
  19. {
  20. BSPackageFileTypeFile,
  21. BSPackageFileTypeDirectory,
  22. BSPackageFileTypeBlock,
  23. BSPackageFileTypeCharacter,
  24. BSPackageFileTypeLink,
  25. BSPackageFileTypePipe,
  26. BSPackageFileTypeSocket,
  27. BSPackageFileTypeUnknown
  28. };
  29. #define DLog(format, ...) CFShow((__bridge CFStringRef)[NSString stringWithFormat:format, ## __VA_ARGS__]);
  30. /*
  31. fileType, @"fileType",octalPermissions, @"octalPermissions", octalUG, @"octalUG", size, @"size", date, @"date", time, @"time", linkDest, @"linkDest", fullPath, @"fullPath", nil];
  32. */
  33. @interface NSObject (Additions)
  34. -(NSArray *)ivars;
  35. -(NSArray *)properties;
  36. @end
  37. @implementation NSObject (Additions)
  38. - (NSArray *)properties
  39. {
  40. u_int count;
  41. objc_property_t* properties = class_copyPropertyList(self.class, &count);
  42. NSMutableArray* propArray = [NSMutableArray arrayWithCapacity:count];
  43. for (int i = 0; i < count ; i++)
  44. {
  45. const char* propertyName = property_getName(properties[i]);
  46. NSString *propName = [NSString stringWithCString:propertyName encoding:NSUTF8StringEncoding];
  47. [propArray addObject:propName];
  48. }
  49. free(properties);
  50. return propArray;
  51. }
  52. -(NSArray *)ivars
  53. {
  54. Class clazz = [self class];
  55. u_int count;
  56. Ivar* ivars = class_copyIvarList(clazz, &count);
  57. NSMutableArray* ivarArray = [NSMutableArray arrayWithCapacity:count];
  58. for (int i = 0; i < count ; i++)
  59. {
  60. const char* ivarName = ivar_getName(ivars[i]);
  61. [ivarArray addObject:[NSString stringWithCString:ivarName encoding:NSUTF8StringEncoding]];
  62. }
  63. free(ivars);
  64. return ivarArray;
  65. }
  66. @end
  67. @interface PackageFile: NSObject
  68. @property (nonatomic, strong) NSString *fileType;
  69. @property (nonatomic, strong) NSString *permissions;
  70. @property (nonatomic, strong) NSString *owner;
  71. @property (nonatomic, strong) NSString *size;
  72. @property (nonatomic, strong) NSString *date;
  73. @property (nonatomic, strong) NSString *time;
  74. @property (nonatomic, strong) NSString *linkDestination;
  75. @property (nonatomic, strong) NSString *path;
  76. @property (nonatomic, strong) NSString *basename;
  77. @property (readwrite, assign) BSPackageFileType type;
  78. - (void)_setFileTypeFromRaw:(NSString *)rawType;
  79. @end
  80. @implementation PackageFile
  81. - (void)_setFileTypeFromRaw:(NSString *)rawType {
  82. _fileType = [PackageFile readableFileTypeForRawMode:rawType];
  83. _type = [PackageFile fileTypeForRawMode:rawType];
  84. }
  85. /*
  86. - denotes a regular file
  87. d denotes a directory
  88. b denotes a block special file
  89. c denotes a character special file
  90. l denotes a symbolic link
  91. p denotes a named pipe
  92. s denotes a domain socket
  93. */
  94. + (NSString* )readableFileTypeForRawMode:(NSString *)fileTypeChar {
  95. NSString *fileType = nil;
  96. if ([fileTypeChar isEqualToString:@"-"])
  97. { fileType = @"file"; }
  98. else if ([fileTypeChar isEqualToString:@"d"])
  99. { fileType = @"directory"; }
  100. else if ([fileTypeChar isEqualToString:@"b"])
  101. { fileType = @"block"; }
  102. else if ([fileTypeChar isEqualToString:@"c"])
  103. { fileType = @"character"; }
  104. else if ([fileTypeChar isEqualToString:@"l"])
  105. { fileType = @"link"; }
  106. else if ([fileTypeChar isEqualToString:@"p"])
  107. { fileType = @"pipe"; }
  108. else if ([fileTypeChar isEqualToString:@"s"])
  109. { fileType = @"socket"; }
  110. return fileType;
  111. }
  112. + (BSPackageFileType)fileTypeForRawMode:(NSString *)fileTypeChar {
  113. BSPackageFileType type = BSPackageFileTypeUnknown;
  114. if ([fileTypeChar isEqualToString:@"-"])
  115. { type = BSPackageFileTypeFile; }
  116. else if ([fileTypeChar isEqualToString:@"d"])
  117. { type = BSPackageFileTypeDirectory; }
  118. else if ([fileTypeChar isEqualToString:@"b"])
  119. { type = BSPackageFileTypeBlock; }
  120. else if ([fileTypeChar isEqualToString:@"c"])
  121. { type = BSPackageFileTypeCharacter; }
  122. else if ([fileTypeChar isEqualToString:@"l"])
  123. { type = BSPackageFileTypeLink; }
  124. else if ([fileTypeChar isEqualToString:@"p"])
  125. { type = BSPackageFileTypePipe; }
  126. else if ([fileTypeChar isEqualToString:@"s"])
  127. { type = BSPackageFileTypeSocket; }
  128. return type;
  129. }
  130. - (NSString*) description {
  131. NSString *orig = [super description];
  132. NSMutableDictionary *details = [NSMutableDictionary new];
  133. NSArray *props = [self properties];
  134. [props enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  135. NSString *cv = [self valueForKey:obj];
  136. if (cv){
  137. details[obj] = cv;
  138. }
  139. }];
  140. return [NSString stringWithFormat:@"%@ = %@", orig, details];
  141. }
  142. @end
  143. @interface ErrorReturn: NSObject
  144. @property (nonatomic, strong) NSArray *overwriteFiles;
  145. @property (readwrite, assign) NSInteger returnStatus;
  146. @end
  147. @implementation ErrorReturn
  148. @end
  149. @interface Package: NSObject
  150. @property (nonatomic, strong) NSArray <PackageFile *> *files;
  151. @property (nonatomic, strong) NSArray *controlFiles;
  152. @property (nonatomic, strong) NSString *packageName;
  153. - (ErrorReturn *)errorReturnForBootstrap:(NSString *)bootstrapPath;
  154. - (NSString *)listfile;
  155. @end
  156. @implementation Package
  157. - (NSString*) description {
  158. NSString *orig = [super description];
  159. NSMutableDictionary *details = [NSMutableDictionary new];
  160. NSArray *props = [self properties];
  161. [props enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  162. NSString *cv = [self valueForKey:obj];
  163. if (cv){
  164. details[obj] = cv;
  165. }
  166. }];
  167. return [NSString stringWithFormat:@"%@ = %@", orig, details];
  168. }
  169. - (NSString *)listfile {
  170. __block NSMutableArray *outFiles = [NSMutableArray new];
  171. [self.files enumerateObjectsUsingBlock:^(PackageFile * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  172. if ([obj.fileType isEqualToString:@"link"]){ //does this need to handle things differently?
  173. [outFiles addObject:obj.path];
  174. } else {
  175. [outFiles addObject:obj.path];
  176. }
  177. }];
  178. return [outFiles componentsJoinedByString:@"\n"];
  179. }
  180. - (ErrorReturn *)errorReturnForBootstrap:(NSString *)bootstrapPath
  181. {
  182. NSArray *ignoreFiles = @[@".fauxsu", @".DS_Store"];
  183. NSArray *forbiddenRoots = @[@"etc", @"var", @"tmp"];
  184. NSFileManager *man = [NSFileManager defaultManager];
  185. __block NSInteger returnValue = 0; //0 = good to go 1 = over write warning, 2 = no go
  186. __block NSMutableArray *_overwriteArray = [NSMutableArray new];
  187. [self.files enumerateObjectsUsingBlock:^(PackageFile * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  188. if ([obj.fileType isEqualToString:@"file"]){
  189. NSString *fullPath = [bootstrapPath stringByAppendingPathComponent:obj.path];
  190. if ([man fileExistsAtPath:fullPath] && ![ignoreFiles containsObject:obj.basename]){
  191. //DLog(@"[WARNING] overwriting a file that already exists and isn't DS_Store or .fauxsu: %@", fullPath);
  192. [_overwriteArray addObject:obj.path];
  193. //*stop = TRUE;//return FALSE;
  194. returnValue = 1;
  195. }
  196. NSArray *pathComponents = [obj.path pathComponents];
  197. if ([pathComponents count] > 1)
  198. {
  199. NSString *rootPath = [pathComponents objectAtIndex:1];
  200. if ([forbiddenRoots containsObject:rootPath])
  201. {
  202. DLog(@"\n [ERROR] package file: '%@' would overwrite symbolic link at '%@'! Exiting!\n\n", obj.path, rootPath);
  203. *stop = TRUE;
  204. returnValue = 2;
  205. }
  206. }
  207. }
  208. }];
  209. ErrorReturn *er = [ErrorReturn new];
  210. er.returnStatus = returnValue;
  211. er.overwriteFiles = _overwriteArray;
  212. return er;
  213. }
  214. @end
  215. @interface HelperClass: NSObject
  216. + (BOOL)shouldContinueWithError:(NSString *)errorMessage;
  217. + (NSArray *)returnForProcess:(NSString *)call;
  218. + (Package *)packageForDeb:(NSString *)debFile;
  219. + (NSString *)octalFromSymbols:(NSString *)theSymbols;
  220. @end
  221. @implementation HelperClass
  222. + (BOOL)shouldContinueWithError:(NSString *)errorMessage {
  223. NSString *errorString = [NSString stringWithFormat:@"\n%@Are you sure you want to continue? [y/n]?", errorMessage];
  224. char c;
  225. printf("%s", [errorString UTF8String] );
  226. c=getchar();
  227. while(c!='y' && c!='n')
  228. {
  229. if (c!='\n'){
  230. printf("[y/n]");
  231. }
  232. c=getchar();
  233. }
  234. if (c == 'n')
  235. {
  236. DLog(@"\nsmart move... exiting\n");
  237. return FALSE;
  238. } else if (c == 'y') {
  239. DLog(@"\nits your funeral....\n");
  240. }
  241. return TRUE;
  242. }
  243. + (NSArray *)returnForProcess:(NSString *)call
  244. {
  245. if (call==nil)
  246. return 0;
  247. char line[200];
  248. //DDLogInfo(@"running process: %@", call);
  249. FILE* fp = popen([call UTF8String], "r");
  250. NSMutableArray *lines = [[NSMutableArray alloc]init];
  251. if (fp)
  252. {
  253. while (fgets(line, sizeof line, fp))
  254. {
  255. NSString *s = [NSString stringWithCString:line encoding:NSUTF8StringEncoding];
  256. s = [s stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
  257. [lines addObject:s];
  258. }
  259. }
  260. pclose(fp);
  261. return lines;
  262. }
  263. + (PackageFile *)packageFileFromLine:(NSString *)inputLine {
  264. // "-rwxr-xr-x 0 root wheel 69424 Oct 22 03:56 ./Library/MobileSubstrate/DynamicLibraries/beigelist7.dylib\n",
  265. //-rwxr-xr-x root/staff 10860 2011-02-02 03:55 ./Library/Frameworks/CydiaSubstrate.framework/Commands/cycc
  266. inputLine = [inputLine stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
  267. inputLine = [inputLine stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"\t"]];
  268. NSMutableString *newString = [[NSMutableString alloc] initWithString:inputLine];
  269. [newString replaceOccurrencesOfString:@" " withString:@" " options:NSLiteralSearch range:NSMakeRange(0, [newString length])];
  270. [newString replaceOccurrencesOfString:@" " withString:@" " options:NSLiteralSearch range:NSMakeRange(0, [newString length])];
  271. [newString replaceOccurrencesOfString:@" " withString:@" " options:NSLiteralSearch range:NSMakeRange(0, [newString length])];
  272. [newString replaceOccurrencesOfString:@" " withString:@" " options:NSLiteralSearch range:NSMakeRange(0, [newString length])];
  273. [newString replaceOccurrencesOfString:@" " withString:@" " options:NSLiteralSearch range:NSMakeRange(0, [newString length])];
  274. NSArray *lineObjects = [newString componentsSeparatedByString:@" "];
  275. //NSLog(@"lineObjects: %@", lineObjects);
  276. /*
  277. "drwxr-xr-x",
  278. "root/wheel",
  279. 0,
  280. "2018-06-27",
  281. "01:21",
  282. "./"
  283. */
  284. NSString *permissionsAndType = [lineObjects objectAtIndex:0];
  285. NSString *userGroup = [lineObjects objectAtIndex:1];
  286. NSString *size = [lineObjects objectAtIndex:2];
  287. NSString *date = [lineObjects objectAtIndex:3];
  288. NSString *time = [lineObjects objectAtIndex:4];
  289. NSString *path = [lineObjects objectAtIndex:5];
  290. //@"drwxr-xr-x"
  291. NSString *fileTypeChar = [permissionsAndType substringWithRange:NSMakeRange(0, 1)];
  292. NSString *octalPermissions = [self octalFromSymbols:permissionsAndType];
  293. NSString *octalUG = [self octalFromGroupSymbols:userGroup];
  294. NSString *fileName = [path lastPathComponent];
  295. //NSString *fullPath = [NSString stringWithFormat:@"/%@", path];
  296. NSString *fullPath = [path substringFromIndex:1];
  297. PackageFile *pf = [PackageFile new];
  298. [pf _setFileTypeFromRaw:fileTypeChar];
  299. switch (pf.type) {
  300. case BSPackageFileTypeLink:
  301. {
  302. fullPath = [lineObjects objectAtIndex:7];
  303. NSString *linkDest = [NSString stringWithFormat:@"/%@", path];
  304. pf.permissions = octalPermissions;
  305. pf.owner = octalUG;
  306. pf.size = size;
  307. pf.time = time;
  308. pf.date = date;
  309. pf.path = fullPath;
  310. pf.basename = fileName;
  311. pf.linkDestination = linkDest;
  312. return pf;
  313. }
  314. break;
  315. case BSPackageFileTypeDirectory: //return for now
  316. //DLog(@"we dont want directory entries do we %@", lineObjects);
  317. pf.permissions = octalPermissions;
  318. pf.owner = octalUG;
  319. pf.size = size;
  320. pf.time = time;
  321. pf.date = date;
  322. pf.path = fullPath;
  323. pf.basename = fileName;
  324. return pf;
  325. break;
  326. default:
  327. break;
  328. }
  329. pf.permissions = octalPermissions;
  330. pf.owner = octalUG;
  331. pf.size = size;
  332. pf.time = time;
  333. pf.date = date;
  334. pf.path = fullPath;
  335. pf.basename = fileName;
  336. return pf;
  337. // return [NSDictionary dictionaryWithObjectsAndKeys:fileType, @"fileType",octalPermissions, @"octalPermissions", octalUG, @"octalUG", size, @"size", date, @"date", time, @"time", fileName, @"fileName", fullPath, @"fullPath", nil];
  338. }
  339. + (NSString *)octalFromGroupSymbols:(NSString *)theSymbols
  340. {
  341. NSArray *groupArray = [theSymbols componentsSeparatedByString:@"/"];
  342. NSString *user = [groupArray objectAtIndex:0];
  343. NSString *group = [groupArray objectAtIndex:1];
  344. NSString *octalUser = nil;
  345. NSString *octalGroup = nil;
  346. //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)
  347. if ([user isEqualToString:@"root"])
  348. {
  349. octalUser = @"0";
  350. } else if ([user isEqualToString:@"mobile"])
  351. {
  352. octalUser = @"501";
  353. }
  354. //obviously more cases!! FIXME:
  355. if ([group isEqualToString:@"staff"])
  356. {
  357. octalGroup = @"20";
  358. } else if ([group isEqualToString:@"admin"])
  359. {
  360. octalGroup = @"80";
  361. } else if ([group isEqualToString:@"wheel"])
  362. {
  363. octalGroup = @"0";
  364. } else if ([group isEqualToString:@"daemon"])
  365. {
  366. octalGroup = @"1";
  367. } else if ([group isEqualToString:@"kmem"])
  368. {
  369. octalGroup = @"2";
  370. } else if ([group isEqualToString:@"sys"])
  371. {
  372. octalGroup = @"3";
  373. } else if ([group isEqualToString:@"tty"])
  374. {
  375. octalGroup = @"4";
  376. } else if ([group isEqualToString:@"operator"])
  377. {
  378. octalGroup = @"5";
  379. } else if ([group isEqualToString:@"procview"])
  380. {
  381. octalGroup = @"8";
  382. } else if ([group isEqualToString:@"procmod"])
  383. {
  384. octalGroup = @"9";
  385. } else if ([group isEqualToString:@"certusers"])
  386. {
  387. octalGroup = @"29";
  388. } else
  389. {
  390. octalGroup = @"501"; //default to mobile
  391. }
  392. //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)
  393. return [NSString stringWithFormat:@"%@:%@", octalUser, octalGroup];
  394. }
  395. + (Package *)packageForDeb:(NSString *)debFile {
  396. NSString *packageName = [[self returnForProcess:[NSString stringWithFormat:@"/usr/local/bin/dpkg -f %@ Package", debFile]] componentsJoinedByString:@"\n"];
  397. NSArray <PackageFile *> *fileList = [self returnForProcess:[NSString stringWithFormat:@"/usr/local/bin/dpkg -c %@", debFile]];
  398. __block NSMutableArray *finalArray = [NSMutableArray new];
  399. [fileList enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  400. PackageFile *file = [self packageFileFromLine:obj];
  401. if (file) {
  402. //DLog(@"%@", file);
  403. [finalArray addObject:file];
  404. }
  405. }];
  406. Package *pkg = [Package new];
  407. pkg.files = finalArray;
  408. pkg.packageName = packageName;
  409. return pkg;
  410. }
  411. + (NSString *)octalFromSymbols:(NSString *)theSymbols
  412. {
  413. //NSLog(@"%@ %s", self, _cmd);
  414. NSString *U = [theSymbols substringWithRange:NSMakeRange(1, 3)];
  415. NSString *G = [theSymbols substringWithRange:NSMakeRange(4, 3)];
  416. NSString *O = [theSymbols substringWithRange:NSMakeRange(7, 3)];
  417. //NSLog(@"fileTypeChar: %@", fileTypeChar);
  418. //NSLog(@"U; %@", U);
  419. //NSLog(@"G; %@", G);
  420. //NSLog(@"O; %@", O);
  421. //USER
  422. int sIdBit = 0;
  423. int uOctal = 0;
  424. const char *uArray = [U cStringUsingEncoding:NSASCIIStringEncoding];
  425. int stringLength = [U length];
  426. int x;
  427. for( x=0; x<stringLength; x++ )
  428. {
  429. unsigned int aCharacter = uArray[x];
  430. if (aCharacter == 'r')
  431. {
  432. uOctal += 4;
  433. } else if (aCharacter == 'w')
  434. {
  435. uOctal += 2;
  436. } else if (aCharacter == 'x')
  437. {
  438. uOctal += 1;
  439. } else if (aCharacter == 's')
  440. {
  441. sIdBit += 4;
  442. }
  443. }
  444. //GROUP
  445. int gOctal = 0;
  446. const char *gArray = [G cStringUsingEncoding:NSASCIIStringEncoding];
  447. stringLength = [G length];
  448. int y;
  449. for( y=0; y<stringLength; y++ )
  450. {
  451. unsigned int aCharacter = gArray[y];
  452. if (aCharacter == 'r')
  453. {
  454. gOctal += 4;
  455. } else if (aCharacter == 'w')
  456. {
  457. gOctal += 2;
  458. } else if (aCharacter == 'x')
  459. {
  460. gOctal += 1;
  461. } else if (aCharacter == 's')
  462. {
  463. gOctal += 2;
  464. }
  465. }
  466. //OTHERS
  467. int z;
  468. int oOctal = 0;
  469. const char *oArray = [O cStringUsingEncoding:NSASCIIStringEncoding];
  470. stringLength = [O length];
  471. for( z=0; z<stringLength; z++ )
  472. {
  473. unsigned int aCharacter = oArray[z];
  474. if (aCharacter == 'r')
  475. {
  476. oOctal += 4;
  477. } else if (aCharacter == 'w')
  478. {
  479. oOctal += 2;
  480. } else if (aCharacter == 'x')
  481. {
  482. oOctal += 1;
  483. }
  484. }
  485. return [NSString stringWithFormat:@"%i%i%i%i", sIdBit, uOctal, gOctal, oOctal];
  486. }
  487. @end
  488. #define OPTION_FLAGS "o:f:b:"
  489. char *progname;
  490. char *path;
  491. static struct option longopts[] = {
  492. { "octal", required_argument, NULL, 'o' },
  493. { "file", required_argument, NULL, 'f' },
  494. { "bootstrap", required_argument, NULL, 'b' },
  495. { NULL, 0, NULL, 0 }
  496. };
  497. int main(int argc, const char * argv[]) {
  498. @autoreleasepool {
  499. setuid(0);
  500. setgid(0);
  501. // insert code here...
  502. progname = basename(argv[0]);
  503. path = dirname(argv[0]);
  504. int flag;
  505. NSString *octalFile = nil;
  506. NSString *debFile = nil;
  507. NSString *bootstrapPath = nil;
  508. while ((flag = getopt_long(argc, argv, OPTION_FLAGS, longopts, NULL)) != -1) {
  509. switch(flag) {
  510. case 'o':
  511. octalFile = [NSString stringWithUTF8String:optarg];
  512. break;
  513. case 'f':
  514. debFile = [NSString stringWithUTF8String:optarg];
  515. break;
  516. case 'b':
  517. bootstrapPath = [NSString stringWithUTF8String:optarg];
  518. break;
  519. }
  520. }
  521. //DLog(@"folder: %@ project: %@", folder, project);
  522. if (octalFile) {
  523. NSString *octal = [HelperClass octalFromSymbols:octalFile];
  524. DLog(@"%@", octal);
  525. }
  526. if (debFile && bootstrapPath) {
  527. DLog(@"\n\nProcessing file: %@\n", debFile);
  528. Package *output = [HelperClass packageForDeb:debFile];
  529. ErrorReturn *safePackage = [output errorReturnForBootstrap:bootstrapPath];
  530. if (safePackage.returnStatus != 0) { //zero is success
  531. if (safePackage.returnStatus == 1) //ovewrwrites, just warnings!
  532. {
  533. NSString *error = [NSString stringWithFormat:@" [WARNING] %@ may overwrite the following files: %@\n\n", debFile.lastPathComponent, [safePackage.overwriteFiles componentsJoinedByString:@"\n"]];
  534. if(![HelperClass shouldContinueWithError:error]){
  535. return -1;
  536. }
  537. } else if (safePackage.returnStatus == 2) //bail!!"
  538. {
  539. return 2;
  540. }
  541. }
  542. //NSString *runPath = [NSString stringWithUTF8String:path];
  543. NSString *pwd = [[HelperClass returnForProcess:@"/bin/pwd"] componentsJoinedByString:@"\n"];
  544. //DLog(@"run path: %@", runPath);
  545. //DLog(@"pwd: %@", pwd);
  546. //DLog(@"%@", output);
  547. //DLog(@"list: %@", output.listfile);
  548. NSFileManager *man = [NSFileManager defaultManager];
  549. NSString *tmpPath = [pwd stringByAppendingPathComponent:output.packageName];
  550. NSString *debian = [tmpPath stringByAppendingPathComponent:@"DEBIAN"];
  551. [man createDirectoryAtPath:tmpPath withIntermediateDirectories:TRUE attributes:nil error:nil];
  552. [HelperClass returnForProcess:[NSString stringWithFormat:@"/usr/local/bin/dpkg -x %@ %@", debFile, tmpPath]];
  553. NSString *listFile = [pwd stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.list", output.packageName]];
  554. NSString *md5s = [pwd stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.md5sums", output.packageName]];
  555. [output.listfile writeToFile:listFile atomically:TRUE encoding:NSUTF8StringEncoding error:nil];
  556. 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];
  557. NSString *outputs = [[HelperClass returnForProcess:runString] componentsJoinedByString:@"\n"];
  558. [outputs writeToFile:md5s atomically:TRUE encoding:NSUTF8StringEncoding error:nil];
  559. [man createDirectoryAtPath:debian withIntermediateDirectories:TRUE attributes:nil error:nil];
  560. [HelperClass returnForProcess:[NSString stringWithFormat:@"/usr/local/bin/dpkg -e %@ %@", debFile, debian]];
  561. //NSString *nextPath = [tmpPath stringByAppendingPathComponent:@"DEBIAN"];
  562. NSArray *files = [man contentsOfDirectoryAtPath:debian error:nil];
  563. [files enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  564. NSString *fullPath = [debian stringByAppendingPathComponent:obj];
  565. if (![obj isEqualToString:@"control"]){
  566. DLog(@"fullPath: %@", fullPath);
  567. NSString *fileName = [NSString stringWithFormat:@"%@.%@", output.packageName, obj];
  568. NSString *newPath = [bootstrapPath stringByAppendingPathComponent:@"Library/dpkg/info"];
  569. newPath = [newPath stringByAppendingPathComponent:fileName];
  570. DLog(@"newPath: %@", newPath);
  571. [man copyItemAtPath:fullPath toPath:newPath error:nil];
  572. } else {
  573. NSMutableString *controlFile = [[NSMutableString alloc] initWithContentsOfFile:fullPath encoding:NSUTF8StringEncoding error:nil];
  574. [controlFile replaceOccurrencesOfString:@"iphoneos-arm" withString:@"appletvos-arm64" options:NSLiteralSearch range:NSMakeRange(0, [controlFile length])];
  575. DLog(@"control file: %@", controlFile);
  576. NSString *statusFile = [bootstrapPath stringByAppendingPathComponent:@"Library/dpkg/status"];
  577. NSMutableString *statusContents = [[NSMutableString alloc] initWithContentsOfFile:statusFile encoding:NSUTF8StringEncoding error:nil];
  578. DLog(@"status contents: %@", statusContents);
  579. [statusContents appendFormat:@"%@\n", controlFile];
  580. [statusContents writeToFile:statusFile atomically:TRUE encoding:NSUTF8StringEncoding error:nil];
  581. }
  582. }];
  583. //finally actually install the package onto the bootstrap
  584. [HelperClass returnForProcess:[NSString stringWithFormat:@"/usr/local/bin/dpkg -x %@ %@", debFile, bootstrapPath]];
  585. //DLog(@"outputs: %@", outputs);
  586. ///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"
  587. }
  588. }
  589. return 0;
  590. }