root/maint/gnulib/lib/copy-file.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. qcopy_file_preserving
  2. copy_file_preserving

   1 /* Copying of files.
   2    Copyright (C) 2001-2003, 2006-2007, 2009-2021 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 <https://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 #include "error.h"
  32 #include "ignore-value.h"
  33 #include "safe-read.h"
  34 #include "full-write.h"
  35 #include "stat-time.h"
  36 #include "utimens.h"
  37 #include "acl.h"
  38 #include "binary-io.h"
  39 #include "quote.h"
  40 #include "gettext.h"
  41 
  42 #define _(str) gettext (str)
  43 
  44 enum { IO_SIZE = 32 * 1024 };
  45 
  46 int
  47 qcopy_file_preserving (const char *src_filename, const char *dest_filename)
     /* [previous][next][first][last][top][bottom][index][help] */
  48 {
  49   int err = 0;
  50   int src_fd;
  51   struct stat statbuf;
  52   int mode;
  53   int dest_fd;
  54 
  55   src_fd = open (src_filename, O_RDONLY | O_BINARY | O_CLOEXEC);
  56   if (src_fd < 0)
  57     return GL_COPY_ERR_OPEN_READ;
  58   if (fstat (src_fd, &statbuf) < 0)
  59     {
  60       err = GL_COPY_ERR_OPEN_READ;
  61       goto error_src;
  62     }
  63 
  64   mode = statbuf.st_mode & 07777;
  65   off_t inbytes = S_ISREG (statbuf.st_mode) ? statbuf.st_size : -1;
  66   bool empty_regular_file = inbytes == 0;
  67 
  68   dest_fd = open (dest_filename,
  69                   O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_CLOEXEC,
  70                   0600);
  71   if (dest_fd < 0)
  72     {
  73       err = GL_COPY_ERR_OPEN_BACKUP_WRITE;
  74       goto error_src;
  75     }
  76 
  77   /* Copy the file contents.  FIXME: Do not copy holes.  */
  78   while (0 < inbytes)
  79     {
  80       size_t copy_max = -1;
  81       copy_max -= copy_max % IO_SIZE;
  82       size_t len = inbytes < copy_max ? inbytes : copy_max;
  83       ssize_t copied = copy_file_range (src_fd, NULL, dest_fd, NULL, len, 0);
  84       if (copied <= 0)
  85         break;
  86       inbytes -= copied;
  87     }
  88 
  89   /* Finish up with read/write, in case the file was not a regular
  90      file, or the file shrank or had I/O errors (in which case find
  91      whether it was a read or write error).  Read empty regular files
  92      since they might be in /proc with their true sizes unknown until
  93      they are read.  */
  94   if (inbytes != 0 || empty_regular_file)
  95     {
  96       char smallbuf[1024];
  97       int bufsize = IO_SIZE;
  98       char *buf = malloc (bufsize);
  99       if (!buf)
 100         buf = smallbuf, bufsize = sizeof smallbuf;
 101 
 102       while (true)
 103         {
 104           size_t n_read = safe_read (src_fd, buf, bufsize);
 105           if (n_read == 0)
 106             break;
 107           if (n_read == SAFE_READ_ERROR)
 108             {
 109               err = GL_COPY_ERR_READ;
 110               break;
 111             }
 112           if (full_write (dest_fd, buf, n_read) < n_read)
 113             {
 114               err = GL_COPY_ERR_WRITE;
 115               break;
 116             }
 117         }
 118 
 119       if (buf != smallbuf)
 120         free (buf);
 121       if (err)
 122         goto error_src_dest;
 123     }
 124 
 125 #if !USE_ACL
 126   if (close (dest_fd) < 0)
 127     {
 128       err = GL_COPY_ERR_WRITE;
 129       goto error_src;
 130     }
 131   if (close (src_fd) < 0)
 132     return GL_COPY_ERR_AFTER_READ;
 133 #endif
 134 
 135   /* Preserve the access and modification times.  */
 136   {
 137     struct timespec ts[2];
 138 
 139     ts[0] = get_stat_atime (&statbuf);
 140     ts[1] = get_stat_mtime (&statbuf);
 141     utimens (dest_filename, ts);
 142   }
 143 
 144 #if HAVE_CHOWN
 145   /* Preserve the owner and group.  */
 146   ignore_value (chown (dest_filename, statbuf.st_uid, statbuf.st_gid));
 147 #endif
 148 
 149   /* Preserve the access permissions.  */
 150 #if USE_ACL
 151   switch (qcopy_acl (src_filename, src_fd, dest_filename, dest_fd, mode))
 152     {
 153     case -2:
 154       err = GL_COPY_ERR_GET_ACL;
 155       goto error_src_dest;
 156     case -1:
 157       err = GL_COPY_ERR_SET_ACL;
 158       goto error_src_dest;
 159     }
 160 #else
 161   chmod (dest_filename, mode);
 162 #endif
 163 
 164 #if USE_ACL
 165   if (close (dest_fd) < 0)
 166     {
 167       err = GL_COPY_ERR_WRITE;
 168       goto error_src;
 169     }
 170   if (close (src_fd) < 0)
 171     return GL_COPY_ERR_AFTER_READ;
 172 #endif
 173 
 174   return 0;
 175 
 176  error_src_dest:
 177   close (dest_fd);
 178  error_src:
 179   close (src_fd);
 180   return err;
 181 }
 182 
 183 void
 184 copy_file_preserving (const char *src_filename, const char *dest_filename)
     /* [previous][next][first][last][top][bottom][index][help] */
 185 {
 186   switch (qcopy_file_preserving (src_filename, dest_filename))
 187     {
 188     case 0:
 189       return;
 190 
 191     case GL_COPY_ERR_OPEN_READ:
 192       error (EXIT_FAILURE, errno, _("error while opening %s for reading"),
 193              quote (src_filename));
 194 
 195     case GL_COPY_ERR_OPEN_BACKUP_WRITE:
 196       error (EXIT_FAILURE, errno, _("cannot open backup file %s for writing"),
 197              quote (dest_filename));
 198 
 199     case GL_COPY_ERR_READ:
 200       error (EXIT_FAILURE, errno, _("error reading %s"),
 201              quote (src_filename));
 202 
 203     case GL_COPY_ERR_WRITE:
 204       error (EXIT_FAILURE, errno, _("error writing %s"),
 205              quote (dest_filename));
 206 
 207     case GL_COPY_ERR_AFTER_READ:
 208       error (EXIT_FAILURE, errno, _("error after reading %s"),
 209              quote (src_filename));
 210 
 211     case GL_COPY_ERR_GET_ACL:
 212       error (EXIT_FAILURE, errno, "%s", quote (src_filename));
 213 
 214     case GL_COPY_ERR_SET_ACL:
 215       error (EXIT_FAILURE, errno, _("preserving permissions for %s"),
 216              quote (dest_filename));
 217 
 218     default:
 219       abort ();
 220     }
 221 }

/* [previous][next][first][last][top][bottom][index][help] */