1/* 2 This file contains some routines that are #ifdef'ed based on what 3 system you're on. Currently it supports the BeOS and Unix. It 4 could be extended to support Windows NT but their posix support 5 is such a joke that it would probably be a real pain in the arse. 6 7 THIS CODE COPYRIGHT DOMINIC GIAMPAOLO. NO WARRANTY IS EXPRESSED 8 OR IMPLIED. YOU MAY USE THIS CODE AND FREELY DISTRIBUTE IT FOR 9 NON-COMMERCIAL USE AS LONG AS THIS NOTICE REMAINS ATTACHED. 10 11 FOR COMMERCIAL USE, CONTACT DOMINIC GIAMPAOLO (dbg@be.com). 12 13 Dominic Giampaolo 14 dbg@be.com 15*/ 16#include "compat.h" 17 18#include <stdarg.h> 19#include <stdio.h> 20#include <fcntl.h> 21#include <unistd.h> 22#include <sys/ioctl.h> 23#include <sys/stat.h> 24 25#include "stat_util.h" 26 27// Linux support 28#ifdef HAIKU_HOST_PLATFORM_LINUX 29# include <linux/hdreg.h> 30#endif // HAIKU_HOST_PLATFORM_LINUX 31 32 33// Let the FS think, we are the root user. 34uid_t 35geteuid() 36{ 37 return 0; 38} 39 40 41gid_t 42getegid() 43{ 44 return 0; 45} 46 47 48int 49device_is_read_only(const char *device) 50{ 51#ifdef unix 52 return 0; /* XXXdbg should do an ioctl or something */ 53#else 54 int fd; 55 device_geometry dg; 56 57 fd = open(device, O_RDONLY); 58 if (ioctl(fd, B_GET_GEOMETRY, &dg) < 0) 59 return 0; 60 61 close(fd); 62 63 return dg.read_only; 64#endif 65} 66 67int 68get_device_block_size(int fd) 69{ 70#ifdef unix 71 return 512; /* XXXdbg should do an ioctl or something */ 72#else 73 struct stat st; 74 device_geometry dg; 75 76 if (ioctl(fd, B_GET_GEOMETRY, &dg) < 0) { 77 if (fstat(fd, &st) < 0 || S_ISDIR(st.st_mode)) 78 return 0; 79 80 return 512; /* just assume it's a plain old file or something */ 81 } 82 83 return dg.bytes_per_sector; 84#endif 85} 86 87fs_off_t 88get_num_device_blocks(int fd) 89{ 90#ifdef unix 91 struct stat st; 92 93 fstat(fd, &st); /* XXXdbg should be an ioctl or something */ 94 95 return st.st_size / get_device_block_size(fd); 96#else 97 struct stat st; 98 device_geometry dg; 99 100 if (ioctl(fd, B_GET_GEOMETRY, &dg) >= 0) { 101 return (fs_off_t)dg.cylinder_count * 102 (fs_off_t)dg.sectors_per_track * 103 (fs_off_t)dg.head_count; 104 } 105 106 /* if the ioctl fails, try just stat'ing in case it's a regular file */ 107 if (fstat(fd, &st) < 0) 108 return 0; 109 110 return st.st_size / get_device_block_size(fd); 111#endif 112} 113 114int 115device_is_removeable(int fd) 116{ 117#ifdef unix 118 return 0; /* XXXdbg should do an ioctl or something */ 119#else 120 device_geometry dg; 121 122 if (ioctl(fd, B_GET_GEOMETRY, &dg) < 0) { 123 return 0; 124 } 125 126 return dg.removable; 127#endif 128} 129 130#if (defined(__BEOS__) || defined(__HAIKU__)) && !defined(USER) 131#include "scsi.h" 132#endif 133 134int 135lock_removeable_device(int fd, bool on_or_off) 136{ 137#if defined(unix) || defined(USER) 138 return 0; /* XXXdbg should do an ioctl or something */ 139#else 140 return ioctl(fd, B_SCSI_PREVENT_ALLOW, &on_or_off); 141#endif 142} 143 144 145 146 147#if (!defined(__BEOS__) && !defined(__HAIKU__)) 148ssize_t 149read_pos(int fd, fs_off_t _pos, void *data, size_t nbytes) 150{ 151 off_t pos = (off_t)_pos; 152 size_t ret; 153 154 if (lseek(fd, pos, SEEK_SET) < 0) { 155 perror("read lseek"); 156 errno = EINVAL; 157 return -1; 158 } 159 160 ret = read(fd, data, nbytes); 161 162 if (ret != nbytes) { 163 printf("read_pos: wanted %d, got %d\n", nbytes, ret); 164 return -1; 165 } 166 167 return ret; 168} 169 170ssize_t 171write_pos(int fd, fs_off_t _pos, const void *data, size_t nbytes) 172{ 173 off_t pos = (off_t)_pos; 174 size_t ret; 175 176 if (lseek(fd, pos, SEEK_SET) < 0) { 177 perror("read lseek"); 178 errno = EINVAL; 179 return -1; 180 } 181 182 ret = write(fd, data, nbytes); 183 184 if (ret != nbytes) { 185 printf("write_pos: wanted %d, got %d\n", nbytes, ret); 186 return -1; 187 } 188 189 return ret; 190} 191 192 193#ifdef sun /* bloody wankers */ 194#include <sys/stream.h> 195#ifdef DEF_IOV_MAX 196#define MAX_IOV DEF_IOV_MAX 197#else 198#define MAX_IOV 16 199#endif 200#else /* the rest of the world... */ 201#define MAX_IOV 8192 /* something way bigger than we'll ever use */ 202#endif 203 204ssize_t 205readv_pos(int fd, fs_off_t _pos, const struct iovec *iov, int count) 206{ 207 off_t pos = (off_t)_pos; 208 size_t amt = 0; 209 ssize_t ret; 210 const struct iovec *tmpiov; 211 int i, n; 212 213 if (lseek(fd, pos, SEEK_SET) < 0) { 214 perror("read lseek"); 215 return FS_EINVAL; 216 } 217 218 i = 0; 219 tmpiov = iov; 220 while (i < count) { 221 if (i + MAX_IOV < count) 222 n = MAX_IOV; 223 else 224 n = (count - i); 225 226 ret = readv(fd, tmpiov, n); 227 amt += ret; 228 229 if (ret < 0) 230 break; 231 232 i += n; 233 tmpiov += n; 234 } 235 236 return amt; 237} 238 239ssize_t 240writev_pos(int fd, fs_off_t _pos, const struct iovec *iov, int count) 241{ 242 off_t pos = (off_t)_pos; 243 size_t amt = 0; 244 ssize_t ret; 245 const struct iovec *tmpiov; 246 int i, n; 247 248 if (lseek(fd, pos, SEEK_SET) < 0) { 249 perror("read lseek"); 250 return FS_EINVAL; 251 } 252 253 i = 0; 254 tmpiov = iov; 255 while (i < count) { 256 if (i + MAX_IOV < count) 257 n = MAX_IOV; 258 else 259 n = (count - i); 260 261 ret = writev(fd, tmpiov, n); 262 amt += ret; 263 264 if (ret < 0) 265 break; 266 267 i += n; 268 tmpiov += n; 269 } 270 271 return amt; 272} 273 274 275int build_platform_open(const char *pathname, int oflags, my_mode_t mode); 276 277int 278build_platform_open(const char *pathname, int oflags, my_mode_t mode) 279{ 280 int fd = open(pathname, to_platform_open_mode(oflags), 281 to_platform_mode(mode)); 282 if (fd < 0) { 283 errno = from_platform_error(errno); 284 return -1; 285 } 286 287 return fd; 288} 289 290 291int build_platform_close(int fd); 292 293int 294build_platform_close(int fd) 295{ 296 if (close(fd) < 0) { 297 errno = from_platform_error(errno); 298 return -1; 299 } 300 301 return 0; 302} 303 304 305int build_platform_fstat(int fd, struct my_stat *myst); 306 307int 308build_platform_fstat(int fd, struct my_stat *myst) 309{ 310 struct stat st; 311 312 if (!myst) { 313 errno = FS_EINVAL; 314 return -1; 315 } 316 317 if (fstat(fd, &st) < 0) { 318 errno = from_platform_error(errno); 319 return -1; 320 } 321 322 from_platform_stat(&st, myst); 323 324 return 0; 325} 326 327 328ssize_t build_platform_read_pos(int fd, fs_off_t pos, void *buf, size_t count); 329 330ssize_t 331build_platform_read_pos(int fd, fs_off_t pos, void *buf, size_t count) 332{ 333 ssize_t result = read_pos(fd, pos, buf, count); 334 if (result < 0) { 335 errno = from_platform_error(errno); 336 return -1; 337 } 338 339 return result; 340} 341 342 343#ifdef HAIKU_HOST_PLATFORM_LINUX 344 345static bool 346test_size(int fd, off_t size) 347{ 348 char buffer[1]; 349 350 if (size == 0) 351 return true; 352 353 if (lseek(fd, size - 1, SEEK_SET) < 0) 354 return false; 355 356 return (read(fd, &buffer, 1) == 1); 357} 358 359 360static off_t 361get_partition_size(int fd, off_t maxSize) 362{ 363 // binary search 364 off_t lower = 0; 365 off_t upper = maxSize; 366 while (lower < upper) { 367 off_t mid = (lower + upper + 1) / 2; 368 if (test_size(fd, mid)) 369 lower = mid; 370 else 371 upper = mid - 1; 372 } 373 374 return lower; 375} 376 377#endif // HAIKU_HOST_PLATFORM_LINUX 378 379 380extern int build_platform_ioctl(int fd, unsigned long op, ...); 381 382int 383build_platform_ioctl(int fd, unsigned long op, ...) 384{ 385 status_t error = FS_BAD_VALUE; 386 va_list list; 387 388 // count arguments 389 390 va_start(list, op); 391 392 switch (op) { 393 case 7: // B_GET_GEOMETRY 394 { 395 #ifdef HAIKU_HOST_PLATFORM_LINUX 396 { 397 device_geometry *geometry = va_arg(list, device_geometry*); 398 struct hd_geometry hdGeometry; 399 // BLKGETSIZE and BLKGETSIZE64 don't seem to work for 400 // partitions. So we get the device geometry (there only seems 401 // to be HDIO_GETGEO, which is kind of obsolete, BTW), and 402 // get the partition size via binary search. 403 if (ioctl(fd, HDIO_GETGEO, &hdGeometry) == 0) { 404 off_t bytesPerCylinder = (off_t)hdGeometry.heads 405 * hdGeometry.sectors * 512; 406 off_t deviceSize = bytesPerCylinder * hdGeometry.cylinders; 407 off_t partitionSize = get_partition_size(fd, deviceSize); 408 409 geometry->head_count = hdGeometry.heads; 410 geometry->cylinder_count = partitionSize / bytesPerCylinder; 411 geometry->sectors_per_track = hdGeometry.sectors; 412 413 // TODO: Get the real values... 414 geometry->bytes_per_sector = 512; 415 geometry->device_type = B_DISK; 416 geometry->removable = false; 417 geometry->read_only = false; 418 geometry->write_once = false; 419 error = FS_OK; 420 } else 421 error = from_platform_error(errno); 422 } 423 #endif // HAIKU_HOST_PLATFORM_LINUX 424 425 break; 426 } 427 428 case 20: // B_FLUSH_DRIVE_CACHE 429 error = FS_OK; 430 break; 431 432 case 10000: // IOCTL_FILE_UNCACHED_IO 433 error = FS_OK; 434 break; 435 } 436 437 va_end(list); 438 439 if (error != FS_OK) { 440 errno = error; 441 return -1; 442 } 443 return 0; 444} 445 446 447#endif /* ! __BEOS__ */ 448 449 450#include <stdarg.h> 451 452 453void 454panic(const char *format, ...) 455{ 456 va_list ap; 457 458 va_start(ap, format); 459 vfprintf(stderr, format, ap); 460 va_end(ap); 461 462 while (TRUE) 463 ; 464} 465 466 467 468#include "lock.h" 469 470int 471new_lock(lock *l, const char *name) 472{ 473 l->c = 1; 474 l->s = create_sem(0, (char *)name); 475 if (l->s <= 0) 476 return l->s; 477 return 0; 478} 479 480int 481free_lock(lock *l) 482{ 483 delete_sem(l->s); 484 485 return 0; 486} 487 488int 489new_mlock(mlock *l, long c, const char *name) 490{ 491 l->s = create_sem(c, (char *)name); 492 if (l->s <= 0) 493 return l->s; 494 return 0; 495} 496 497int 498free_mlock(mlock *l) 499{ 500 delete_sem(l->s); 501 502 return 0; 503} 504 505 506#ifdef unix 507#include <sys/time.h> 508 509bigtime_t 510system_time(void) 511{ 512 bigtime_t t; 513 struct timeval tv; 514 515 gettimeofday(&tv, NULL); 516 517 t = ((bigtime_t)tv.tv_sec * 1000000) + (bigtime_t)tv.tv_usec; 518 return t; 519} 520 521/* 522 If you're compiler/system can't deal with the version of system_time() 523 as defined above, use this one instead 524bigtime_t 525system_time(void) 526{ 527 return (bigtime_t)time(NULL); 528} 529*/ 530 531#endif /* unix */ 532 533#if (defined(__BEOS__) || defined(__HAIKU__)) 534#include <KernelExport.h> 535 536void 537dprintf(const char *format, ...) 538{ 539 va_list args; 540 541 va_start(args, format); 542 vprintf(format, args); 543 va_end(args); 544} 545 546#endif 547