2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2009 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version two of the GNU General Public
10 License as published by the Free Software Foundation and included
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of Kern Sibbald.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
36 static int dbglvl=200;
38 typedef struct PrivateCurFile {
46 bool accurate_mark_file_as_seen(JCR *jcr, char *fname)
48 if (!jcr->accurate || !jcr->file_list) {
51 /* TODO: just use elt->seen = 1 */
52 CurFile *temp = (CurFile *)jcr->file_list->lookup(fname);
54 temp->seen = 1; /* records are in memory */
59 static bool accurate_mark_file_as_seen(JCR *jcr, CurFile *elt)
61 /* TODO: just use elt->seen = 1 */
62 CurFile *temp = (CurFile *)jcr->file_list->lookup(elt->fname);
64 temp->seen = 1; /* records are in memory */
69 static bool accurate_lookup(JCR *jcr, char *fname, CurFile *ret)
74 CurFile *temp = (CurFile *)jcr->file_list->lookup(fname);
76 memcpy(ret, temp, sizeof(CurFile));
78 Dmsg1(dbglvl, "lookup <%s> ok\n", fname);
84 static bool accurate_init(JCR *jcr, int nbfile)
87 jcr->file_list = (htable *)malloc(sizeof(htable));
88 jcr->file_list->init(elt, &elt->link, nbfile);
92 /* This function is called at the end of backup
93 * We walk over all hash disk element, and we check
96 bool accurate_send_deleted_list(JCR *jcr)
100 int stream = STREAM_UNIX_ATTRIBUTES;
102 if (!jcr->accurate || jcr->get_JobLevel() == L_FULL) {
106 if (jcr->file_list == NULL) {
110 ff_pkt = init_find_files();
111 ff_pkt->type = FT_DELETED;
113 foreach_htable(elt, jcr->file_list) {
114 if (elt->seen || plugin_check_file(jcr, elt->fname)) {
117 Dmsg2(dbglvl, "deleted fname=%s seen=%i\n", elt->fname, elt->seen);
118 ff_pkt->fname = elt->fname;
119 ff_pkt->statp.st_mtime = elt->mtime;
120 ff_pkt->statp.st_ctime = elt->ctime;
121 encode_and_send_attributes(jcr, ff_pkt, stream);
125 term_find_files(ff_pkt);
127 /* TODO: clean htable when this function is not reached ? */
128 if (jcr->file_list) {
129 jcr->file_list->destroy();
130 free(jcr->file_list);
131 jcr->file_list = NULL;
136 static bool accurate_add_file(JCR *jcr, char *fname, char *lstat)
142 decode_stat(lstat, &statp, &LinkFIc); /* decode catalog stat */
143 elt.ctime = statp.st_ctime;
144 elt.mtime = statp.st_mtime;
148 /* we store CurFile, fname and ctime/mtime in the same chunk */
149 item = (CurFile *)jcr->file_list->hash_malloc(sizeof(CurFile)+strlen(fname)+1);
150 memcpy(item, &elt, sizeof(CurFile));
151 item->fname = (char *)item+sizeof(CurFile);
152 strcpy(item->fname, fname);
153 jcr->file_list->insert(item->fname, item);
155 Dmsg2(dbglvl, "add fname=<%s> lstat=%s\n", fname, lstat);
160 * This function is called for each file seen in fileset.
161 * We check in file_list hash if fname have been backuped
162 * the last time. After we can compare Lstat field.
163 * Full Lstat usage have been removed on 6612
165 bool accurate_check_file(JCR *jcr, FF_PKT *ff_pkt)
171 if (!jcr->accurate || jcr->get_JobLevel() == L_FULL) {
177 if (S_ISDIR(ff_pkt->statp.st_mode)) {
178 fname = ff_pkt->link;
180 fname = ff_pkt->fname;
183 if (!accurate_lookup(jcr, fname, &elt)) {
184 Dmsg1(dbglvl, "accurate %s (not found)\n", fname);
189 if (elt.seen) { /* file has been seen ? */
190 Dmsg1(dbglvl, "accurate %s (already seen)\n", fname);
195 * We check only mtime/ctime like with the normal
196 * incremental/differential mode
198 if (elt.mtime != ff_pkt->statp.st_mtime) {
199 // Jmsg(jcr, M_SAVED, 0, _("%s st_mtime differs\n"), fname);
200 Dmsg3(dbglvl, "%s st_mtime differs (%i!=%i)\n",
201 fname, elt.mtime, ff_pkt->statp.st_mtime);
203 } else if (!(ff_pkt->flags & FO_MTIMEONLY)
204 && (elt.ctime != ff_pkt->statp.st_ctime)) {
205 // Jmsg(jcr, M_SAVED, 0, _("%s st_ctime differs\n"), fname);
206 Dmsg3(dbglvl, "%s st_ctime differs\n",
207 fname, elt.ctime, ff_pkt->statp.st_ctime);
211 accurate_mark_file_as_seen(jcr, &elt);
212 // Dmsg2(dbglvl, "accurate %s = %i\n", fname, stat);
215 unstrip_path(ff_pkt);
220 * TODO: use big buffer from htable
222 int accurate_cmd(JCR *jcr)
224 BSOCK *dir = jcr->dir_bsock;
228 if (!jcr->accurate || job_canceled(jcr) || jcr->get_JobLevel()==L_FULL) {
232 if (sscanf(dir->msg, "accurate files=%ld", &nb) != 1) {
233 dir->fsend(_("2991 Bad accurate command\n"));
237 accurate_init(jcr, nb);
240 * buffer = sizeof(CurFile) + dirmsg
241 * dirmsg = fname + \0 + lstat
243 /* get current files */
244 while (dir->recv() >= 0) {
245 len = strlen(dir->msg) + 1;
246 if (len < dir->msglen) {
247 accurate_add_file(jcr, dir->msg, dir->msg + len);
252 extern void *start_heap;
254 char b1[50], b2[50], b3[50], b4[50], b5[50];
255 Dmsg5(dbglvl," Heap: heap=%s smbytes=%s max_bytes=%s bufs=%s max_bufs=%s\n",
256 edit_uint64_with_commas((char *)sbrk(0)-(char *)start_heap, b1),
257 edit_uint64_with_commas(sm_bytes, b2),
258 edit_uint64_with_commas(sm_max_bytes, b3),
259 edit_uint64_with_commas(sm_buffers, b4),
260 edit_uint64_with_commas(sm_max_buffers, b5));