2 Copyright (C) 2001-2003, 2006-2007, 2009-2025 Free Software Foundation, Inc.
3 Written by Bruno Haible <haible@clisp.cons.org>, 2001.
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.
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.
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/>. */
22 #include "copy-file.h"
32 #include "ignore-value.h"
33 #include "safe-read.h"
34 #include "full-write.h"
35 #include "stat-time.h"
38 #include "binary-io.h"
42 #define _(msgid) dgettext ("gnulib", msgid)
44 enum { IO_SIZE
= 32 * 1024 };
47 copy_file_internal (const char *src_filename
, const char *dest_filename
,
56 src_fd
= open (src_filename
, O_RDONLY
| O_BINARY
| O_CLOEXEC
);
58 return GL_COPY_ERR_OPEN_READ
;
59 if (fstat (src_fd
, &statbuf
) < 0)
61 err
= GL_COPY_ERR_OPEN_READ
;
65 mode
= statbuf
.st_mode
& 07777;
66 off_t inbytes
= S_ISREG (statbuf
.st_mode
) ? statbuf
.st_size
: -1;
67 bool empty_regular_file
= inbytes
== 0;
69 dest_fd
= open (dest_filename
,
70 O_WRONLY
| O_CREAT
| O_TRUNC
| O_BINARY
| O_CLOEXEC
,
71 /* If preserve is true, we must assume that the file may
72 have confidential contents. Therefore open it with mode
73 0600 and assign the permissions at the end.
74 If preserve is false, open it with mode 0666 & ~umask. */
75 preserve
? 0600 : 0666);
78 err
= GL_COPY_ERR_OPEN_BACKUP_WRITE
;
82 /* Copy the file contents. FIXME: Do not copy holes. */
86 copy_max
-= copy_max
% IO_SIZE
;
87 size_t len
= inbytes
< copy_max
? inbytes
: copy_max
;
88 ssize_t copied
= copy_file_range (src_fd
, NULL
, dest_fd
, NULL
, len
, 0);
94 /* Finish up with read/write, in case the file was not a regular
95 file, or the file shrank or had I/O errors (in which case find
96 whether it was a read or write error). Read empty regular files
97 since they might be in /proc with their true sizes unknown until
99 if (inbytes
!= 0 || empty_regular_file
)
102 int bufsize
= IO_SIZE
;
103 char *buf
= malloc (bufsize
);
105 buf
= smallbuf
, bufsize
= sizeof smallbuf
;
109 size_t n_read
= safe_read (src_fd
, buf
, bufsize
);
112 if (n_read
== SAFE_READ_ERROR
)
114 err
= GL_COPY_ERR_READ
;
117 if (full_write (dest_fd
, buf
, n_read
) < n_read
)
119 err
= GL_COPY_ERR_WRITE
;
131 if (close (dest_fd
) < 0)
133 err
= GL_COPY_ERR_WRITE
;
136 if (close (src_fd
) < 0)
137 return GL_COPY_ERR_AFTER_READ
;
142 /* Preserve the access and modification times. */
144 struct timespec ts
[2];
146 ts
[0] = get_stat_atime (&statbuf
);
147 ts
[1] = get_stat_mtime (&statbuf
);
148 utimens (dest_filename
, ts
);
152 /* Preserve the owner and group. */
153 ignore_value (chown (dest_filename
, statbuf
.st_uid
, statbuf
.st_gid
));
156 /* Preserve the access permissions. */
158 switch (qcopy_acl (src_filename
, src_fd
, dest_filename
, dest_fd
, mode
))
161 err
= GL_COPY_ERR_GET_ACL
;
164 err
= GL_COPY_ERR_SET_ACL
;
168 chmod (dest_filename
, mode
);
173 if (close (dest_fd
) < 0)
175 err
= GL_COPY_ERR_WRITE
;
178 if (close (src_fd
) < 0)
179 return GL_COPY_ERR_AFTER_READ
;
192 qcopy_file_preserving (const char *src_filename
, const char *dest_filename
)
194 return copy_file_internal (src_filename
, dest_filename
, true);
198 copy_file_to (const char *src_filename
, const char *dest_filename
)
200 return copy_file_internal (src_filename
, dest_filename
, false);
204 handle_error_code (int err
, const char *src_filename
, const char *dest_filename
)
211 case GL_COPY_ERR_OPEN_READ
:
212 error (EXIT_FAILURE
, errno
, _("error while opening %s for reading"),
213 quote (src_filename
));
215 case GL_COPY_ERR_OPEN_BACKUP_WRITE
:
216 error (EXIT_FAILURE
, errno
, _("cannot open backup file %s for writing"),
217 quote (dest_filename
));
219 case GL_COPY_ERR_READ
:
220 error (EXIT_FAILURE
, errno
, _("error reading %s"),
221 quote (src_filename
));
223 case GL_COPY_ERR_WRITE
:
224 error (EXIT_FAILURE
, errno
, _("error writing %s"),
225 quote (dest_filename
));
227 case GL_COPY_ERR_AFTER_READ
:
228 error (EXIT_FAILURE
, errno
, _("error after reading %s"),
229 quote (src_filename
));
231 case GL_COPY_ERR_GET_ACL
:
232 error (EXIT_FAILURE
, errno
, "%s", quote (src_filename
));
234 case GL_COPY_ERR_SET_ACL
:
235 error (EXIT_FAILURE
, errno
, _("preserving permissions for %s"),
236 quote (dest_filename
));
244 xcopy_file_preserving (const char *src_filename
, const char *dest_filename
)
246 int err
= qcopy_file_preserving (src_filename
, dest_filename
);
247 handle_error_code (err
, src_filename
, dest_filename
);
251 copy_file_preserving (const char *src_filename
, const char *dest_filename
)
253 xcopy_file_preserving (src_filename
, dest_filename
);
257 xcopy_file_to (const char *src_filename
, const char *dest_filename
)
259 int err
= copy_file_to (src_filename
, dest_filename
);
260 handle_error_code (err
, src_filename
, dest_filename
);