1/*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 9 * 10 * This software is licensed as described in the file COPYING, which 11 * you should have received as part of this distribution. The terms 12 * are also available at https://curl.se/docs/copyright.html. 13 * 14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 15 * copies of the Software, and permit persons to whom the Software is 16 * furnished to do so, under the terms of the COPYING file. 17 * 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19 * KIND, either express or implied. 20 * 21 * SPDX-License-Identifier: curl 22 * 23 ***************************************************************************/ 24#include "tool_setup.h" 25 26#define ENABLE_CURLX_PRINTF 27/* use our own printf() functions */ 28#include "curlx.h" 29 30#include "tool_cfgable.h" 31#include "tool_operate.h" 32#include "tool_cb_see.h" 33 34#include "memdebug.h" /* keep this as LAST include */ 35 36/* OUR_MAX_SEEK_L has 'long' data type, OUR_MAX_SEEK_O has 'curl_off_t, 37 both represent the same value. Maximum offset used here when we lseek 38 using a 'long' data type offset */ 39 40#define OUR_MAX_SEEK_L 2147483647L - 1L 41#define OUR_MAX_SEEK_O CURL_OFF_T_C(0x7FFFFFFF) - CURL_OFF_T_C(0x1) 42 43/* 44** callback for CURLOPT_SEEKFUNCTION 45** 46** Notice that this is not supposed to return the resulting offset. This 47** shall only return CURL_SEEKFUNC_* return codes. 48*/ 49 50int tool_seek_cb(void *userdata, curl_off_t offset, int whence) 51{ 52 struct per_transfer *per = userdata; 53 54#if(SIZEOF_CURL_OFF_T > SIZEOF_OFF_T) && !defined(USE_WIN32_LARGE_FILES) 55 56 /* The offset check following here is only interesting if curl_off_t is 57 larger than off_t and we are not using the WIN32 large file support 58 macros that provide the support to do 64bit seeks correctly */ 59 60 if(offset > OUR_MAX_SEEK_O) { 61 /* Some precaution code to work around problems with different data sizes 62 to allow seeking >32bit even if off_t is 32bit. Should be very rare and 63 is really valid on weirdo-systems. */ 64 curl_off_t left = offset; 65 66 if(whence != SEEK_SET) 67 /* this code path doesn't support other types */ 68 return CURL_SEEKFUNC_FAIL; 69 70 if(LSEEK_ERROR == lseek(per->infd, 0, SEEK_SET)) 71 /* couldn't rewind to beginning */ 72 return CURL_SEEKFUNC_FAIL; 73 74 while(left) { 75 long step = (left > OUR_MAX_SEEK_O) ? OUR_MAX_SEEK_L : (long)left; 76 if(LSEEK_ERROR == lseek(per->infd, step, SEEK_CUR)) 77 /* couldn't seek forwards the desired amount */ 78 return CURL_SEEKFUNC_FAIL; 79 left -= step; 80 } 81 return CURL_SEEKFUNC_OK; 82 } 83#endif 84 85 if(LSEEK_ERROR == lseek(per->infd, offset, whence)) 86 /* couldn't rewind, the reason is in errno but errno is just not portable 87 enough and we don't actually care that much why we failed. We'll let 88 libcurl know that it may try other means if it wants to. */ 89 return CURL_SEEKFUNC_CANTSEEK; 90 91 return CURL_SEEKFUNC_OK; 92} 93 94#ifdef USE_TOOL_FTRUNCATE 95 96#ifdef _WIN32_WCE 97/* 64-bit lseek-like function unavailable */ 98# undef _lseeki64 99# define _lseeki64(hnd,ofs,whence) lseek(hnd,ofs,whence) 100# undef _get_osfhandle 101# define _get_osfhandle(fd) (fd) 102#endif 103 104/* 105 * Truncate a file handle at a 64-bit position 'where'. 106 */ 107 108int tool_ftruncate64(int fd, curl_off_t where) 109{ 110 intptr_t handle = _get_osfhandle(fd); 111 112 if(_lseeki64(fd, where, SEEK_SET) < 0) 113 return -1; 114 115 if(!SetEndOfFile((HANDLE)handle)) 116 return -1; 117 118 return 0; 119} 120 121#endif /* USE_TOOL_FTRUNCATE */ 122