1 /* 2 * Copyright 2008-2010, Axel Dörfler, axeld@pinc-software.de. 3 * All rights reserved. Distributed under the terms of the MIT License. 4 */ 5 6 7 #include "system_dependencies.h" 8 #include "file_systems/DeviceOpener.h" 9 10 11 DeviceOpener::DeviceOpener(const char* device, int mode) 12 : 13 fBlockCache(NULL) 14 { 15 Open(device, mode); 16 } 17 18 19 DeviceOpener::DeviceOpener(int fd, int mode) 20 : 21 fBlockCache(NULL) 22 { 23 Open(fd, mode); 24 } 25 26 27 DeviceOpener::~DeviceOpener() 28 { 29 if (fDevice >= 0){ 30 RemoveCache(false); 31 close(fDevice); 32 } 33 } 34 35 36 int 37 DeviceOpener::Open(const char* device, int mode) 38 { 39 fDevice = open(device, mode | O_NOCACHE); 40 if (fDevice < 0) 41 fDevice = errno; 42 43 if (fDevice < 0 && _IsReadWrite(mode)) { 44 return Open(device, O_RDONLY | O_NOCACHE); 45 } 46 47 if (fDevice >= 0) { 48 fMode = mode; 49 if (_IsReadWrite(mode)) { 50 device_geometry geometry; 51 if (!ioctl(fDevice, B_GET_GEOMETRY, &geometry, 52 sizeof(device_geometry))) 53 { 54 if (geometry.read_only) { 55 close(fDevice); 56 return Open(device, O_RDONLY | O_NOCACHE); 57 } 58 } 59 } 60 } 61 return fDevice; 62 } 63 64 65 int 66 DeviceOpener::Open(int fd, int mode) 67 { 68 fDevice = dup(fd); 69 if (fDevice < 0) 70 return errno; 71 72 fMode = mode; 73 74 return fDevice; 75 } 76 77 78 void* 79 DeviceOpener::InitCache(off_t numBlocks, uint32 blockSize) 80 { 81 return fBlockCache = block_cache_create(fDevice, numBlocks, blockSize, 82 IsReadOnly()); 83 } 84 85 86 void 87 DeviceOpener::RemoveCache(bool allowWrites) 88 { 89 if (fBlockCache == NULL) 90 return; 91 92 block_cache_delete(fBlockCache, allowWrites); 93 fBlockCache = NULL; 94 } 95 96 97 void 98 DeviceOpener::Keep() 99 { 100 fDevice = -1; 101 } 102 103 104 status_t 105 DeviceOpener::GetSize(off_t* _size, uint32* _blockSize) 106 { 107 device_geometry geometry; 108 if (ioctl(fDevice, B_GET_GEOMETRY, &geometry, 109 sizeof(device_geometry)) < 0) { 110 // maybe it's just a file 111 struct stat stat; 112 if (fstat(fDevice, &stat) < 0) 113 return B_ERROR; 114 115 if (_size) 116 *_size = stat.st_size; 117 if (_blockSize) // that shouldn't cause us any problems 118 *_blockSize = 512; 119 120 return B_OK; 121 } 122 123 if (_size) { 124 *_size = 1ULL * geometry.head_count * geometry.cylinder_count 125 * geometry.sectors_per_track * geometry.bytes_per_sector; 126 } 127 if (_blockSize) 128 *_blockSize = geometry.bytes_per_sector; 129 130 return B_OK; 131 } 132