+2024-08-24 Bruno Haible <bruno@clisp.org>
+
+ copy-file: Add functions for copying non-confidential files.
+ Reported by Patrice Dumas <pertusus@free.fr> in
+ <https://lists.gnu.org/archive/html/bug-gnulib/2024-08/msg00142.html>.
+ * lib/copy-file.h (copy_file_to, xcopy_file_to): New declarations.
+ * lib/copy-file.c (copy_file_internal): New function, extracted from
+ qcopy_file_preserving.
+ (qcopy_file_preserving): Invoke it.
+ (copy_file_to): New function.
+ (handle_error_code): New function, extracted from xcopy_file_preserving.
+ (xcopy_file_preserving): Invoke it.
+ (xcopy_file_to): New function.
+
2024-08-24 Bruno Haible <bruno@clisp.org>
copy-file: First step towards more consistent function names.
enum { IO_SIZE = 32 * 1024 };
-int
-qcopy_file_preserving (const char *src_filename, const char *dest_filename)
+static int
+copy_file_internal (const char *src_filename, const char *dest_filename,
+ bool preserve)
{
int err = 0;
int src_fd;
dest_fd = open (dest_filename,
O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_CLOEXEC,
- 0600);
+ /* If preserve is true, we must assume that the file may
+ have confidential contents. Therefore open it with mode
+ 0600 and assign the permissions at the end.
+ If preserve is false, open it with mode 0666 & ~umask. */
+ preserve ? 0600 : 0666);
if (dest_fd < 0)
{
err = GL_COPY_ERR_OPEN_BACKUP_WRITE;
return GL_COPY_ERR_AFTER_READ;
#endif
- /* Preserve the access and modification times. */
- {
- struct timespec ts[2];
+ if (preserve)
+ {
+ /* Preserve the access and modification times. */
+ {
+ struct timespec ts[2];
- ts[0] = get_stat_atime (&statbuf);
- ts[1] = get_stat_mtime (&statbuf);
- utimens (dest_filename, ts);
- }
+ ts[0] = get_stat_atime (&statbuf);
+ ts[1] = get_stat_mtime (&statbuf);
+ utimens (dest_filename, ts);
+ }
#if HAVE_CHOWN
- /* Preserve the owner and group. */
- ignore_value (chown (dest_filename, statbuf.st_uid, statbuf.st_gid));
+ /* Preserve the owner and group. */
+ ignore_value (chown (dest_filename, statbuf.st_uid, statbuf.st_gid));
#endif
- /* Preserve the access permissions. */
+ /* Preserve the access permissions. */
#if USE_ACL
- switch (qcopy_acl (src_filename, src_fd, dest_filename, dest_fd, mode))
- {
- case -2:
- err = GL_COPY_ERR_GET_ACL;
- goto error_src_dest;
- case -1:
- err = GL_COPY_ERR_SET_ACL;
- goto error_src_dest;
- }
+ switch (qcopy_acl (src_filename, src_fd, dest_filename, dest_fd, mode))
+ {
+ case -2:
+ err = GL_COPY_ERR_GET_ACL;
+ goto error_src_dest;
+ case -1:
+ err = GL_COPY_ERR_SET_ACL;
+ goto error_src_dest;
+ }
#else
- chmod (dest_filename, mode);
+ chmod (dest_filename, mode);
#endif
+ }
#if USE_ACL
if (close (dest_fd) < 0)
return err;
}
-void
-xcopy_file_preserving (const char *src_filename, const char *dest_filename)
+int
+qcopy_file_preserving (const char *src_filename, const char *dest_filename)
+{
+ return copy_file_internal (src_filename, dest_filename, true);
+}
+
+int
+copy_file_to (const char *src_filename, const char *dest_filename)
{
- switch (qcopy_file_preserving (src_filename, dest_filename))
+ return copy_file_internal (src_filename, dest_filename, false);
+}
+
+static void
+handle_error_code (int err, const char *src_filename, const char *dest_filename)
+{
+ switch (err)
{
case 0:
return;
}
}
+void
+xcopy_file_preserving (const char *src_filename, const char *dest_filename)
+{
+ int err = qcopy_file_preserving (src_filename, dest_filename);
+ handle_error_code (err, src_filename, dest_filename);
+}
+
void
copy_file_preserving (const char *src_filename, const char *dest_filename)
{
xcopy_file_preserving (src_filename, dest_filename);
}
+
+void
+xcopy_file_to (const char *src_filename, const char *dest_filename)
+{
+ int err = copy_file_to (src_filename, dest_filename);
+ handle_error_code (err, src_filename, dest_filename);
+}
#endif
-/* Error codes returned by qcopy_file_preserving. */
+/* Error codes returned by qcopy_file_preserving or copy_file_to. */
enum
{
GL_COPY_ERR_OPEN_READ = -1,
GL_COPY_ERR_SET_ACL = -7
};
+
/* Copy a regular file: from src_filename to dest_filename.
The destination file is assumed to be a backup file.
Modification times, owner, group and access permissions are preserved as
- far as possible.
+ far as possible (similarly to what 'cp -p SRC DEST' would do).
Return 0 if successful, otherwise set errno and return one of the error
codes above. */
extern int qcopy_file_preserving (const char *src_filename, const char *dest_filename);
/* Copy a regular file: from src_filename to dest_filename.
The destination file is assumed to be a backup file.
Modification times, owner, group and access permissions are preserved as
- far as possible.
+ far as possible (similarly to what 'cp -p SRC DEST' would do).
Exit upon failure. */
extern void xcopy_file_preserving (const char *src_filename, const char *dest_filename);
_GL_ATTRIBUTE_DEPRECATED void copy_file_preserving (const char *src_filename, const char *dest_filename);
+/* Copy a regular file: from src_filename to dest_filename.
+ The source file is assumed to be not confidential.
+ Modification times, owner, group and access permissions of src_filename
+ are *not* copied over to dest_filename (similarly to what 'cat SRC > DEST'
+ would do; if DEST already exists, this is the same as what 'cp SRC DEST'
+ would do.)
+ Return 0 if successful, otherwise set errno and return one of the error
+ codes above. */
+extern int copy_file_to (const char *src_filename, const char *dest_filename);
+
+/* Copy a regular file: from src_filename to dest_filename.
+ The source file is assumed to be not confidential.
+ Modification times, owner, group and access permissions of src_filename
+ are *not* copied over to dest_filename (similarly to what 'cat SRC > DEST'
+ would do; if DEST already exists, this is the same as what 'cp SRC DEST'
+ would do.)
+ Exit upon failure. */
+extern void xcopy_file_to (const char *src_filename, const char *dest_filename);
+
+
#ifdef __cplusplus
}
#endif