! Update an open file's current offset * * @param[in,out] r newlib reentrancy struct * @param[in,out] fd Pointer to archive_file_t * @param[in] pos Offset to seek to * @param[in] whence Where to seek from * * @returns new offset for success * @returns -1 for error */
| 722 | * @returns -1 for error |
| 723 | */ |
| 724 | static off_t |
| 725 | archive_seek(struct _reent *r, |
| 726 | void *fd, |
| 727 | off_t pos, |
| 728 | int whence) |
| 729 | { |
| 730 | Result rc; |
| 731 | u64 offset; |
| 732 | |
| 733 | /* get pointer to our data */ |
| 734 | archive_file_t *file = (archive_file_t*)fd; |
| 735 | |
| 736 | /* find the offset to see from */ |
| 737 | switch(whence) |
| 738 | { |
| 739 | /* set absolute position; start offset is 0 */ |
| 740 | case SEEK_SET: |
| 741 | offset = 0; |
| 742 | break; |
| 743 | |
| 744 | /* set position relative to the current position */ |
| 745 | case SEEK_CUR: |
| 746 | offset = file->offset; |
| 747 | break; |
| 748 | |
| 749 | /* set position relative to the end of the file */ |
| 750 | case SEEK_END: |
| 751 | rc = FSFILE_GetSize(file->fd, &offset); |
| 752 | if(R_FAILED(rc)) |
| 753 | { |
| 754 | r->_errno = archive_translate_error(rc); |
| 755 | return -1; |
| 756 | } |
| 757 | break; |
| 758 | |
| 759 | /* an invalid option was provided */ |
| 760 | default: |
| 761 | r->_errno = EINVAL; |
| 762 | return -1; |
| 763 | } |
| 764 | |
| 765 | /* TODO: A better check that prevents overflow. */ |
| 766 | if(pos < 0 && (s64)offset < -(s64)pos) |
| 767 | { |
| 768 | /* don't allow seek to before the beginning of the file */ |
| 769 | r->_errno = EINVAL; |
| 770 | return -1; |
| 771 | } |
| 772 | |
| 773 | /* update the current offset */ |
| 774 | file->offset = offset + pos; |
| 775 | return file->offset; |
| 776 | } |
| 777 | |
| 778 | /*! Get file stats from an open file |
| 779 | * |
nothing calls this directly
no test coverage detected