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
DeviceOpener(const char * device,int mode)16 DeviceOpener::DeviceOpener(const char* device, int mode)
17 :
18 fBlockCache(NULL)
19 {
20 Open(device, mode);
21 }
22
23
DeviceOpener(int fd,int mode)24 DeviceOpener::DeviceOpener(int fd, int mode)
25 :
26 fBlockCache(NULL)
27 {
28 Open(fd, mode);
29 }
30
31
~DeviceOpener()32 DeviceOpener::~DeviceOpener()
33 {
34 if (fDevice >= 0){
35 RemoveCache(false);
36 close(fDevice);
37 }
38 }
39
40
41 int
Open(const char * device,int mode)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
Open(int fd,int mode)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*
InitCache(off_t numBlocks,uint32 blockSize)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
RemoveCache(bool allowWrites)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
Keep()103 DeviceOpener::Keep()
104 {
105 fDevice = -1;
106 }
107
108
109 status_t
GetSize(off_t * _size,uint32 * _blockSize)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