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