1251875Speter/* Licensed to the Apache Software Foundation (ASF) under one or more
2251875Speter * contributor license agreements.  See the NOTICE file distributed with
3251875Speter * this work for additional information regarding copyright ownership.
4251875Speter * The ASF licenses this file to You under the Apache License, Version 2.0
5251875Speter * (the "License"); you may not use this file except in compliance with
6251875Speter * the License.  You may obtain a copy of the License at
7251875Speter *
8251875Speter *     http://www.apache.org/licenses/LICENSE-2.0
9251875Speter *
10251875Speter * Unless required by applicable law or agreed to in writing, software
11251875Speter * distributed under the License is distributed on an "AS IS" BASIS,
12251875Speter * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13251875Speter * See the License for the specific language governing permissions and
14251875Speter * limitations under the License.
15251875Speter */
16251875Speter
17251875Speter#include "apr_arch_file_io.h"
18251875Speter
19251875Speterstatic apr_status_t setptr(apr_file_t *thefile, apr_off_t pos )
20251875Speter{
21251875Speter    apr_off_t newbufpos;
22251875Speter    apr_status_t rv;
23251875Speter
24251875Speter    if (thefile->direction == 1) {
25251875Speter        rv = apr_file_flush_locked(thefile);
26251875Speter        if (rv) {
27251875Speter            return rv;
28251875Speter        }
29251875Speter        thefile->bufpos = thefile->direction = thefile->dataRead = 0;
30251875Speter    }
31251875Speter
32251875Speter    newbufpos = pos - (thefile->filePtr - thefile->dataRead);
33251875Speter    if (newbufpos >= 0 && newbufpos <= thefile->dataRead) {
34251875Speter        thefile->bufpos = newbufpos;
35251875Speter        rv = APR_SUCCESS;
36251875Speter    }
37251875Speter    else {
38251875Speter        if (lseek(thefile->filedes, pos, SEEK_SET) != -1) {
39251875Speter            thefile->bufpos = thefile->dataRead = 0;
40251875Speter            thefile->filePtr = pos;
41251875Speter            rv = APR_SUCCESS;
42251875Speter        }
43251875Speter        else {
44251875Speter            rv = errno;
45251875Speter        }
46251875Speter    }
47251875Speter
48251875Speter    return rv;
49251875Speter}
50251875Speter
51251875Speter
52251875SpeterAPR_DECLARE(apr_status_t) apr_file_seek(apr_file_t *thefile, apr_seek_where_t where, apr_off_t *offset)
53251875Speter{
54251875Speter    apr_off_t rv;
55251875Speter
56251875Speter    thefile->eof_hit = 0;
57251875Speter
58251875Speter    if (thefile->buffered) {
59251875Speter        int rc = EINVAL;
60251875Speter        apr_finfo_t finfo;
61251875Speter
62251875Speter        file_lock(thefile);
63251875Speter
64251875Speter        switch (where) {
65251875Speter        case APR_SET:
66251875Speter            rc = setptr(thefile, *offset);
67251875Speter            break;
68251875Speter
69251875Speter        case APR_CUR:
70251875Speter            rc = setptr(thefile, thefile->filePtr - thefile->dataRead + thefile->bufpos + *offset);
71251875Speter            break;
72251875Speter
73251875Speter        case APR_END:
74251875Speter            rc = apr_file_info_get_locked(&finfo, APR_FINFO_SIZE, thefile);
75251875Speter            if (rc == APR_SUCCESS)
76251875Speter                rc = setptr(thefile, finfo.size + *offset);
77251875Speter            break;
78251875Speter        }
79251875Speter
80251875Speter        *offset = thefile->filePtr - thefile->dataRead + thefile->bufpos;
81251875Speter
82251875Speter        file_unlock(thefile);
83251875Speter
84251875Speter        return rc;
85251875Speter    }
86251875Speter    else {
87251875Speter        rv = lseek(thefile->filedes, *offset, where);
88251875Speter        if (rv == -1) {
89251875Speter            *offset = -1;
90251875Speter            return errno;
91251875Speter        }
92251875Speter        else {
93251875Speter            *offset = rv;
94251875Speter            return APR_SUCCESS;
95251875Speter        }
96251875Speter    }
97251875Speter}
98251875Speter
99251875Speterapr_status_t apr_file_trunc(apr_file_t *fp, apr_off_t offset)
100251875Speter{
101251875Speter    if (fp->buffered) {
102251875Speter        int rc = 0;
103251875Speter        file_lock(fp);
104251875Speter        if (fp->direction == 1 && fp->bufpos != 0) {
105251875Speter            apr_off_t len = fp->filePtr + fp->bufpos;
106251875Speter            if (offset < len) {
107251875Speter                /* New file end fall below our write buffer limit.
108251875Speter                 * Figure out if and what needs to be flushed.
109251875Speter                 */
110251875Speter                apr_off_t off = len - offset;
111251875Speter                if (off >= 0 && off <= fp->bufpos)
112251875Speter                    fp->bufpos = fp->bufpos - (size_t)off;
113251875Speter                else
114251875Speter                    fp->bufpos = 0;
115251875Speter            }
116251875Speter            rc = apr_file_flush_locked(fp);
117251875Speter            /* Reset buffer positions for write mode */
118251875Speter            fp->bufpos = fp->direction = fp->dataRead = 0;
119251875Speter        }
120253734Speter        file_unlock(fp);
121251875Speter        if (rc) {
122251875Speter            return rc;
123251875Speter        }
124251875Speter    }
125251875Speter    if (ftruncate(fp->filedes, offset) == -1) {
126251875Speter        return errno;
127251875Speter    }
128251875Speter    return apr_file_seek(fp, APR_SET, &offset);
129251875Speter}
130