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