]> git.cameronkatri.com Git - snaprestore.git/commitdiff
Initial
authorCameron Katri <me@cameronkatri.com>
Thu, 3 Dec 2020 06:32:25 +0000 (01:32 -0500)
committerCameron Katri <me@cameronkatri.com>
Thu, 3 Dec 2020 06:41:22 +0000 (01:41 -0500)
.gitignore [new file with mode: 0644]
Makefile [new file with mode: 0644]
NSTask.h [new file with mode: 0644]
ent.xml [new file with mode: 0644]
snaprestore.m [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..79aa634
--- /dev/null
@@ -0,0 +1,3 @@
+snaprestore
+compile_commands.json
+.cache
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..90edba3
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,13 @@
+CC     = aarch64-apple-darwin-clang
+STRIP  = aarch64-apple-darwin-strip
+LDID   = ldid
+CFLAGS = -arch arm64  -isysroot /home/cameron/Documents/SDK/iPhoneOS14.2.sdk -miphoneos-version-min=13.0 -isystem /home/cameron/Documents/Procursus/build_base/iphoneos-arm64/1600/usr/include -isystem /home/cameron/Documents/Procursus/build_base/iphoneos-arm64/1600/usr/local/include -F/home/cameron/Documents/Procursus/build_base/iphoneos-arm64/1600/System/Library/Frameworks
+
+all: snaprestore
+
+snaprestore: snaprestore.m ent.xml NSTask.h
+       $(CC) $(CFLAGS) -o snaprestore snaprestore.m -framework IOKit -framework Foundation -fobjc-arc
+       $(LDID) -Sent.xml snaprestore
+
+clean: 
+       rm -f snaprestore
diff --git a/NSTask.h b/NSTask.h
new file mode 100644 (file)
index 0000000..7b51c23
--- /dev/null
+++ b/NSTask.h
@@ -0,0 +1,43 @@
+/*
+* This header is generated by classdump-dyld 1.0
+* on Thursday, January 25, 2018 at 11:20:38 PM Eastern European Standard Time
+* Operating System: Version 11.1.2 (Build 15B202)
+* Image Source: /System/Library/Frameworks/Foundation.framework/Foundation
+* classdump-dyld is licensed under GPLv3, Copyright © 2013-2016 by Elias Limneos.
+*/
+
+#import <Foundation/Foundation.h>
+
+@interface NSTask : NSObject
+
+@property (copy) NSURL * executableURL;
+@property (copy) NSArray * arguments;
+@property (copy) NSDictionary * environment;
+@property (copy) NSURL * currentDirectoryURL;
+@property (retain) id standardInput;
+@property (retain) id standardOutput;
+@property (retain) id standardError;
+@property (readonly) int processIdentifier;
+@property (getter=isRunning, readonly) BOOL running;
+@property (readonly) int terminationStatus;
+@property (readonly) long long terminationReason;
+@property (copy) id terminationHandler;
+@property (assign) long long qualityOfService;
++ (id)currentTaskDictionary;
++ (id)launchedTaskWithDictionary:(id)arg1;
++ (id)launchedTaskWithLaunchPath:(id)arg1 arguments:(id)arg2;
++ (id)launchedTaskWithExecutableURL:(id)arg1 arguments:(id)arg2 error:(out id*)arg3 terminationHandler:(/*^block*/id)arg4;
+- (void)waitUntilExit;
+- (id)currentDirectoryPath;
+- (void)setCurrentDirectoryPath:(id)arg1;
+- (id)launchPath;
+- (void)setLaunchPath:(id)arg1;
+- (void)launch;
+- (BOOL)launchAndReturnError:(id*)arg1;
+- (void)interrupt;
+- (long long)suspendCount;
+- (BOOL)suspend;
+- (BOOL)resume;
+- (void)terminate;
+- (NSArray *)arguments;
+@end
diff --git a/ent.xml b/ent.xml
new file mode 100644 (file)
index 0000000..ea437c4
--- /dev/null
+++ b/ent.xml
@@ -0,0 +1,17 @@
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>platform-application</key>
+       <true/>
+       <key>com.apple.private.security.no-container</key>
+       <true/>
+       <key>com.apple.private.skip-library-validation</key>
+       <true/>
+       <key>com.apple.private.apfs.revert-to-snapshot</key>
+       <true/>
+       <key>com.apple.private.security.disk-device-access</key>
+       <true/>
+       <key>com.apple.private.vfs.snapshot</key>
+       <true/>
+</dict>
+</plist>
diff --git a/snaprestore.m b/snaprestore.m
new file mode 100644 (file)
index 0000000..96e7b4d
--- /dev/null
@@ -0,0 +1,112 @@
+#import <Foundation/Foundation.h>
+#import <Foundation/NSFileManager.h>
+#import <IOKit/IOKitLib.h>
+#import <sys/snapshot.h>
+#import <getopt.h>
+#import "NSTask.h"
+
+void usage(char *name) {
+       printf(
+               "Usage: %s [volume] [snapshot]\n", name);
+}
+
+NSString *bootsnapshot() {
+       const io_registry_entry_t chosen = IORegistryEntryFromPath(0, "IODeviceTree:/chosen");
+       const NSData *data = (__bridge const NSData *)IORegistryEntryCreateCFProperty(chosen, (__bridge CFStringRef)@"boot-manifest-hash", kCFAllocatorDefault, 0);
+       IOObjectRelease(chosen);
+
+       NSMutableString *manifestHash = [NSMutableString stringWithString:@""]; 
+       NSUInteger len = [data length];
+       Byte *buf = (Byte*)malloc(len);
+       memcpy(buf, [data bytes], len);
+       int buf2;
+       for (buf2 = 0; buf2 <= 19; buf2++) {
+               [manifestHash appendFormat:@"%02X", buf[buf2]];
+       }
+       // add com.apple.os.update-
+       return [NSString stringWithFormat:@"%@%@", @"com.apple.os.update-", manifestHash];
+}
+
+int restore(const char *vol, const char *snap) {
+       int fd = open(vol, O_RDONLY, 0);
+
+       int ret = fs_snapshot_revert(fd, snap, 0);
+       return ret;
+}
+
+int mount(const char *vol, const char *snap, const char *mnt) {
+       int fd = open(vol, O_RDONLY, 0);
+
+       BOOL isDir;
+       NSFileManager *fileManager = [NSFileManager defaultManager]; 
+               if(![fileManager fileExistsAtPath:[NSString stringWithUTF8String:mnt] isDirectory:&isDir])
+                       if(![fileManager createDirectoryAtPath:[NSString stringWithUTF8String:mnt] withIntermediateDirectories:YES attributes:nil error:NULL])
+                               NSLog(@"Error: Create folder failed %s", mnt);
+
+       int ret = fs_snapshot_mount(fd, mnt, snap, 0);
+       
+       return ret;
+}
+
+NSMutableSet *findApps(const char *root, const char *mnt) {
+       NSMutableString *rootApplications = [NSMutableString stringWithUTF8String:root];
+       rootApplications = [[rootApplications stringByAppendingString:@"/Applications"] mutableCopy];
+
+       NSMutableString *mntApplications = [NSMutableString stringWithUTF8String:mnt];
+       mntApplications = [[mntApplications stringByAppendingString:@"/Applications"] mutableCopy];
+
+       NSArray *rootApps = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:rootApplications error:nil];
+       NSArray *mntApps = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:mntApplications error:nil];
+
+       NSMutableSet *ret = [[NSMutableSet alloc] init];
+       for (NSString *app in rootApps) {
+               if (![mntApps containsObject:app]) {
+                       [ret addObject:[@"/Applications/" stringByAppendingString:app]];
+               }
+       }
+
+       return ret;
+}
+
+int rename(const char *vol, const char *snap) {
+       int fd = open(vol, O_RDONLY, 0);
+
+       int ret = fs_snapshot_rename(fd, snap, [bootsnapshot() UTF8String], 0);
+       return ret;
+}
+
+int main(int argc, char *argv[]) {
+       if (argc != 3) {
+               usage(argv[0]);
+               return 0;
+       }
+
+       char *vol = argv[1];
+       char *snap = argv[2];
+       char *mnt = "/tmp/rootfsmnt";
+
+       printf("Restoring snapshot %s...\n", snap);
+       restore(vol, snap);
+       printf("Restored snapshot...\n");
+       printf("Mounting rootfs...\n");
+       mount(vol, snap, mnt);
+       printf("Mounted %s at %s\n", snap, mnt);
+       NSMutableSet *appSet = findApps(vol, mnt);
+       if (appSet) {
+               printf("Refreshing icon cache...\n");
+               NSMutableArray *argArray = [[NSMutableArray alloc] init];
+               for (NSString *app in appSet) {
+                       [argArray addObject:@"-u"];
+                       [argArray addObject:app];
+               }
+               NSTask *task = [[NSTask alloc] init];
+               [task setLaunchPath:@"/usr/bin/uicache"];
+               [task setArguments:argArray];
+               [task launch];
+               [task waitUntilExit];
+       }
+       printf("Renaming snapshot...\n");
+       rename(vol, snap);
+       printf("Restoring %s on %s has succeeded\n", snap, vol); 
+       return 0;
+}