Skip to content

Instantly share code, notes, and snippets.

@Dev1an
Created August 26, 2020 15:56
Show Gist options
  • Select an option

  • Save Dev1an/214e5f99a191f7e9f713c36cb8fc587b to your computer and use it in GitHub Desktop.

Select an option

Save Dev1an/214e5f99a191f7e9f713c36cb8fc587b to your computer and use it in GitHub Desktop.
Recover lost ARW files from an exFAT drive
import Foundation
let minimumFileSize = 24_000_000
let separator = [UInt8](repeating: 0, count: 50)
let arwPrefix: [UInt8] = [0x49, 0x49, 0x2A, 0, 0x08, 0, 0, 0, 0x15, 0, 0xFE, 0, 0x04, 0, 0x01, 0, 0, 0, 0x01, 0, 0, 0, 0x03, 0x01, 0x03, 0, 0x01, 0, 0, 0, 0x06, 0]
let disc = try Data(contentsOf: URL(fileURLWithPath: "path-to-drive-image"))
var cursor = disc.startIndex
var fileNames = Set<String>()
while cursor + minimumFileSize < disc.endIndex {
guard let separator = disc.firstRange(of: separator, in: (cursor + minimumFileSize)...) else {
fatalError("no end of file found")
}
let timestamp = String(bytes: disc[(346..<365) + cursor], encoding: .ascii)!
print(timestamp, cursor, separator.startIndex - cursor)
let convertedTime = timestamp.replacingOccurrences(of: ":", with: "-")
var counter = 1
while fileNames.contains(convertedTime + " \(counter)") {
counter += 1
}
let fileName = convertedTime + " \(counter)"
fileNames.insert(fileName)
try disc[cursor..<separator.startIndex].write(to: URL(fileURLWithPath: "~/Downloads/RecoveredPhotos/\(fileName).ARW"))
cursor = disc.firstRange(of: arwPrefix, in: separator.endIndex...)?.startIndex ?? disc.endIndex
}
extension Range where Bound == Int {
static func + (_ range: Self, _ offset: Int) -> Self {
return (range.lowerBound + offset) ..< (range.upperBound + offset)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment