xref: /haiku/src/add-ons/kernel/file_systems/shared/DeviceOpener.cpp (revision d72239d23d37436ce8e7e230056136a858c0ec79)
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