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