2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2008 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 static int my_cmp(void *item1, void *item2)
49 elt1 = (CurFile *) item1;
50 elt2 = (CurFile *) item2;
51 return strcmp(elt1->fname, elt2->fname);
54 static bool accurate_mark_file_as_seen(JCR *jcr, CurFile *elt)
56 /* TODO: just use elt->seen = 1 */
57 CurFile *temp = (CurFile *)jcr->file_list->search(elt, my_cmp);
59 temp->seen = 1; /* records are in memory */
64 static bool accurate_lookup(JCR *jcr, char *fname, CurFile *ret)
71 CurFile *temp = (CurFile *)jcr->file_list->search(&search, my_cmp);
73 memcpy(ret, temp, sizeof(CurFile));
75 // Dmsg1(dbglvl, "lookup <%s> ok\n", fname);
81 static bool accurate_init(JCR *jcr, int nbfile)
84 jcr->file_list = New(rblist(elt, &elt->link));
88 /* This function is called at the end of backup
89 * We walk over all hash disk element, and we check
92 bool accurate_send_deleted_list(JCR *jcr)
96 int stream = STREAM_UNIX_ATTRIBUTES;
98 if (!jcr->accurate || jcr->get_JobLevel() == L_FULL) {
102 if (jcr->file_list == NULL) {
106 ff_pkt = init_find_files();
107 ff_pkt->type = FT_DELETED;
109 foreach_rblist(elt, jcr->file_list) {
110 if (!elt->seen) { /* already seen */
111 // Dmsg2(dbglvl, "deleted fname=%s seen=%i\n", elt->fname, elt->seen);
112 ff_pkt->fname = elt->fname;
113 ff_pkt->statp.st_mtime = elt->mtime;
114 ff_pkt->statp.st_ctime = elt->ctime;
115 encode_and_send_attributes(jcr, ff_pkt, stream);
120 term_find_files(ff_pkt);
122 /* TODO: clean htable when this function is not reached ? */
123 if (jcr->file_list) {
124 delete jcr->file_list;
125 jcr->file_list = NULL;
130 static bool accurate_add_file(JCR *jcr, char *fname, char *lstat)
136 decode_stat(lstat, &statp, &LinkFIc); /* decode catalog stat */
137 elt.ctime = statp.st_ctime;
138 elt.mtime = statp.st_mtime;
142 /* we store CurFile, fname and ctime/mtime in the same chunk */
143 item = (CurFile *)malloc(sizeof(CurFile)+strlen(fname)+1);
144 memcpy(item, &elt, sizeof(CurFile));
145 item->fname = (char *)item+sizeof(CurFile);
146 strcpy(item->fname, fname);
147 jcr->file_list->insert(item, my_cmp);
149 // Dmsg2(dbglvl, "add fname=<%s> lstat=%s\n", fname, lstat);
154 * This function is called for each file seen in fileset.
155 * We check in file_list hash if fname have been backuped
156 * the last time. After we can compare Lstat field.
157 * Full Lstat usage have been removed on 6612
159 bool accurate_check_file(JCR *jcr, FF_PKT *ff_pkt)
165 if (!jcr->accurate || jcr->get_JobLevel() == L_FULL) {
171 if (S_ISDIR(ff_pkt->statp.st_mode)) {
172 fname = ff_pkt->link;
174 fname = ff_pkt->fname;
177 if (!accurate_lookup(jcr, fname, &elt)) {
178 Dmsg1(dbglvl, "accurate %s (not found)\n", fname);
183 if (elt.seen) { /* file has been seen ? */
184 Dmsg1(dbglvl, "accurate %s (already seen)\n", fname);
188 if (elt.mtime != ff_pkt->statp.st_mtime) {
189 // Jmsg(jcr, M_SAVED, 0, _("%s st_mtime differs\n"), fname);
190 Dmsg1(dbglvl, "%s st_mtime differs\n", fname);
192 } else if (elt.ctime != ff_pkt->statp.st_ctime) {
193 // Jmsg(jcr, M_SAVED, 0, _("%s st_ctime differs\n"), fname);
194 Dmsg1(dbglvl, "%s st_ctime differs\n", fname);
198 accurate_mark_file_as_seen(jcr, &elt);
199 // Dmsg2(dbglvl, "accurate %s = %i\n", fname, stat);
202 unstrip_path(ff_pkt);
207 * TODO: use big buffer from htable
209 int accurate_cmd(JCR *jcr)
211 BSOCK *dir = jcr->dir_bsock;
215 if (!jcr->accurate || job_canceled(jcr) || jcr->get_JobLevel()==L_FULL) {
219 if (sscanf(dir->msg, "accurate files=%ld", &nb) != 1) {
220 dir->fsend(_("2991 Bad accurate command\n"));
224 accurate_init(jcr, nb);
227 * buffer = sizeof(CurFile) + dirmsg
228 * dirmsg = fname + \0 + lstat
230 /* get current files */
231 while (dir->recv() >= 0) {
232 len = strlen(dir->msg) + 1;
233 if (len < dir->msglen) {
234 accurate_add_file(jcr, dir->msg, dir->msg + len);
239 extern void *start_heap;
241 char b1[50], b2[50], b3[50], b4[50], b5[50];
242 Dmsg5(dbglvl," Heap: heap=%s smbytes=%s max_bytes=%s bufs=%s max_bufs=%s\n",
243 edit_uint64_with_commas((char *)sbrk(0)-(char *)start_heap, b1),
244 edit_uint64_with_commas(sm_bytes, b2),
245 edit_uint64_with_commas(sm_max_bytes, b3),
246 edit_uint64_with_commas(sm_buffers, b4),
247 edit_uint64_with_commas(sm_max_buffers, b5));