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