Skip to content

Commit b9e967a

Browse files
committed
Handle locked disks fixes #26
1 parent 52f07f6 commit b9e967a

File tree

3 files changed

+87
-7
lines changed

3 files changed

+87
-7
lines changed

TmpDisk/TmpDiskManager.swift

Lines changed: 75 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -258,20 +258,88 @@ class TmpDiskManager {
258258
if volume.tmpFs {
259259
try FileManager.default.removeItem(atPath: volume.path())
260260
}
261-
} catch {
262-
print(error)
261+
DispatchQueue.main.async {
262+
self.volumes.remove(volume)
263+
}
264+
265+
if recreate {
266+
self.createTmpDisk(volume: volume, onCreate: {_ in })
267+
}
268+
} catch let error as NSError {
269+
if error.code == fBsyErr {
270+
DispatchQueue.main.async {
271+
self.ejectErrorDiskInUse(name: volume.name, recreate: recreate)
272+
}
273+
} else {
274+
DispatchQueue.main.async {
275+
self.ejectError(name: volume.name)
276+
}
277+
}
263278
}
264279

265-
DispatchQueue.main.async {
266-
self.volumes.remove(volume)
280+
group.leave()
281+
}
282+
283+
}
284+
285+
func forceEject(name: String, recreate: Bool) {
286+
guard let volume = self.volumes.first(where: { name == $0.name }) else {
287+
return
288+
}
289+
290+
let task = Process()
291+
task.launchPath = "/sbin/umount"
292+
293+
let command = volume.path()
294+
task.arguments = ["-f", command]
295+
296+
task.terminationHandler = { process in
297+
if process.terminationStatus != 0 {
298+
DispatchQueue.main.async {
299+
self.ejectError(name: name)
300+
}
301+
return
267302
}
268303

269-
if recreate {
270-
self.createTmpDisk(volume: volume, onCreate: {_ in })
304+
DispatchQueue.main.async {
305+
self.volumes.remove(volume)
306+
307+
if recreate {
308+
// We've force ejected so recreate the TmpDisk
309+
self.createTmpDisk(volume: volume, onCreate: {_ in })
310+
}
271311
}
272-
group.leave()
273312
}
274313

314+
if #available(macOS 10.13, *) {
315+
do {
316+
try task.run()
317+
} catch {
318+
print(error)
319+
}
320+
} else {
321+
task.launch()
322+
}
323+
}
324+
325+
func ejectErrorDiskInUse(name: String, recreate: Bool) {
326+
let alert = NSAlert()
327+
alert.messageText = String(format: NSLocalizedString("The volume \"%@\" wasn't ejected because one or more programs may be using it", comment: ""), name)
328+
alert.informativeText = NSLocalizedString("To eject the disk immediately, hit the Force Eject button", comment: "")
329+
alert.alertStyle = .warning
330+
alert.addButton(withTitle: NSLocalizedString("Force Eject", comment: ""))
331+
alert.addButton(withTitle: "Cancel")
332+
if alert.runModal() == .alertFirstButtonReturn {
333+
self.forceEject(name: name, recreate: recreate)
334+
}
335+
}
336+
337+
func ejectError(name: String) {
338+
let alert = NSAlert()
339+
alert.messageText = String(format: NSLocalizedString("Failed to eject \"%@\"", comment: ""), name)
340+
alert.alertStyle = .warning
341+
alert.addButton(withTitle: "OK")
342+
alert.runModal()
275343
}
276344

277345
/*

TmpDisk/en.lproj/Localizable.strings

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,13 @@
1717
"Your TmpDisk must have a name" = "Your TmpDisk must have a name";
1818
"A volume with this name already exists" = "A volume with this name already exists";
1919
"Size must be a number of megabytes > 0" = "Size must be a number of megabytes > 0";
20+
"Size must be a number of gigabytes >= 0.01" = "Size must be a number of gigabytes >= 0.01";
2021
"Failed to create TmpDisk" = "Failed to create TmpDisk";
2122
"Preferences" = "Preferences";
2223
"You can't change the root volume while tmpFS disks are mounted." = "You can't change the root volume while tmpFS disks are mounted.";
2324
"Icon must be square" = "Icon must be square";
2425
"Could not convert image to icon" = "Could not convert image to icon";
26+
"Failed to eject \"%@\"" = "Failed to eject \"%@\"";
27+
"The volume \"%@\" wasn't ejected because one or more programs may be using it" = "The volume \"%@\" wasn't ejected because one or more programs may be using it";
28+
"To eject the disk immediately, hit the Force Eject button" = "To eject the disk immediately, hit the Force Eject button";
29+
"Force Eject" = "Force Eject";

TmpDisk/zh-Hans.lproj/Localizable.strings

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@
1717
"Your TmpDisk must have a name" = "你的 TmpDisk 必须有一个名字";
1818
"A volume with this name already exists" = "已存在同名的卷";
1919
"Size must be a number of megabytes > 0" = "大小必须是大于 0 的兆字节数";
20+
"Size must be a number of gigabytes >= 0.01" = "Size must be a number of gigabytes >= 0.01";
2021
"Failed to create TmpDisk" = "创建 TmpDisk 失败";
2122
"Preferences" = "Preferences";
2223
"You can't change the root volume while tmpFS disks are mounted." = "You can't change the root volume while tmpFS disks are mounted.";
24+
"Icon must be square" = "Icon must be square";
25+
"Could not convert image to icon" = "Could not convert image to icon";
26+
"Failed to eject \"%@\"" = "Failed to eject \"%@\"";
27+
"The volume \"%@\" wasn't ejected because one or more programs may be using it" = "The volume \"%@\" wasn't ejected because one or more programs may be using it";
28+
"To eject the disk immediately, hit the Force Eject button" = "To eject the disk immediately, hit the Force Eject button";
29+
"Force Eject" = "Force Eject";

0 commit comments

Comments
 (0)