		/* Copyright 2002-2004 The Apache Software Foundation
		 *
		 * Licensed under the Apache License, Version 2.0 (the "License");
		 * you may not use this file except in compliance with the License.
		 * You may obtain a copy of the License at
		 *
		 *     http://www.apache.org/licenses/LICENSE-2.0
		 *
		 * Unless required by applicable law or agreed to in writing, software
		 * distributed under the License is distributed on an "AS IS" BASIS,
		 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
		 * See the License for the specific language governing permissions and
		 * limitations under the License.
		 */
		
		#include "apr_arch_file_io.h"
		#include "apr_file_io.h"
		
		static apr_status_t apr_file_transfer_contents(const char *from_path,
		                                               const char *to_path,
		                                               apr_int32_t flags,
		                                               apr_fileperms_t to_perms,
		                                               apr_pool_t *pool)
           6    {
           6        apr_file_t *s = NULL, *d = NULL;  /* init to null important for APR */
           6        apr_status_t status;
           6        apr_finfo_t finfo;
           6        apr_fileperms_t perms;
		
		    /* Open source file. */
           6        status = apr_file_open(&s, from_path, APR_READ, APR_OS_DEFAULT, pool);
           6        if (status)
      ######            return status;
		
		    /* Maybe get its permissions. */
           6        if (to_perms == APR_FILE_SOURCE_PERMS) {
           6            status = apr_file_info_get(&finfo, APR_FINFO_PROT, s);
           6            if (status != APR_SUCCESS && status != APR_INCOMPLETE) {
      ######                apr_file_close(s);  /* toss any error */
      ######                return status;
		        }
           6            perms = finfo.protection;
		    }
		    else
      ######            perms = to_perms;
		
		    /* Open dest file. */
           6        status = apr_file_open(&d, to_path, flags, perms, pool);
           6        if (status) {
      ######            apr_file_close(s);  /* toss any error */
      ######            return status;
		    }
		
		    /* Copy bytes till the cows come home. */
          12        while (1) {
          12            char buf[BUFSIZ];
          12            apr_size_t bytes_this_time = sizeof(buf);
          12            apr_status_t read_err;
          12            apr_status_t write_err;
		
		        /* Read 'em. */
          12            read_err = apr_file_read(s, buf, &bytes_this_time);
          12            if (read_err && !APR_STATUS_IS_EOF(read_err)) {
      ######                apr_file_close(s);  /* toss any error */
      ######                apr_file_close(d);  /* toss any error */
      ######                return read_err;
		        }
		
		        /* Write 'em. */
          12            write_err = apr_file_write_full(d, buf, bytes_this_time, NULL);
          12            if (write_err) {
      ######                apr_file_close(s);  /* toss any error */
      ######                apr_file_close(d);  /* toss any error */
      ######                return write_err;
		        }
		
          12            if (read_err && APR_STATUS_IS_EOF(read_err)) {
           6                status = apr_file_close(s);
           6                if (status) {
      ######                    apr_file_close(d);  /* toss any error */
      ######                    return status;
		            }
		
		            /* return the results of this close: an error, or success */
           6                return apr_file_close(d);
		        }
		    }
		    /* NOTREACHED */
		}
		
		APR_DECLARE(apr_status_t) apr_file_copy(const char *from_path,
		                                        const char *to_path,
		                                        apr_fileperms_t perms,
		                                        apr_pool_t *pool)
           5    {
           5        return apr_file_transfer_contents(from_path, to_path,
		                                      (APR_WRITE | APR_CREATE | APR_TRUNCATE),
		                                      perms,
		                                      pool);
		}
		
		APR_DECLARE(apr_status_t) apr_file_append(const char *from_path,
		                                          const char *to_path,
		                                          apr_fileperms_t perms,
		                                          apr_pool_t *pool)
           1    {
           1        return apr_file_transfer_contents(from_path, to_path,
		                                      (APR_WRITE | APR_CREATE | APR_APPEND),
		                                      perms,
		                                      pool);
		}
