1 /* 2 * Copyright 2015, Axel Dörfler, axeld@pinc-software.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include "Utility.h" 8 9 #include <errno.h> 10 #include <stdio.h> 11 #include <string.h> 12 13 #include <device/scsi.h> 14 #include <DiskDevice.h> 15 #include <DiskDeviceRoster.h> 16 #include <fs_info.h> 17 #include <Volume.h> 18 19 20 namespace { 21 22 23 status_t 24 IssueDeviceCommand(const char* path, int opcode, void* buffer, 25 size_t bufferSize) 26 { 27 fs_info info; 28 if (fs_stat_dev(dev_for_path(path), &info) == B_OK) { 29 if (strcmp(info.fsh_name, "devfs") != 0) 30 path = info.device_name; 31 } 32 33 int device = open(path, O_RDONLY); 34 if (device < 0) 35 return device; 36 37 status_t status = B_OK; 38 39 if (ioctl(device, opcode, buffer, bufferSize) != 0) { 40 fprintf(stderr, "Failed to process %d on %s: %s\n", opcode, path, 41 strerror(errno)); 42 status = errno; 43 } 44 close(device); 45 return status; 46 } 47 48 49 } // private namespace 50 51 52 namespace Utility { 53 54 55 bool 56 IsReadOnlyVolume(dev_t device) 57 { 58 BVolume volume; 59 status_t status = volume.SetTo(device); 60 if (status != B_OK) { 61 fprintf(stderr, "Failed to get BVolume for device %" B_PRIdDEV 62 ": %s\n", device, strerror(status)); 63 return false; 64 } 65 66 BDiskDeviceRoster roster; 67 BDiskDevice diskDevice; 68 BPartition* partition; 69 status = roster.FindPartitionByVolume(volume, &diskDevice, &partition); 70 if (status != B_OK) { 71 fprintf(stderr, "Failed to get partition for device %" B_PRIdDEV 72 ": %s\n", device, strerror(status)); 73 return false; 74 } 75 76 return partition->IsReadOnly(); 77 } 78 79 80 bool 81 IsReadOnlyVolume(const char* path) 82 { 83 return IsReadOnlyVolume(dev_for_path(path)); 84 } 85 86 87 status_t 88 BlockMedia(const char* path, bool block) 89 { 90 return IssueDeviceCommand(path, B_SCSI_PREVENT_ALLOW, &block, 91 sizeof(block)); 92 } 93 94 95 status_t 96 EjectMedia(const char* path) 97 { 98 return IssueDeviceCommand(path, B_EJECT_DEVICE, NULL, 0); 99 } 100 101 102 BString 103 TranslatePath(const char* originalPath) 104 { 105 BString path = originalPath; 106 107 // TODO: get actual home directory! 108 const char* home = "/boot/home"; 109 path.ReplaceAll("$HOME", home); 110 path.ReplaceAll("${HOME}", home); 111 if (path.StartsWith("~/")) 112 path.ReplaceFirst("~", home); 113 114 return path; 115 } 116 117 118 } // namespace Utility 119