1 /* Copying of files. 2 Copyright (C) 2001-2003, 2006 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 2, or (at your option) 8 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, write to the Free Software Foundation, 17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ 18 19 20 #include <config.h> 21 22 /* Specification. */ 23 #include "copy-file.h" 24 25 #include <errno.h> 26 #include <fcntl.h> 27 #include <stddef.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 "binary-io.h" 43 #include "exit.h" 44 #include "gettext.h" 45 46 #define _(str) gettext (str) 47 48 void 49 copy_file_preserving (const char *src_filename, const char *dest_filename) 50 { 51 int src_fd; 52 struct stat statbuf; 53 int mode; 54 int dest_fd; 55 char buf[4096]; 56 const size_t buf_size = sizeof (buf); 57 58 src_fd = open (src_filename, O_RDONLY | O_BINARY); 59 if (src_fd < 0 || fstat (src_fd, &statbuf) < 0) 60 error (EXIT_FAILURE, errno, _("error while opening \"%s\" for reading"), 61 src_filename); 62 63 mode = statbuf.st_mode & 07777; 64 65 dest_fd = open (dest_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0600); 66 if (dest_fd < 0) 67 error (EXIT_FAILURE, errno, _("cannot open backup file \"%s\" for writing"), 68 dest_filename); 69 70 /* Copy the file contents. */ 71 for (;;) 72 { 73 size_t n_read = safe_read (src_fd, buf, buf_size); 74 if (n_read == SAFE_READ_ERROR) 75 error (EXIT_FAILURE, errno, _("error reading \"%s\""), src_filename); 76 if (n_read == 0) 77 break; 78 79 if (full_write (dest_fd, buf, n_read) < n_read) 80 error (EXIT_FAILURE, errno, _("error writing \"%s\""), dest_filename); 81 } 82 83 if (close (dest_fd) < 0) 84 error (EXIT_FAILURE, errno, _("error writing \"%s\""), dest_filename); 85 if (close (src_fd) < 0) 86 error (EXIT_FAILURE, errno, _("error after reading \"%s\""), src_filename); 87 88 /* Preserve the access and modification times. */ 89 #if HAVE_UTIME 90 { 91 struct utimbuf ut; 92 93 ut.actime = statbuf.st_atime; 94 ut.modtime = statbuf.st_mtime; 95 utime (dest_filename, &ut); 96 } 97 #elif HAVE_UTIMES 98 { 99 struct timeval ut[2]; 100 101 ut[0].tv_sec = statbuf.st_atime; ut[0].tv_usec = 0; 102 ut[1].tv_sec = statbuf.st_mtime; ut[1].tv_usec = 0; 103 utimes (dest_filename, &ut); 104 } 105 #endif 106 107 #if HAVE_CHOWN 108 /* Preserve the owner and group. */ 109 chown (dest_filename, statbuf.st_uid, statbuf.st_gid); 110 #endif 111 112 /* Preserve the access permissions. */ 113 chmod (dest_filename, mode); 114 } 115