1/* Copying of files. 2 Copyright (C) 2001-2003, 2006-2007 Free Software Foundation, Inc. 3 Written by Bruno Haible <haible@clisp.cons.org>, 2001. 4 5 This program is free software: you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 3 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 17 18 19#include <config.h> 20 21/* Specification. */ 22#include "copy-file.h" 23 24#include <errno.h> 25#include <fcntl.h> 26#include <stddef.h> 27#include <stdlib.h> 28#include <sys/stat.h> 29#include <unistd.h> 30 31#if HAVE_UTIME || HAVE_UTIMES 32# if HAVE_UTIME_H 33# include <utime.h> 34# else 35# include <sys/utime.h> 36# endif 37#endif 38 39#include "error.h" 40#include "safe-read.h" 41#include "full-write.h" 42#include "acl.h" 43#include "binary-io.h" 44#include "gettext.h" 45 46#define _(str) gettext (str) 47 48/* The results of open() in this file are not used with fchdir, 49 therefore save some unnecessary work in fchdir.c. */ 50#undef open 51#undef close 52 53 54void 55copy_file_preserving (const char *src_filename, const char *dest_filename) 56{ 57 int src_fd; 58 struct stat statbuf; 59 int mode; 60 int dest_fd; 61 char buf[4096]; 62 const size_t buf_size = sizeof (buf); 63 64 src_fd = open (src_filename, O_RDONLY | O_BINARY); 65 if (src_fd < 0 || fstat (src_fd, &statbuf) < 0) 66 error (EXIT_FAILURE, errno, _("error while opening \"%s\" for reading"), 67 src_filename); 68 69 mode = statbuf.st_mode & 07777; 70 71 dest_fd = open (dest_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0600); 72 if (dest_fd < 0) 73 error (EXIT_FAILURE, errno, _("cannot open backup file \"%s\" for writing"), 74 dest_filename); 75 76 /* Copy the file contents. */ 77 for (;;) 78 { 79 size_t n_read = safe_read (src_fd, buf, buf_size); 80 if (n_read == SAFE_READ_ERROR) 81 error (EXIT_FAILURE, errno, _("error reading \"%s\""), src_filename); 82 if (n_read == 0) 83 break; 84 85 if (full_write (dest_fd, buf, n_read) < n_read) 86 error (EXIT_FAILURE, errno, _("error writing \"%s\""), dest_filename); 87 } 88 89#if !USE_ACL 90 if (close (dest_fd) < 0) 91 error (EXIT_FAILURE, errno, _("error writing \"%s\""), dest_filename); 92 if (close (src_fd) < 0) 93 error (EXIT_FAILURE, errno, _("error after reading \"%s\""), src_filename); 94#endif 95 96 /* Preserve the access and modification times. */ 97#if HAVE_UTIME 98 { 99 struct utimbuf ut; 100 101 ut.actime = statbuf.st_atime; 102 ut.modtime = statbuf.st_mtime; 103 utime (dest_filename, &ut); 104 } 105#elif HAVE_UTIMES 106 { 107 struct timeval ut[2]; 108 109 ut[0].tv_sec = statbuf.st_atime; ut[0].tv_usec = 0; 110 ut[1].tv_sec = statbuf.st_mtime; ut[1].tv_usec = 0; 111 utimes (dest_filename, &ut); 112 } 113#endif 114 115#if HAVE_CHOWN 116 /* Preserve the owner and group. */ 117 chown (dest_filename, statbuf.st_uid, statbuf.st_gid); 118#endif 119 120 /* Preserve the access permissions. */ 121#if USE_ACL 122 if (copy_acl (src_filename, src_fd, dest_filename, dest_fd, mode)) 123 exit (EXIT_FAILURE); 124#else 125 chmod (dest_filename, mode); 126#endif 127 128#if USE_ACL 129 if (close (dest_fd) < 0) 130 error (EXIT_FAILURE, errno, _("error writing \"%s\""), dest_filename); 131 if (close (src_fd) < 0) 132 error (EXIT_FAILURE, errno, _("error after reading \"%s\""), src_filename); 133#endif 134} 135