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