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