Skip to content
This repository has been archived by the owner on Dec 29, 2022. It is now read-only.

Commit

Permalink
Attempt running ASR multiple times on failure (#66)
Browse files Browse the repository at this point in the history
* Attempt running ASR multiple times (configurable in the profile) on failure.

* Document the ASRAttempts configuration option in the README file.

* fix nits.
  • Loading branch information
howiekaye authored and tburgin committed May 2, 2019
1 parent 8a7cae6 commit 941e656
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 35 deletions.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,16 @@ sudo defaults write /Library/Preferences/com.google.corp.restor.plist DiskFilter
"(bsdName != 'disk3s2')"
```

### ASRAttempts

__Optional__

Set how many times Restor should attempt to run ASR until it runs successfully.
This may help with issues where the Volume is not unmountable by ASR due to some
external process (ie spotlight) holding onto it. Defaults to 1.

`sudo defaults write /Library/Preferences/com.google.corp.restor.plist ASRAttempts -int 5`

## 10.13 and APFS Note

In order to restore an APFS 10.13 DMG to a machine, the host machine running
Expand Down
79 changes: 44 additions & 35 deletions restord/ImageSessionServer.m
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
// GUID Partition Table UUID Constants
NSString * const kGPTAPFSUUID = @"7C3457EF-0000-11AA-AA11-00306543ECAC";
NSString * const kGPTCoreStorageUUID = @"53746F72-6167-11AA-AA11-00306543ECAC";
static NSString * const kPreferenceDomain = @"com.google.corp.restor";
static NSString * const kASRAttempts = @"ASRAttempts";

@interface ImageSessionServer ()

Expand Down Expand Up @@ -102,8 +104,6 @@ - (void)dealloc {
}

- (void)beginImaging {
[self unmountDisk:self.diskRef withOptions:kDADiskUnmountOptionWhole];

// Remove any top level recovery partitions.
[self removeRecovery];

Expand Down Expand Up @@ -260,39 +260,48 @@ - (NSString *)apfsOSDisk {
- (int)applyImage {
NSString *path = self.image.localURL.path;

self.asr = [[NSTask alloc] init];
self.asr.launchPath = @"/usr/sbin/asr";
self.asr.arguments = @[ @"restore",
@"--buffersize",
@"16m",
@"--source",
path,
@"--target",
self.destination.path,
@"--erase",
@"--noprompt",
@"--noverify",
@"--puppetstrings" ];

// Set task environment.
NSMutableDictionary *environment = [[[NSProcessInfo processInfo] environment] mutableCopy];
environment[@"NSUnbufferedIO"] = @"YES";
self.asr.environment = environment;

// Create output pipe & file handle.
self.asr.standardError = self.asr.standardOutput = [[NSPipe alloc] init];
NSFileHandle *outputFh = [self.asr.standardOutput fileHandleForReading];
outputFh.readabilityHandler = ^(NSFileHandle *h) {
NSData *availableData = [h availableData];
[self processOutput:(NSData *)availableData];
};

// Launch and wait for exit.
[self.asr launch];
[self.asr waitUntilExit];

// Clear readability handler or the file handle is never released.
outputFh.readabilityHandler = nil;
int retries = (int)[[[NSUserDefaults alloc] initWithSuiteName:kPreferenceDomain] integerForKey:kASRAttempts];
if (retries <= 0) retries = 1;
NSLog(@"Will attempt ASR up to %d times.", retries);
for (int i = 0; i < retries; ++i) {
[self unmountDisk:self.diskRef withOptions:kDADiskUnmountOptionWhole];

self.asr = [[NSTask alloc] init];
self.asr.launchPath = @"/usr/sbin/asr";
self.asr.arguments = @[ @"restore",
@"--buffersize",
@"16m",
@"--source",
path,
@"--target",
self.destination.path,
@"--erase",
@"--noprompt",
@"--noverify",
@"--puppetstrings" ];

// Set task environment.
NSMutableDictionary *environment = [[[NSProcessInfo processInfo] environment] mutableCopy];
environment[@"NSUnbufferedIO"] = @"YES";
self.asr.environment = environment;

// Create output pipe & file handle.
self.asr.standardError = self.asr.standardOutput = [[NSPipe alloc] init];
NSFileHandle *outputFh = [self.asr.standardOutput fileHandleForReading];
outputFh.readabilityHandler = ^(NSFileHandle *h) {
NSData *availableData = [h availableData];
[self processOutput:(NSData *)availableData];
};

// Launch and wait for exit.
[self.asr launch];
[self.asr waitUntilExit];

// Clear readability handler or the file handle is never released.
outputFh.readabilityHandler = nil;
if (self.asr && self.asr.terminationStatus == 0) break;
NSLog(@"%@ ASR attempt %d exit code: %d", self, i + 1, self.asr.terminationStatus);
}
return self.asr ? self.asr.terminationStatus : -1;
}

Expand Down

0 comments on commit 941e656

Please sign in to comment.