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