fstat: Fix module dependency conditions.
[gnulib/ericb.git] / lib / copy-file.c
blob462ea1cfd49a179cb7b70c6b1878177183b782d9
1 /* Copying of files.
2 Copyright (C) 2001-2003, 2006-2007, 2009-2017 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 <http://www.gnu.org/licenses/>. */
19 #include <config.h>
21 /* Specification. */
22 #include "copy-file.h"
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>
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 #include "xalloc.h"
43 #define _(str) gettext (str)
45 enum { IO_SIZE = 32 * 1024 };
47 int
48 qcopy_file_preserving (const char *src_filename, const char *dest_filename)
50 int err = 0;
51 int src_fd;
52 struct stat statbuf;
53 int mode;
54 int dest_fd;
55 char *buf = xmalloc (IO_SIZE);
57 src_fd = open (src_filename, O_RDONLY | O_BINARY);
58 if (src_fd < 0)
60 err = GL_COPY_ERR_OPEN_READ;
61 goto error;
63 if (fstat (src_fd, &statbuf) < 0)
65 err = GL_COPY_ERR_OPEN_READ;
66 goto error_src;
69 mode = statbuf.st_mode & 07777;
71 dest_fd = open (dest_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0600);
72 if (dest_fd < 0)
74 err = GL_COPY_ERR_OPEN_BACKUP_WRITE;
75 goto error_src;
78 /* Copy the file contents. */
79 for (;;)
81 size_t n_read = safe_read (src_fd, buf, IO_SIZE);
82 if (n_read == SAFE_READ_ERROR)
84 err = GL_COPY_ERR_READ;
85 goto error_src_dest;
87 if (n_read == 0)
88 break;
90 if (full_write (dest_fd, buf, n_read) < n_read)
92 err = GL_COPY_ERR_WRITE;
93 goto error_src_dest;
97 free (buf);
98 buf = NULL; /* To avoid double free in error case. */
100 #if !USE_ACL
101 if (close (dest_fd) < 0)
103 err = GL_COPY_ERR_WRITE;
104 goto error_src;
106 if (close (src_fd) < 0)
108 err = GL_COPY_ERR_AFTER_READ;
109 goto error;
111 #endif
113 /* Preserve the access and modification times. */
115 struct timespec ts[2];
117 ts[0] = get_stat_atime (&statbuf);
118 ts[1] = get_stat_mtime (&statbuf);
119 utimens (dest_filename, ts);
122 #if HAVE_CHOWN
123 /* Preserve the owner and group. */
124 ignore_value (chown (dest_filename, statbuf.st_uid, statbuf.st_gid));
125 #endif
127 /* Preserve the access permissions. */
128 #if USE_ACL
129 switch (qcopy_acl (src_filename, src_fd, dest_filename, dest_fd, mode))
131 case -2:
132 err = GL_COPY_ERR_GET_ACL;
133 goto error_src_dest;
134 case -1:
135 err = GL_COPY_ERR_SET_ACL;
136 goto error_src_dest;
138 #else
139 chmod (dest_filename, mode);
140 #endif
142 #if USE_ACL
143 if (close (dest_fd) < 0)
145 err = GL_COPY_ERR_WRITE;
146 goto error_src;
148 if (close (src_fd) < 0)
150 err = GL_COPY_ERR_AFTER_READ;
151 goto error;
153 #endif
155 return 0;
157 error_src_dest:
158 close (dest_fd);
159 error_src:
160 close (src_fd);
161 error:
162 free (buf);
163 return err;
166 void
167 copy_file_preserving (const char *src_filename, const char *dest_filename)
169 switch (qcopy_file_preserving (src_filename, dest_filename))
171 case 0:
172 return;
174 case GL_COPY_ERR_OPEN_READ:
175 error (EXIT_FAILURE, errno, _("error while opening %s for reading"),
176 quote (src_filename));
178 case GL_COPY_ERR_OPEN_BACKUP_WRITE:
179 error (EXIT_FAILURE, errno, _("cannot open backup file %s for writing"),
180 quote (dest_filename));
182 case GL_COPY_ERR_READ:
183 error (EXIT_FAILURE, errno, _("error reading %s"),
184 quote (src_filename));
186 case GL_COPY_ERR_WRITE:
187 error (EXIT_FAILURE, errno, _("error writing %s"),
188 quote (dest_filename));
190 case GL_COPY_ERR_AFTER_READ:
191 error (EXIT_FAILURE, errno, _("error after reading %s"),
192 quote (src_filename));
194 case GL_COPY_ERR_GET_ACL:
195 error (EXIT_FAILURE, errno, "%s", quote (src_filename));
197 case GL_COPY_ERR_SET_ACL:
198 error (EXIT_FAILURE, errno, _("preserving permissions for %s"),
199 quote (dest_filename));
201 default:
202 abort ();