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