xref: /haiku/src/tools/fs_shell/unistd.cpp (revision 1214ef1b2100f2b3299fc9d8d6142e46f70a4c3f)
1 /*
2  * Copyright 2007, Ingo Weinhold, bonefish@cs.tu-berlin.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 #include "compatibility.h"
7 
8 #include "fssh_unistd.h"
9 
10 #include <errno.h>
11 #include <stdarg.h>
12 #include <unistd.h>
13 
14 #include <SupportDefs.h>
15 
16 #include "fssh_drivers.h"
17 #include "fssh_errno.h"
18 
19 #ifdef __BEOS__
20 #	include <Drivers.h>
21 #else
22 #	if defined(HAIKU_HOST_PLATFORM_FREEBSD) \
23 		|| defined(HAIKU_HOST_PLATFORM_DARWIN)
24 #		include <sys/ioctl.h>
25 #	else
26 		// the (POSIX) correct place of definition for ioctl()
27 #		include <stropts.h>
28 #	endif
29 
30 #	if defined(HAIKU_HOST_PLATFORM_LINUX)
31 #		include <linux/hdreg.h>
32 #		include <linux/fs.h>
33 #	endif
34 #endif
35 
36 
37 #ifndef __BEOS__
38 	// Defined in libroot_build.so.
39 	extern "C" int _kern_dup(int fd);
40 	extern "C" status_t _kern_close(int fd);
41 #endif
42 
43 
44 #ifdef HAIKU_HOST_PLATFORM_LINUX
45 
46 static bool
47 test_size(int fd, off_t size)
48 {
49 	char buffer[1];
50 
51 	if (size == 0)
52 		return true;
53 
54 	if (lseek(fd, size - 1, SEEK_SET) < 0)
55 		return false;
56 
57 	return (read(fd, &buffer, 1) == 1);
58 }
59 
60 
61 static off_t
62 get_partition_size(int fd, off_t maxSize)
63 {
64 	// binary search
65 	off_t lower = 0;
66 	off_t upper = maxSize;
67 	while (lower < upper) {
68 		off_t mid = (lower + upper + 1) / 2;
69 		if (test_size(fd, mid))
70 			lower = mid;
71 		else
72 			upper = mid - 1;
73 	}
74 
75 	return lower;
76 }
77 
78 #endif // HAIKU_HOST_PLATFORM_LINUX
79 
80 
81 int
82 fssh_dup(int fd)
83 {
84 	// Use the _kern_dup() defined in libroot on BeOS incompatible systems.
85 	// Required for proper attribute emulation support.
86 	#if __BEOS__
87 		return dup(fd);
88 	#else
89 		int result = _kern_dup(fd);
90 		if (result < 0) {
91 			fssh_set_errno(result);
92 			return -1;
93 		}
94 		return result;
95 	#endif
96 }
97 
98 
99 int
100 fssh_close(int fd)
101 {
102 	// Use the _kern_close() defined in libroot on BeOS incompatible systems.
103 	// Required for proper attribute emulation support.
104 	#if __BEOS__
105 		return close(fd);
106 	#else
107 		return _kern_close(fd);
108 	#endif
109 }
110 
111 
112 int
113 fssh_unlink(const char *name)
114 {
115 	return unlink(name);
116 }
117 
118 
119 int
120 fssh_ioctl(int fd, unsigned long op, ...)
121 {
122 	status_t error = B_BAD_VALUE;
123 	va_list list;
124 
125 	// count arguments
126 
127 	va_start(list, op);
128 
129 	switch (op) {
130 		case FSSH_B_GET_GEOMETRY:
131 		{
132 			fssh_device_geometry *geometry
133 				= va_arg(list, fssh_device_geometry*);
134 
135 			#ifdef __BEOS__
136 				device_geometry systemGeometry;
137 				if (ioctl(fd, B_GET_GEOMETRY, &systemGeometry) == 0) {
138 					geometry->bytes_per_sector
139 						= systemGeometry.bytes_per_sector;
140 					geometry->sectors_per_track
141 						= systemGeometry.sectors_per_track;
142 					geometry->cylinder_count = systemGeometry.cylinder_count;
143 					geometry->head_count = systemGeometry.head_count;
144 					geometry->device_type = systemGeometry.device_type;
145 					geometry->removable = systemGeometry.removable;
146 					geometry->read_only = systemGeometry.read_only;
147 					geometry->write_once = systemGeometry.write_once;
148 					error = B_OK;
149 				} else
150 					error = errno;
151 
152 			#elif defined(HAIKU_HOST_PLATFORM_LINUX)
153 				struct hd_geometry hdGeometry;
154 				// BLKGETSIZE and BLKGETSIZE64 don't seem to work for
155 				// partitions. So we get the device geometry (there only seems
156 				// to be HDIO_GETGEO, which is kind of obsolete, BTW), and
157 				// get the partition size via binary search.
158 				if (ioctl(fd, HDIO_GETGEO, &hdGeometry) == 0) {
159 					int blockSize = 512;
160 					if (hdGeometry.heads == 0) {
161 						off_t size;
162 						if (ioctl(fd, BLKGETSIZE64, &size) == 0) {
163 							off_t blocks = size / blockSize;
164 							uint32_t heads = (blocks + ULONG_MAX - 1)
165 								/ ULONG_MAX;
166 							if (heads == 0)
167 								heads = 1;
168 
169 							geometry->head_count = heads;
170 							geometry->cylinder_count = blocks / heads;
171 							geometry->sectors_per_track = 1;
172 							error = B_OK;
173 						} else
174 							error = errno;
175 					} else {
176 						off_t bytesPerCylinder = (off_t)hdGeometry.heads
177 							* hdGeometry.sectors * 512;
178 						off_t deviceSize = bytesPerCylinder * hdGeometry.cylinders;
179 						off_t partitionSize = get_partition_size(fd, deviceSize);
180 
181 						geometry->head_count = hdGeometry.heads;
182 						geometry->cylinder_count = partitionSize / bytesPerCylinder;
183 						geometry->sectors_per_track = hdGeometry.sectors;
184 						error = B_OK;
185 					}
186 
187 					if (error == B_OK) {
188 						// TODO: Get the real values...
189 						geometry->bytes_per_sector = blockSize;
190 						geometry->device_type = FSSH_B_DISK;
191 						geometry->removable = false;
192 						geometry->read_only = false;
193 						geometry->write_once = false;
194 					}
195 				} else
196 					error = errno;
197 
198 			#else
199 				// Not implemented for this platform, i.e. we won't be able to
200 				// deal with block devices.
201 			#endif
202 
203 			break;
204 		}
205 
206 		case FSSH_B_FLUSH_DRIVE_CACHE:
207 		{
208 			#ifdef __BEOS__
209 				if (ioctl(fd, B_FLUSH_DRIVE_CACHE) == 0)
210 					error = B_OK;
211 				else
212 					error = errno;
213 			#else
214 				error = B_OK;
215 			#endif
216 
217 			break;
218 		}
219 
220 		case 10000:	// IOCTL_FILE_UNCACHED_IO
221 		{
222 			#ifdef __BEOS__
223 				if (ioctl(fd, 10000) == 0)
224 					error = B_OK;
225 				else
226 					error = errno;
227 			#else
228 				error = B_OK;
229 			#endif
230 
231 			break;
232 		}
233 	}
234 
235 	va_end(list);
236 
237 	if (error != B_OK) {
238 		fssh_set_errno(error);
239 		return -1;
240 	}
241 	return 0;
242 }
243 
244 
245 fssh_ssize_t
246 fssh_read(int fd, void *buffer, fssh_size_t count)
247 {
248 	return read(fd, buffer, count);
249 }
250 
251 
252 fssh_ssize_t
253 fssh_read_pos(int fd, fssh_off_t pos, void *buffer, fssh_size_t count)
254 {
255 	return read_pos(fd, pos, buffer, count);
256 }
257 
258 
259 fssh_ssize_t
260 fssh_write(int fd, const void *buffer, fssh_size_t count)
261 {
262 	return write(fd, buffer, count);
263 }
264 
265 
266 fssh_ssize_t
267 fssh_write_pos(int fd, fssh_off_t pos, const void *buffer, fssh_size_t count)
268 {
269 	return write_pos(fd, pos, buffer, count);
270 }
271 
272 
273 fssh_gid_t
274 fssh_getegid(void)
275 {
276 	return 0;
277 }
278 
279 
280 fssh_uid_t
281 fssh_geteuid(void)
282 {
283 	return 0;
284 }
285 
286 
287 fssh_gid_t
288 fssh_getgid(void)
289 {
290 	return 0;
291 }
292 
293 
294 #if 0
295 int
296 fssh_getgroups(int groupSize, fssh_gid_t groupList[])
297 {
298 }
299 #endif	// 0
300 
301 
302 fssh_uid_t
303 fssh_getuid(void)
304 {
305 	return 0;
306 }
307