Changeset 14321 for trunk/libtransmission/file-posix.c
- Timestamp:
- Jul 8, 2014, 12:15:12 AM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/libtransmission/file-posix.c
r14314 r14321 8 8 */ 9 9 10 #if defined (HAVE_CANONICALIZE_FILE_NAME) && !defined (_GNU_SOURCE) 10 #if (defined (HAVE_POSIX_FADVISE) || defined (HAVE_POSIX_FALLOCATE)) && (!defined (_XOPEN_SOURCE) || _XOPEN_SOURCE < 600) 11 #ifdef _XOPEN_SOURCE 12 #undef _XOPEN_SOURCE 13 #endif 14 #define _XOPEN_SOURCE 600 15 #endif 16 17 #if (defined (HAVE_FALLOCATE64) || defined (HAVE_CANONICALIZE_FILE_NAME)) && !defined (_GNU_SOURCE) 11 18 #define _GNU_SOURCE 19 #endif 20 21 #if defined (__APPLE__) && !defined (_DARWIN_C_SOURCE) 22 #define _DARWIN_C_SOURCE 12 23 #endif 13 24 14 25 #include <assert.h> 15 26 #include <errno.h> 27 #include <fcntl.h> /* O_LARGEFILE, posix_fadvise (), [posix_]fallocate () */ 16 28 #include <libgen.h> /* basename (), dirname () */ 17 29 #include <limits.h> /* PATH_MAX */ 18 30 #include <stdio.h> 19 31 #include <stdlib.h> 32 #include <string.h> 33 #include <sys/mman.h> /* mmap (), munmap () */ 20 34 #include <sys/types.h> 21 35 #include <sys/stat.h> 22 #include <unistd.h> 36 #include <unistd.h> /* lseek (), write (), ftruncate (), pread (), pwrite (), pathconf (), etc */ 37 38 #ifdef HAVE_XFS_XFS_H 39 #include <xfs/xfs.h> 40 #endif 23 41 24 42 #include "transmission.h" 25 43 #include "file.h" 44 #include "platform.h" 26 45 #include "utils.h" 46 47 #ifndef O_LARGEFILE 48 #define O_LARGEFILE 0 49 #endif 50 #ifndef O_BINARY 51 #define O_BINARY 0 52 #endif 53 #ifndef O_SEQUENTIAL 54 #define O_SEQUENTIAL 0 55 #endif 56 #ifndef O_CLOEXEC 57 #define O_CLOEXEC 0 58 #endif 27 59 28 60 #ifndef PATH_MAX 29 61 #define PATH_MAX 4096 62 #endif 63 64 /* don't use pread/pwrite on old versions of uClibc because they're buggy. 65 * https://trac.transmissionbt.com/ticket/3826 */ 66 #ifdef __UCLIBC__ 67 #define TR_UCLIBC_CHECK_VERSION(major,minor,micro) \ 68 (__UCLIBC_MAJOR__ > (major) || \ 69 (__UCLIBC_MAJOR__ == (major) && __UCLIBC_MINOR__ > (minor)) || \ 70 (__UCLIBC_MAJOR__ == (major) && __UCLIBC_MINOR__ == (minor) && \ 71 __UCLIBC_SUBLEVEL__ >= (micro))) 72 #if !TR_UCLIBC_CHECK_VERSION (0,9,28) 73 #undef HAVE_PREAD 74 #undef HAVE_PWRITE 75 #endif 76 #endif 77 78 #ifdef __APPLE__ 79 #ifndef HAVE_PREAD 80 #define HAVE_PREAD 81 #endif 82 #ifndef HAVE_PWRITE 83 #define HAVE_PWRITE 84 #endif 85 #ifndef HAVE_MKDTEMP 86 #define HAVE_MKDTEMP 87 #endif 30 88 #endif 31 89 … … 63 121 } 64 122 123 static void 124 set_file_for_single_pass (tr_sys_file_t handle) 125 { 126 /* Set hints about the lookahead buffer and caching. It's okay 127 for these to fail silently, so don't let them affect errno */ 128 129 const int err = errno; 130 131 if (handle == TR_BAD_SYS_FILE) 132 return; 133 134 #ifdef HAVE_POSIX_FADVISE 135 136 posix_fadvise (handle, 0, 0, POSIX_FADV_SEQUENTIAL); 137 138 #endif 139 140 #ifdef __APPLE__ 141 142 fcntl (handle, F_RDAHEAD, 1); 143 fcntl (handle, F_NOCACHE, 1); 144 145 #endif 146 147 errno = err; 148 } 149 65 150 bool 66 151 tr_sys_path_exists (const char * path, … … 239 324 return ret; 240 325 } 326 327 tr_sys_file_t 328 tr_sys_file_get_std (tr_std_sys_file_t std_file, 329 tr_error ** error) 330 { 331 tr_sys_file_t ret = TR_BAD_SYS_FILE; 332 333 switch (std_file) 334 { 335 case TR_STD_SYS_FILE_IN: 336 ret = STDIN_FILENO; 337 break; 338 case TR_STD_SYS_FILE_OUT: 339 ret = STDOUT_FILENO; 340 break; 341 case TR_STD_SYS_FILE_ERR: 342 ret = STDERR_FILENO; 343 break; 344 default: 345 assert (0 && "Unknown standard file"); 346 set_system_error (error, EINVAL); 347 } 348 349 return ret; 350 } 351 352 tr_sys_file_t 353 tr_sys_file_open (const char * path, 354 int flags, 355 int permissions, 356 tr_error ** error) 357 { 358 tr_sys_file_t ret; 359 int native_flags = 0; 360 361 assert (path != NULL); 362 assert ((flags & (TR_SYS_FILE_READ | TR_SYS_FILE_WRITE)) != 0); 363 364 if ((flags & (TR_SYS_FILE_READ | TR_SYS_FILE_WRITE)) == (TR_SYS_FILE_READ | TR_SYS_FILE_WRITE)) 365 native_flags |= O_RDWR; 366 else if (flags & TR_SYS_FILE_READ) 367 native_flags |= O_RDONLY; 368 else if (flags & TR_SYS_FILE_WRITE) 369 native_flags |= O_WRONLY; 370 371 native_flags |= 372 (flags & TR_SYS_FILE_CREATE ? O_CREAT : 0) | 373 (flags & TR_SYS_FILE_CREATE_NEW ? O_CREAT | O_EXCL : 0) | 374 (flags & TR_SYS_FILE_APPEND ? O_APPEND : 0) | 375 (flags & TR_SYS_FILE_TRUNCATE ? O_TRUNC : 0) | 376 (flags & TR_SYS_FILE_SEQUENTIAL ? O_SEQUENTIAL : 0) | 377 O_BINARY | O_LARGEFILE | O_CLOEXEC; 378 379 ret = open (path, native_flags, permissions); 380 381 if (ret != TR_BAD_SYS_FILE) 382 { 383 if (flags & TR_SYS_FILE_SEQUENTIAL) 384 set_file_for_single_pass (ret); 385 } 386 else 387 { 388 set_system_error (error, errno); 389 } 390 391 return ret; 392 } 393 394 tr_sys_file_t 395 tr_sys_file_open_temp (char * path_template, 396 tr_error ** error) 397 { 398 tr_sys_file_t ret; 399 400 assert (path_template != NULL); 401 402 ret = mkstemp (path_template); 403 404 if (ret == TR_BAD_SYS_FILE) 405 set_system_error (error, errno); 406 407 set_file_for_single_pass (ret); 408 409 return ret; 410 } 411 412 bool 413 tr_sys_file_close (tr_sys_file_t handle, 414 tr_error ** error) 415 { 416 bool ret; 417 418 assert (handle != TR_BAD_SYS_FILE); 419 420 ret = close (handle) != -1; 421 422 if (!ret) 423 set_system_error (error, errno); 424 425 return ret; 426 } 427 428 bool 429 tr_sys_file_get_info (tr_sys_file_t handle, 430 tr_sys_path_info * info, 431 tr_error ** error) 432 { 433 bool ret; 434 struct stat sb; 435 436 assert (handle != TR_BAD_SYS_FILE); 437 assert (info != NULL); 438 439 ret = fstat (handle, &sb) != -1; 440 441 if (ret) 442 stat_to_sys_path_info (&sb, info); 443 else 444 set_system_error (error, errno); 445 446 return ret; 447 } 448 449 bool 450 tr_sys_file_seek (tr_sys_file_t handle, 451 int64_t offset, 452 tr_seek_origin_t origin, 453 uint64_t * new_offset, 454 tr_error ** error) 455 { 456 bool ret = false; 457 off_t my_new_offset; 458 459 TR_STATIC_ASSERT (TR_SEEK_SET == SEEK_SET, "values should match"); 460 TR_STATIC_ASSERT (TR_SEEK_CUR == SEEK_CUR, "values should match"); 461 TR_STATIC_ASSERT (TR_SEEK_END == SEEK_END, "values should match"); 462 463 TR_STATIC_ASSERT (sizeof (*new_offset) >= sizeof (my_new_offset), ""); 464 465 assert (handle != TR_BAD_SYS_FILE); 466 assert (origin == TR_SEEK_SET || origin == TR_SEEK_CUR || origin == TR_SEEK_END); 467 468 my_new_offset = lseek (handle, offset, origin); 469 470 if (my_new_offset != (off_t)-1) 471 { 472 if (new_offset != NULL) 473 *new_offset = my_new_offset; 474 ret = true; 475 } 476 else 477 { 478 set_system_error (error, errno); 479 } 480 481 return ret; 482 } 483 484 bool 485 tr_sys_file_read (tr_sys_file_t handle, 486 void * buffer, 487 uint64_t size, 488 uint64_t * bytes_read, 489 tr_error ** error) 490 { 491 bool ret = false; 492 ssize_t my_bytes_read; 493 494 TR_STATIC_ASSERT (sizeof (*bytes_read) >= sizeof (my_bytes_read), ""); 495 496 assert (handle != TR_BAD_SYS_FILE); 497 assert (buffer != NULL || size == 0); 498 499 my_bytes_read = read (handle, buffer, size); 500 501 if (my_bytes_read != -1) 502 { 503 if (bytes_read != NULL) 504 *bytes_read = my_bytes_read; 505 ret = true; 506 } 507 else 508 { 509 set_system_error (error, errno); 510 } 511 512 return ret; 513 } 514 515 bool 516 tr_sys_file_read_at (tr_sys_file_t handle, 517 void * buffer, 518 uint64_t size, 519 uint64_t offset, 520 uint64_t * bytes_read, 521 tr_error ** error) 522 { 523 bool ret = false; 524 ssize_t my_bytes_read; 525 526 TR_STATIC_ASSERT (sizeof (*bytes_read) >= sizeof (my_bytes_read), ""); 527 528 assert (handle != TR_BAD_SYS_FILE); 529 assert (buffer != NULL || size == 0); 530 531 #ifdef HAVE_PREAD 532 533 my_bytes_read = pread (handle, buffer, size, offset); 534 535 #else 536 537 if (lseek (handle, offset, SEEK_SET) != -1) 538 my_bytes_read = read (handle, buffer, size); 539 else 540 my_bytes_read = -1; 541 542 #endif 543 544 if (my_bytes_read != -1) 545 { 546 if (bytes_read != NULL) 547 *bytes_read = my_bytes_read; 548 ret = true; 549 } 550 else 551 { 552 set_system_error (error, errno); 553 } 554 555 return ret; 556 } 557 558 bool 559 tr_sys_file_write (tr_sys_file_t handle, 560 const void * buffer, 561 uint64_t size, 562 uint64_t * bytes_written, 563 tr_error ** error) 564 { 565 bool ret = false; 566 ssize_t my_bytes_written; 567 568 TR_STATIC_ASSERT (sizeof (*bytes_written) >= sizeof (my_bytes_written), ""); 569 570 assert (handle != TR_BAD_SYS_FILE); 571 assert (buffer != NULL || size == 0); 572 573 my_bytes_written = write (handle, buffer, size); 574 575 if (my_bytes_written != -1) 576 { 577 if (bytes_written != NULL) 578 *bytes_written = my_bytes_written; 579 ret = true; 580 } 581 else 582 { 583 set_system_error (error, errno); 584 } 585 586 return ret; 587 } 588 589 bool 590 tr_sys_file_write_at (tr_sys_file_t handle, 591 const void * buffer, 592 uint64_t size, 593 uint64_t offset, 594 uint64_t * bytes_written, 595 tr_error ** error) 596 { 597 bool ret = false; 598 ssize_t my_bytes_written; 599 600 TR_STATIC_ASSERT (sizeof (*bytes_written) >= sizeof (my_bytes_written), ""); 601 602 assert (handle != TR_BAD_SYS_FILE); 603 assert (buffer != NULL || size == 0); 604 605 #ifdef HAVE_PWRITE 606 607 my_bytes_written = pwrite (handle, buffer, size, offset); 608 609 #else 610 611 if (lseek (handle, offset, SEEK_SET) != -1) 612 my_bytes_written = write (handle, buffer, size); 613 else 614 my_bytes_written = -1; 615 616 #endif 617 618 if (my_bytes_written != -1) 619 { 620 if (bytes_written != NULL) 621 *bytes_written = my_bytes_written; 622 ret = true; 623 } 624 else 625 { 626 set_system_error (error, errno); 627 } 628 629 return ret; 630 } 631 632 bool 633 tr_sys_file_flush (tr_sys_file_t handle, 634 tr_error ** error) 635 { 636 bool ret; 637 638 assert (handle != TR_BAD_SYS_FILE); 639 640 ret = fsync (handle) != -1; 641 642 if (!ret) 643 set_system_error (error, errno); 644 645 return ret; 646 } 647 648 bool 649 tr_sys_file_truncate (tr_sys_file_t handle, 650 uint64_t size, 651 tr_error ** error) 652 { 653 bool ret; 654 655 assert (handle != TR_BAD_SYS_FILE); 656 657 ret = ftruncate (handle, size) != -1; 658 659 if (!ret) 660 set_system_error (error, errno); 661 662 return ret; 663 } 664 665 bool 666 tr_sys_file_prefetch (tr_sys_file_t handle, 667 uint64_t offset, 668 uint64_t size, 669 tr_error ** error) 670 { 671 bool ret = false; 672 673 #if defined (HAVE_POSIX_FADVISE) 674 675 int code; 676 677 assert (handle != TR_BAD_SYS_FILE); 678 assert (size > 0); 679 680 code = posix_fadvise (handle, offset, size, POSIX_FADV_WILLNEED); 681 682 if (code == 0) 683 ret = true; 684 else 685 set_system_error (error, code); 686 687 #elif defined (__APPLE__) 688 689 struct radvisory radv; 690 691 assert (handle != TR_BAD_SYS_FILE); 692 assert (size > 0); 693 694 radv.ra_offset = offset; 695 radv.ra_count = size; 696 697 ret = fcntl (handle, F_RDADVISE, &radv) != -1; 698 699 if (!ret) 700 set_system_error (error, errno); 701 702 #endif 703 704 return ret; 705 } 706 707 bool 708 tr_sys_file_preallocate (tr_sys_file_t handle, 709 uint64_t size, 710 int flags, 711 tr_error ** error) 712 { 713 bool ret = false; 714 715 assert (handle != TR_BAD_SYS_FILE); 716 717 errno = 0; 718 719 #ifdef HAVE_FALLOCATE64 720 721 /* fallocate64 is always preferred, so try it first */ 722 ret = fallocate64 (handle, 0, 0, size) != -1; 723 724 #endif 725 726 if (!ret && (flags & TR_SYS_FILE_PREALLOC_SPARSE) == 0) 727 { 728 int code = errno; 729 730 #ifdef HAVE_XFS_XFS_H 731 732 if (!ret && platform_test_xfs_fd (handle)) 733 { 734 xfs_flock64_t fl; 735 736 fl.l_whence = 0; 737 fl.l_start = 0; 738 fl.l_len = size; 739 740 ret = xfsctl (NULL, handle, XFS_IOC_RESVSP64, &fl) != -1; 741 742 code = errno; 743 } 744 745 #endif 746 747 #ifdef __APPLE__ 748 749 if (!ret) 750 { 751 fstore_t fst; 752 753 fst.fst_flags = F_ALLOCATECONTIG; 754 fst.fst_posmode = F_PEOFPOSMODE; 755 fst.fst_offset = 0; 756 fst.fst_length = size; 757 fst.fst_bytesalloc = 0; 758 759 ret = fcntl (handle, F_PREALLOCATE, &fst) != -1; 760 761 if (ret) 762 ret = ftruncate (handle, size) != -1; 763 764 code = errno; 765 } 766 767 #endif 768 769 #ifdef HAVE_POSIX_FALLOCATE 770 771 if (!ret) 772 { 773 code = posix_fallocate (handle, 0, size); 774 ret = code == 0; 775 } 776 777 #endif 778 779 errno = code; 780 } 781 782 if (!ret) 783 set_system_error (error, errno); 784 785 return ret; 786 } 787 788 void * 789 tr_sys_file_map_for_reading (tr_sys_file_t handle, 790 uint64_t offset, 791 uint64_t size, 792 tr_error ** error) 793 { 794 void * ret; 795 796 assert (handle != TR_BAD_SYS_FILE); 797 assert (size > 0); 798 799 ret = mmap (NULL, size, PROT_READ, MAP_SHARED, handle, offset); 800 801 if (ret == MAP_FAILED) 802 { 803 set_system_error (error, errno); 804 ret = NULL; 805 } 806 807 return ret; 808 } 809 810 bool 811 tr_sys_file_unmap (const void * address, 812 uint64_t size, 813 tr_error ** error) 814 { 815 bool ret; 816 817 assert (address != NULL); 818 assert (size > 0); 819 820 ret = munmap ((void *) address, size) != -1; 821 822 if (!ret) 823 set_system_error (error, errno); 824 825 return ret; 826 }
Note: See TracChangeset
for help on using the changeset viewer.