This source file includes following definitions.
- qcopy_file_preserving
- copy_file_preserving
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include <config.h>
20
21
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)
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
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
90
91
92
93
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
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
146 ignore_value (chown (dest_filename, statbuf.st_uid, statbuf.st_gid));
147 #endif
148
149
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)
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 }