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#include "apr_file_io.h"
19251875Speter
20251875Speterstatic apr_status_t apr_file_transfer_contents(const char *from_path,
21251875Speter                                               const char *to_path,
22251875Speter                                               apr_int32_t flags,
23251875Speter                                               apr_fileperms_t to_perms,
24251875Speter                                               apr_pool_t *pool)
25251875Speter{
26251875Speter    apr_file_t *s, *d;
27251875Speter    apr_status_t status;
28251875Speter    apr_finfo_t finfo;
29251875Speter    apr_fileperms_t perms;
30251875Speter
31251875Speter    /* Open source file. */
32251875Speter    status = apr_file_open(&s, from_path, APR_FOPEN_READ, APR_OS_DEFAULT, pool);
33251875Speter    if (status)
34251875Speter        return status;
35251875Speter
36251875Speter    /* Maybe get its permissions. */
37251875Speter    if (to_perms == APR_FILE_SOURCE_PERMS) {
38251875Speter        status = apr_file_info_get(&finfo, APR_FINFO_PROT, s);
39251875Speter        if (status != APR_SUCCESS && status != APR_INCOMPLETE) {
40251875Speter            apr_file_close(s);  /* toss any error */
41251875Speter            return status;
42251875Speter        }
43251875Speter        perms = finfo.protection;
44362181Sdim        apr_file_perms_set(to_path, perms); /* ignore any failure */
45251875Speter    }
46251875Speter    else
47251875Speter        perms = to_perms;
48251875Speter
49251875Speter    /* Open dest file. */
50251875Speter    status = apr_file_open(&d, to_path, flags, perms, pool);
51251875Speter    if (status) {
52251875Speter        apr_file_close(s);  /* toss any error */
53251875Speter        return status;
54251875Speter    }
55251875Speter
56251875Speter#if BUFSIZ > APR_FILE_DEFAULT_BUFSIZE
57251875Speter#define COPY_BUFSIZ BUFSIZ
58251875Speter#else
59251875Speter#define COPY_BUFSIZ APR_FILE_DEFAULT_BUFSIZE
60251875Speter#endif
61251875Speter
62251875Speter    /* Copy bytes till the cows come home. */
63251875Speter    while (1) {
64251875Speter        char buf[COPY_BUFSIZ];
65251875Speter        apr_size_t bytes_this_time = sizeof(buf);
66251875Speter        apr_status_t read_err;
67251875Speter        apr_status_t write_err;
68251875Speter
69251875Speter        /* Read 'em. */
70251875Speter        read_err = apr_file_read(s, buf, &bytes_this_time);
71251875Speter        if (read_err && !APR_STATUS_IS_EOF(read_err)) {
72251875Speter            apr_file_close(s);  /* toss any error */
73251875Speter            apr_file_close(d);  /* toss any error */
74251875Speter            return read_err;
75251875Speter        }
76251875Speter
77251875Speter        /* Write 'em. */
78251875Speter        write_err = apr_file_write_full(d, buf, bytes_this_time, NULL);
79251875Speter        if (write_err) {
80251875Speter            apr_file_close(s);  /* toss any error */
81251875Speter            apr_file_close(d);  /* toss any error */
82251875Speter            return write_err;
83251875Speter        }
84251875Speter
85251875Speter        if (read_err && APR_STATUS_IS_EOF(read_err)) {
86251875Speter            status = apr_file_close(s);
87251875Speter            if (status) {
88251875Speter                apr_file_close(d);  /* toss any error */
89251875Speter                return status;
90251875Speter            }
91251875Speter
92251875Speter            /* return the results of this close: an error, or success */
93251875Speter            return apr_file_close(d);
94251875Speter        }
95251875Speter    }
96251875Speter    /* NOTREACHED */
97251875Speter}
98251875Speter
99251875SpeterAPR_DECLARE(apr_status_t) apr_file_copy(const char *from_path,
100251875Speter                                        const char *to_path,
101251875Speter                                        apr_fileperms_t perms,
102251875Speter                                        apr_pool_t *pool)
103251875Speter{
104251875Speter    return apr_file_transfer_contents(from_path, to_path,
105251875Speter                                      (APR_FOPEN_WRITE | APR_FOPEN_CREATE | APR_FOPEN_TRUNCATE),
106251875Speter                                      perms,
107251875Speter                                      pool);
108251875Speter}
109251875Speter
110251875SpeterAPR_DECLARE(apr_status_t) apr_file_append(const char *from_path,
111251875Speter                                          const char *to_path,
112251875Speter                                          apr_fileperms_t perms,
113251875Speter                                          apr_pool_t *pool)
114251875Speter{
115251875Speter    return apr_file_transfer_contents(from_path, to_path,
116251875Speter                                      (APR_FOPEN_WRITE | APR_FOPEN_CREATE | APR_FOPEN_APPEND),
117251875Speter                                      perms,
118251875Speter                                      pool);
119251875Speter}
120