Line data Source code
1 : /*
2 : SSSD
3 :
4 : Backup files
5 :
6 : Copyright (C) Simo Sorce 2009
7 :
8 : This program is free software; you can redistribute it and/or modify
9 : it under the terms of the GNU General Public License as published by
10 : the Free Software Foundation; either version 3 of the License, or
11 : (at your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program. If not, see <http://www.gnu.org/licenses/>.
20 : */
21 :
22 : #include "util/util.h"
23 : #include <fcntl.h>
24 : #include <stddef.h>
25 : #include <stdlib.h>
26 :
27 : #define BUFFER_SIZE 65536
28 :
29 0 : int backup_file(const char *src_file, int dbglvl)
30 : {
31 0 : TALLOC_CTX *tmp_ctx = NULL;
32 : char buf[BUFFER_SIZE];
33 0 : int src_fd = -1;
34 0 : int dst_fd = -1;
35 : char *dst_file;
36 : ssize_t numread;
37 : ssize_t written;
38 : int ret, i;
39 :
40 0 : src_fd = open(src_file, O_RDONLY);
41 0 : if (src_fd < 0) {
42 0 : ret = errno;
43 0 : DEBUG(dbglvl, "Error (%d [%s]) opening source file %s\n",
44 : ret, strerror(ret), src_file);
45 0 : goto done;
46 : }
47 :
48 0 : tmp_ctx = talloc_new(NULL);
49 0 : if (!tmp_ctx) {
50 0 : ret = ENOMEM;
51 0 : goto done;
52 : }
53 :
54 : /* try a few times to come up with a new backup file, then give up */
55 0 : for (i = 0; i < 10; i++) {
56 0 : if (i == 0) {
57 0 : dst_file = talloc_asprintf(tmp_ctx, "%s.bak", src_file);
58 : } else {
59 0 : dst_file = talloc_asprintf(tmp_ctx, "%s.bak%d", src_file, i);
60 : }
61 0 : if (!dst_file) {
62 0 : ret = ENOMEM;
63 0 : goto done;
64 : }
65 :
66 0 : errno = 0;
67 0 : dst_fd = open(dst_file, O_CREAT|O_EXCL|O_WRONLY, 0600);
68 0 : ret = errno;
69 :
70 0 : if (dst_fd >= 0) break;
71 :
72 0 : if (ret != EEXIST) {
73 0 : DEBUG(dbglvl, "Error (%d [%s]) opening destination file %s\n",
74 : ret, strerror(ret), dst_file);
75 0 : goto done;
76 : }
77 : }
78 0 : if (ret != 0) {
79 0 : DEBUG(dbglvl, "Error (%d [%s]) opening destination file %s\n",
80 : ret, strerror(ret), dst_file);
81 0 : goto done;
82 : }
83 :
84 : /* copy file contents */
85 : while (1) {
86 0 : errno = 0;
87 0 : numread = sss_atomic_read_s(src_fd, buf, BUFFER_SIZE);
88 0 : if (numread < 0) {
89 0 : ret = errno;
90 0 : DEBUG(dbglvl, "Error (%d [%s]) reading from source %s\n",
91 : ret, strerror(ret), src_file);
92 0 : goto done;
93 : }
94 0 : if (numread == 0) break;
95 :
96 0 : errno = 0;
97 0 : written = sss_atomic_write_s(dst_fd, buf, numread);
98 0 : if (written == -1) {
99 0 : ret = errno;
100 0 : DEBUG(dbglvl, "Error (%d [%s]) writing to destination %s\n",
101 : ret, strerror(ret), dst_file);
102 0 : goto done;
103 : }
104 :
105 0 : if (written != numread) {
106 0 : DEBUG(dbglvl, "Wrote %zd bytes expected %zd bytes\n",
107 : written, numread);
108 0 : ret = EIO;
109 0 : goto done;
110 : }
111 0 : }
112 :
113 0 : ret = EOK;
114 :
115 : done:
116 0 : if (src_fd != -1) close(src_fd);
117 0 : if (dst_fd != -1) close(dst_fd);
118 0 : talloc_free(tmp_ctx);
119 0 : return ret;
120 : }
|