Branch data 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 : : goto done;
46 : : }
47 : :
48 : 0 : tmp_ctx = talloc_new(NULL);
49 [ # # ]: 0 : if (!tmp_ctx) {
50 : : ret = ENOMEM;
51 : : 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 : : ret = ENOMEM;
63 : : 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 : : 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 : : 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 : : 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 : : goto done;
103 : : }
104 : :
105 [ # # ]: 0 : if (written != numread) {
106 [ # # ][ # # ]: 0 : DEBUG(dbglvl, ("Wrote %d bytes expected %d bytes\n",
[ # # ][ # # ]
[ # # ]
107 : : written, numread));
108 : : ret = EIO;
109 : : goto done;
110 : : }
111 : : }
112 : :
113 : : 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 : : }
|