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