seek.c revision 253734
1206917Smarius/* Licensed to the Apache Software Foundation (ASF) under one or more 2206917Smarius * contributor license agreements. See the NOTICE file distributed with 3206917Smarius * this work for additional information regarding copyright ownership. 4206917Smarius * The ASF licenses this file to You under the Apache License, Version 2.0 5206917Smarius * (the "License"); you may not use this file except in compliance with 6206917Smarius * the License. You may obtain a copy of the License at 7206917Smarius * 8206917Smarius * http://www.apache.org/licenses/LICENSE-2.0 9206917Smarius * 10206917Smarius * Unless required by applicable law or agreed to in writing, software 11206917Smarius * distributed under the License is distributed on an "AS IS" BASIS, 12206917Smarius * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13206917Smarius * See the License for the specific language governing permissions and 14206917Smarius * limitations under the License. 15206917Smarius */ 16206917Smarius 17206917Smarius#include "apr_arch_file_io.h" 18206917Smarius 19206917Smariusstatic apr_status_t setptr(apr_file_t *thefile, apr_off_t pos ) 20206917Smarius{ 21206917Smarius apr_off_t newbufpos; 22206917Smarius apr_status_t rv; 23206917Smarius 24206917Smarius if (thefile->direction == 1) { 25206917Smarius rv = apr_file_flush_locked(thefile); 26206917Smarius if (rv) { 27206917Smarius return rv; 28206917Smarius } 29206917Smarius thefile->bufpos = thefile->direction = thefile->dataRead = 0; 30228975Suqs } 31206917Smarius 32206917Smarius newbufpos = pos - (thefile->filePtr - thefile->dataRead); 33206917Smarius if (newbufpos >= 0 && newbufpos <= thefile->dataRead) { 34206917Smarius thefile->bufpos = newbufpos; 35206917Smarius rv = APR_SUCCESS; 36206917Smarius } 37206917Smarius else { 38206917Smarius if (lseek(thefile->filedes, pos, SEEK_SET) != -1) { 39206917Smarius thefile->bufpos = thefile->dataRead = 0; 40206917Smarius thefile->filePtr = pos; 41206917Smarius rv = APR_SUCCESS; 42206917Smarius } 43206917Smarius else { 44206917Smarius rv = errno; 45206917Smarius } 46206917Smarius } 47206917Smarius 48206917Smarius return rv; 49206917Smarius} 50206917Smarius 51206917Smarius 52206917SmariusAPR_DECLARE(apr_status_t) apr_file_seek(apr_file_t *thefile, apr_seek_where_t where, apr_off_t *offset) 53206917Smarius{ 54206917Smarius apr_off_t rv; 55206917Smarius 56206917Smarius thefile->eof_hit = 0; 57206917Smarius 58206917Smarius if (thefile->buffered) { 59206917Smarius int rc = EINVAL; 60206917Smarius apr_finfo_t finfo; 61206917Smarius 62206917Smarius file_lock(thefile); 63206917Smarius 64206917Smarius switch (where) { 65206917Smarius case APR_SET: 66206917Smarius rc = setptr(thefile, *offset); 67206917Smarius break; 68206917Smarius 69206917Smarius case APR_CUR: 70206917Smarius rc = setptr(thefile, thefile->filePtr - thefile->dataRead + thefile->bufpos + *offset); 71206917Smarius break; 72206917Smarius 73206917Smarius case APR_END: 74206917Smarius rc = apr_file_info_get_locked(&finfo, APR_FINFO_SIZE, thefile); 75206917Smarius if (rc == APR_SUCCESS) 76206917Smarius rc = setptr(thefile, finfo.size + *offset); 77206917Smarius break; 78206917Smarius } 79206917Smarius 80206917Smarius *offset = thefile->filePtr - thefile->dataRead + thefile->bufpos; 81206917Smarius 82206917Smarius file_unlock(thefile); 83206917Smarius 84206917Smarius return rc; 85206917Smarius } 86206917Smarius else { 87206917Smarius rv = lseek(thefile->filedes, *offset, where); 88206917Smarius if (rv == -1) { 89206917Smarius *offset = -1; 90206917Smarius return errno; 91206917Smarius } 92206917Smarius else { 93206917Smarius *offset = rv; 94206917Smarius return APR_SUCCESS; 95206917Smarius } 96206917Smarius } 97206917Smarius} 98206917Smarius 99206917Smariusapr_status_t apr_file_trunc(apr_file_t *fp, apr_off_t offset) 100206917Smarius{ 101206917Smarius if (fp->buffered) { 102206917Smarius int rc = 0; 103206917Smarius file_lock(fp); 104206917Smarius if (fp->direction == 1 && fp->bufpos != 0) { 105206917Smarius apr_off_t len = fp->filePtr + fp->bufpos; 106206917Smarius if (offset < len) { 107206917Smarius /* New file end fall below our write buffer limit. 108206917Smarius * Figure out if and what needs to be flushed. 109206917Smarius */ 110206917Smarius apr_off_t off = len - offset; 111206917Smarius if (off >= 0 && off <= fp->bufpos) 112206917Smarius fp->bufpos = fp->bufpos - (size_t)off; 113206917Smarius else 114206917Smarius fp->bufpos = 0; 115206917Smarius } 116206917Smarius rc = apr_file_flush_locked(fp); 117206917Smarius /* Reset buffer positions for write mode */ 118206917Smarius fp->bufpos = fp->direction = fp->dataRead = 0; 119206917Smarius } 120206917Smarius file_unlock(fp); 121206917Smarius if (rc) { 122206917Smarius return rc; 123206917Smarius } 124206917Smarius } 125206917Smarius if (ftruncate(fp->filedes, offset) == -1) { 126206917Smarius return errno; 127206917Smarius } 128206917Smarius return apr_file_seek(fp, APR_SET, &offset); 129206917Smarius} 130206917Smarius