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