2 $Id: cmd_dbd_scanvol.c,v 1.8 2009-09-14 02:56:19 didg Exp $
4 Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
19 #endif /* HAVE_CONFIG_H */
23 #include <sys/types.h>
30 #include <atalk/adouble.h>
31 #include <atalk/unicode.h>
32 #include <atalk/volinfo.h>
33 #include <atalk/cnid_dbd_private.h>
39 /* Some defines to ease code parsing */
40 #define ADDIR_OK (addir_ok == 0)
41 #define ADFILE_OK (adfile_ok == 0)
43 /* These must be accessible for cmd_dbd_* funcs */
44 struct volinfo *volinfo;
45 char cwdbuf[MAXPATHLEN+1];
47 /* Some static vars */
49 static DBD *dbd_rebuild;
50 static dbd_flags_t dbd_flags;
51 static char stamp[CNID_DEV_LEN];
52 static char *netatalk_dirs[] = {
57 static struct cnid_dbd_rqst rqst;
58 static struct cnid_dbd_rply rply;
62 Taken form afpd/desktop.c
64 static char *utompath(char *upath)
66 static char mpath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */
68 uint16_t flags = CONV_IGNORE | CONV_UNESCAPEHEX;
76 outlen = strlen(upath);
78 if ((volinfo->v_casefold & AFPVOL_UTOMUPPER))
79 flags |= CONV_TOUPPER;
80 else if ((volinfo->v_casefold & AFPVOL_UTOMLOWER))
81 flags |= CONV_TOLOWER;
83 if ((volinfo->v_flags & AFPVOL_EILSEQ)) {
84 flags |= CONV__EILSEQ;
87 /* convert charsets */
88 if ((size_t)-1 == ( outlen = convert_charset(volinfo->v_volcharset,
90 volinfo->v_maccharset,
91 u, outlen, mpath, MAXPATHLEN, &flags)) ) {
92 dbd_log( LOGSTD, "Conversion from %s to %s for %s failed.",
93 volinfo->v_volcodepage, volinfo->v_maccodepage, u);
101 Taken form afpd/desktop.c
103 static char *mtoupath(char *mpath)
105 static char upath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */
114 if ( *mpath == '\0' ) {
118 /* set conversion flags */
119 if (!(volinfo->v_flags & AFPVOL_NOHEX))
120 flags |= CONV_ESCAPEHEX;
121 if (!(volinfo->v_flags & AFPVOL_USEDOTS))
122 flags |= CONV_ESCAPEDOTS;
124 if ((volinfo->v_casefold & AFPVOL_MTOUUPPER))
125 flags |= CONV_TOUPPER;
126 else if ((volinfo->v_casefold & AFPVOL_MTOULOWER))
127 flags |= CONV_TOLOWER;
129 if ((volinfo->v_flags & AFPVOL_EILSEQ)) {
130 flags |= CONV__EILSEQ;
139 if ((size_t)-1 == (outlen = convert_charset(CH_UTF8_MAC,
140 volinfo->v_volcharset,
141 volinfo->v_maccharset,
142 m, inplen, u, outlen, &flags)) ) {
143 dbd_log( LOGSTD, "conversion from UTF8-MAC to %s for %s failed.",
144 volinfo->v_volcodepage, mpath);
152 Check for wrong encoding e.g. "." at the beginning is not CAP encoded (:2e) although volume is default !AFPVOL_USEDOTS.
153 We do it by roundtripiping from volcharset to UTF8-MAC and back and then compare the result.
155 static int check_name_encoding(char *uname)
159 roundtripped = mtoupath(utompath(uname));
161 dbd_log( LOGSTD, "Error checking encoding for '%s/%s'", cwdbuf, uname);
165 if ( STRCMP(uname, !=, roundtripped)) {
166 dbd_log( LOGSTD, "Bad encoding for '%s/%s'", cwdbuf, uname);
174 Check for netatalk special folders e.g. ".AppleDB" or ".AppleDesktop"
175 Returns pointer to name or NULL.
177 static const char *check_netatalk_dirs(const char *name)
181 for (c=0; netatalk_dirs[c]; c++) {
182 if ((strcmp(name, netatalk_dirs[c])) == 0)
183 return netatalk_dirs[c];
189 Check for .AppleDouble file, create if missing
191 static int check_adfile(const char *fname, const struct stat *st)
197 if (S_ISREG(st->st_mode))
200 adflags = ADFLAGS_DIR;
202 adname = volinfo->ad_path(fname, adflags);
204 if ((ret = access( adname, F_OK)) != 0) {
205 if (errno != ENOENT) {
206 dbd_log(LOGSTD, "Access error for ad-file '%s/%s': %s",
207 cwdbuf, adname, strerror(errno));
210 /* Missing. Log and create it */
211 dbd_log(LOGSTD, "Missing AppleDoube file '%s/%s'", cwdbuf, adname);
213 if (dbd_flags & DBD_FLAGS_SCAN)
214 /* Scan only requested, dont change anything */
218 ad_init(&ad, volinfo->v_adouble, volinfo->v_ad_options);
220 if ((ret = ad_open_metadata( fname, adflags, O_CREAT, &ad)) != 0) {
221 dbd_log( LOGSTD, "Error creating AppleDouble file '%s/%s': %s",
222 cwdbuf, adname, strerror(errno));
226 /* Set name in ad-file */
227 ad_setname(&ad, utompath((char *)fname));
229 ad_close_metadata(&ad);
231 chown(adname, st->st_uid, st->st_gid);
232 /* FIXME: should we inherit mode too here ? */
234 chmod(adname, st->st_mode);
241 Check for .AppleDouble folder and .Parent, create if missing
243 static int check_addir(int volroot)
245 int addir_ok, adpar_ok;
250 /* Check for ad-dir */
251 if ( (addir_ok = access(ADv2_DIRNAME, F_OK)) != 0) {
252 if (errno != ENOENT) {
253 dbd_log(LOGSTD, "Access error in directory %s: %s", cwdbuf, strerror(errno));
256 dbd_log(LOGSTD, "Missing %s for '%s'", ADv2_DIRNAME, cwdbuf);
259 /* Check for ".Parent" */
260 if ( (adpar_ok = access(volinfo->ad_path(".", ADFLAGS_DIR), F_OK)) != 0) {
261 if (errno != ENOENT) {
262 dbd_log(LOGSTD, "Access error on '%s/%s': %s",
263 cwdbuf, volinfo->ad_path(".", ADFLAGS_DIR), strerror(errno));
266 dbd_log(LOGSTD, "Missing .AppleDouble/.Parent for '%s'", cwdbuf);
269 /* Is one missing ? */
270 if ((addir_ok != 0) || (adpar_ok != 0)) {
271 /* Yes, but are we only scanning ? */
272 if (dbd_flags & DBD_FLAGS_SCAN) {
273 /* Yes: missing .Parent is not a problem, but missing ad-dir
274 causes later checking of ad-files to fail. So we have to return appropiately */
277 else /* (adpar_ok != 0) */
281 /* Create ad dir and set name */
282 ad_init(&ad, volinfo->v_adouble, volinfo->v_ad_options);
284 if (ad_open_metadata( ".", ADFLAGS_DIR, O_CREAT, &ad) != 0) {
285 dbd_log( LOGSTD, "Error creating AppleDouble dir in %s: %s", cwdbuf, strerror(errno));
289 /* Get basename of cwd from cwdbuf */
290 utompath(strrchr(cwdbuf, '/') + 1);
292 /* Update name in ad file */
293 ad_setname(&ad, mname);
295 ad_close_metadata(&ad);
297 /* Inherit owner/group from "." to ".AppleDouble" and ".Parent" */
298 if ((stat(".", &st)) != 0) {
299 dbd_log( LOGSTD, "Couldnt stat %s: %s", cwdbuf, strerror(errno));
302 chown(ADv2_DIRNAME, st.st_uid, st.st_gid);
303 chown(volinfo->ad_path(".", ADFLAGS_DIR), st.st_uid, st.st_gid);
310 Check files and dirs inside .AppleDouble folder:
311 - remove orphaned files
314 static int read_addir(void)
319 static char fname[MAXPATHLEN] = "../";
321 if ((chdir(ADv2_DIRNAME)) != 0) {
322 dbd_log(LOGSTD, "Couldn't chdir to '%s/%s': %s",
323 cwdbuf, ADv2_DIRNAME, strerror(errno));
327 if ((dp = opendir(".")) == NULL) {
328 dbd_log(LOGSTD, "Couldn't open the directory '%s/%s': %s",
329 cwdbuf, ADv2_DIRNAME, strerror(errno));
333 while ((ep = readdir(dp))) {
334 /* Check if its "." or ".." */
335 if (DIR_DOT_OR_DOTDOT(ep->d_name))
338 if (STRCMP(ep->d_name, ==, ".Parent"))
341 if ((stat(ep->d_name, &st)) < 0) {
342 dbd_log( LOGSTD, "Lost file or dir while enumeratin dir '%s/%s/%s', probably removed: %s",
343 cwdbuf, ADv2_DIRNAME, ep->d_name, strerror(errno));
348 if (S_ISDIR(st.st_mode)) {
349 dbd_log( LOGSTD, "Unexpected directory '%s' in AppleDouble dir '%s/%s'",
350 ep->d_name, cwdbuf, ADv2_DIRNAME);
354 /* Check for data file */
355 strcpy(fname+3, ep->d_name);
356 if ((access( fname, F_OK)) != 0) {
357 if (errno != ENOENT) {
358 dbd_log(LOGSTD, "Access error for file '%s/%s': %s",
359 cwdbuf, ep->d_name, strerror(errno));
362 /* Orphaned ad-file*/
363 dbd_log(LOGSTD, "Orphaned AppleDoube file '%s/%s/%s'",
364 cwdbuf, ADv2_DIRNAME, ep->d_name);
366 if (dbd_flags & DBD_FLAGS_SCAN)
367 /* Scan only requested, dont change anything */
370 if ((unlink(ep->d_name)) != 0) {
371 dbd_log(LOGSTD, "Error unlinking orphaned AppleDoube file '%s/%s/%s'",
372 cwdbuf, ADv2_DIRNAME, ep->d_name);
378 if ((chdir("..")) != 0) {
379 dbd_log(LOGSTD, "Couldn't chdir back to '%s' from AppleDouble dir: %s",
380 cwdbuf, strerror(errno));
381 /* This really is EOT! */
391 Check CNID for a file/dir, both from db and from ad-file.
392 For detailed specs see intro.
394 static cnid_t check_cnid(const char *name, cnid_t did, struct stat *st, int adfile_ok, int adflags)
397 cnid_t db_cnid, ad_cnid;
400 /* Get CNID from ad-file if volume is using AFPVOL_CACHE */
402 if ( (volinfo->v_flags & AFPVOL_CACHE) && ADFILE_OK) {
403 ad_init(&ad, volinfo->v_adouble, volinfo->v_ad_options);
404 if (ad_open_metadata( name, adflags, O_RDWR, &ad) != 0) {
405 dbd_log( LOGSTD, "Error opening AppleDouble file for '%s/%s': %s", cwdbuf, name, strerror(errno));
409 if (dbd_flags & DBD_FLAGS_FORCE) {
410 ad_cnid = ad_forcegetid(&ad);
411 /* This ensures the changed stamp is written */
412 ad_setid( &ad, st->st_dev, st->st_ino, ad_cnid, did, stamp);
416 ad_cnid = ad_getid(&ad, st->st_dev, st->st_ino, did, stamp);
419 dbd_log( LOGSTD, "Incorrect CNID data in .AppleDouble data for '%s/%s' (bad stamp?)", cwdbuf, name);
421 ad_close_metadata(&ad);
424 /* Get CNID from database */
426 /* Prepare request data */
427 memset(&rqst, 0, sizeof(struct cnid_dbd_rqst));
428 memset(&rply, 0, sizeof(struct cnid_dbd_rply));
430 if ( ! (volinfo->v_flags & AFPVOL_NODEV))
431 rqst.dev = st->st_dev;
432 rqst.ino = st->st_ino;
433 rqst.type = S_ISDIR(st->st_mode)?1:0;
434 rqst.name = (char *)name;
435 rqst.namelen = strlen(name);
437 /* Query the database */
438 ret = cmd_dbd_lookup(dbd, &rqst, &rply, (dbd_flags & DBD_FLAGS_SCAN) ? 1 : 0);
439 dbif_txn_close(dbd, ret);
440 if (rply.result == CNID_DBD_RES_OK) {
442 } else if (rply.result == CNID_DBD_RES_NOTFOUND) {
443 if ( ! (dbd_flags & DBD_FLAGS_FORCE))
444 dbd_log( LOGSTD, "No CNID for '%s/%s' in database", cwdbuf, name);
447 dbd_log( LOGSTD, "Fatal error resolving '%s/%s'", cwdbuf, name);
451 /* Compare results from both CNID searches */
452 if (ad_cnid && db_cnid && (ad_cnid == db_cnid)) {
453 /* Everything is fine */
455 } else if (ad_cnid && db_cnid && (ad_cnid != db_cnid)) {
456 /* Mismatch ? Delete both from db and re-add data from file */
457 dbd_log( LOGSTD, "CNID mismatch for '%s/%s', db: %u, ad-file: %u", cwdbuf, name, ntohl(db_cnid), ntohl(ad_cnid));
458 if ( ! (dbd_flags & DBD_FLAGS_SCAN)) {
460 ret = dbd_delete(dbd, &rqst, &rply, DBIF_CNID);
461 dbif_txn_close(dbd, ret);
464 ret = dbd_delete(dbd, &rqst, &rply, DBIF_CNID);
465 dbif_txn_close(dbd, ret);
467 ret = dbd_rebuild_add(dbd, &rqst, &rply);
468 dbif_txn_close(dbd, ret);
471 } else if (ad_cnid && (db_cnid == 0)) {
472 /* in ad-file but not in db */
473 if ( ! (dbd_flags & DBD_FLAGS_SCAN)) {
474 dbd_log( LOGDEBUG, "CNID rebuild add for '%s/%s', adding with CNID from ad-file: %u", cwdbuf, name, ntohl(ad_cnid));
476 ret = dbd_delete(dbd, &rqst, &rply, DBIF_CNID);
477 dbif_txn_close(dbd, ret);
478 ret = dbd_rebuild_add(dbd, &rqst, &rply);
479 dbif_txn_close(dbd, ret);
482 } else if ((db_cnid == 0) && (ad_cnid == 0)) {
483 /* No CNID at all, we clearly have to allocate a fresh one... */
484 /* Note: the next test will use this new CNID too! */
485 if ( ! (dbd_flags & DBD_FLAGS_SCAN)) {
487 ret = cmd_dbd_add(dbd, &rqst, &rply);
488 dbif_txn_close(dbd, ret);
490 dbd_log( LOGSTD, "New CNID for '%s/%s': %u", cwdbuf, name, ntohl(db_cnid));
494 if ((ad_cnid == 0) && db_cnid) {
495 /* in db but zeroID in ad-file, write it to ad-file if AFPVOL_CACHE */
496 if ((volinfo->v_flags & AFPVOL_CACHE) && ADFILE_OK) {
497 if ( ! (dbd_flags & DBD_FLAGS_SCAN)) {
498 dbd_log( LOGSTD, "Writing CNID data for '%s/%s' to AppleDouble file", cwdbuf, name, ntohl(db_cnid));
499 ad_init(&ad, volinfo->v_adouble, volinfo->v_ad_options);
500 if (ad_open_metadata( name, adflags, O_RDWR, &ad) != 0) {
501 dbd_log( LOGSTD, "Error opening AppleDouble file for '%s/%s': %s", cwdbuf, name, strerror(errno));
504 ad_setid( &ad, st->st_dev, st->st_ino, db_cnid, did, stamp);
506 ad_close_metadata(&ad);
516 This is called recursively for all dirs.
517 volroot=1 means we're in the volume root dir, 0 means we aren't.
518 We use this when checking for netatalk private folders like .AppleDB.
519 did is our parents CNID.
521 static int dbd_readdir(int volroot, cnid_t did)
523 int cwd, ret = 0, adflags, adfile_ok, addir_ok, encoding_ok;
528 static struct stat st; /* Save some stack space */
530 /* Check again for .AppleDouble folder, check_adfile also checks/creates it */
531 if ((addir_ok = check_addir(volroot)) != 0)
532 if ( ! (dbd_flags & DBD_FLAGS_SCAN))
533 /* Fatal on rebuild run, continue if only scanning ! */
536 /* Check AppleDouble files in AppleDouble folder, but only if it exists or could be created */
538 if ((read_addir()) != 0)
539 if ( ! (dbd_flags & DBD_FLAGS_SCAN))
540 /* Fatal on rebuild run, continue if only scanning ! */
543 if ((dp = opendir (".")) == NULL) {
544 dbd_log(LOGSTD, "Couldn't open the directory: %s",strerror(errno));
548 while ((ep = readdir (dp))) {
549 /* Check if we got a termination signal */
551 longjmp(jmp, 1); /* this jumps back to cmd_dbd_scanvol() */
553 /* Check if its "." or ".." */
554 if (DIR_DOT_OR_DOTDOT(ep->d_name))
557 /* Check for netatalk special folders e.g. ".AppleDB" or ".AppleDesktop" */
558 if ((name = check_netatalk_dirs(ep->d_name)) != NULL) {
560 dbd_log(LOGSTD, "Nested %s in %s", name, cwdbuf);
564 /* Skip .AppleDouble dir in this loop */
565 if (STRCMP(ep->d_name, == , ADv2_DIRNAME))
568 if ((ret = stat(ep->d_name, &st)) < 0) {
569 dbd_log( LOGSTD, "Lost file while reading dir '%s/%s', probably removed: %s", cwdbuf, ep->d_name, strerror(errno));
572 if (S_ISREG(st.st_mode))
575 adflags = ADFLAGS_DIR;
577 /**************************************************************************
579 **************************************************************************/
582 if ( -1 == (encoding_ok = check_name_encoding(ep->d_name)) ) {
583 /* If its a file: skipp all other tests now ! */
584 /* For dirs we could try to get a CNID for it and recurse, but currently I prefer not to */
588 /* Check for appledouble file, create if missing, but only if we have addir */
591 adfile_ok = check_adfile(ep->d_name, &st);
594 cnid = check_cnid(ep->d_name, did, &st, adfile_ok, adflags);
596 /* Now add this object to our rebuild dbd */
598 rqst.cnid = rply.cnid;
599 dbd_rebuild_add(dbd_rebuild, &rqst, &rply);
600 if (rply.result != CNID_DBD_RES_OK) {
601 dbd_log( LOGDEBUG, "Fatal error adding CNID: %u for '%s/%s' to in-memory rebuild-db",
602 cnid, cwdbuf, ep->d_name);
607 /**************************************************************************
609 **************************************************************************/
610 if (S_ISDIR(st.st_mode) && cnid) { /* If we have no cnid for it we cant recur */
612 strcat(cwdbuf, ep->d_name);
613 dbd_log( LOGDEBUG, "Entering directory: %s", cwdbuf);
614 if (-1 == (cwd = open(".", O_RDONLY))) {
615 dbd_log( LOGSTD, "Cant open directory '%s': %s", cwdbuf, strerror(errno));
618 if (0 != chdir(ep->d_name)) {
619 dbd_log( LOGSTD, "Cant chdir to directory '%s': %s", cwdbuf, strerror(errno));
624 ret = dbd_readdir(0, cnid);
628 *(strrchr(cwdbuf, '/')) = 0;
635 Use results of previous checks
642 static int scanvol(struct volinfo *vi, dbd_flags_t flags)
644 /* Dont scanvol on no-appledouble vols */
645 if (vi->v_flags & AFPVOL_NOADOUBLE) {
646 dbd_log( LOGSTD, "Volume without AppleDouble support: skipping volume scanning.");
650 /* Make this stuff accessible from all funcs easily */
654 /* Run with umask 0 */
658 strcpy(cwdbuf, volinfo->v_path);
659 if (cwdbuf[strlen(cwdbuf) - 1] == '/')
660 cwdbuf[strlen(cwdbuf) - 1] = 0;
661 chdir(volinfo->v_path);
663 /* Start recursion */
664 if (dbd_readdir(1, htonl(2)) < 0) /* 2 = volumeroot CNID */
671 Remove all CNIDs from dbd that are not in dbd_rebuild
673 void delete_orphaned_cnids(DBD *dbd, DBD *dbd_rebuild, dbd_flags_t flags)
675 int ret, deleted = 0;
676 cnid_t dbd_cnid = 0, rebuild_cnid = 0;
677 struct cnid_dbd_rqst rqst;
678 struct cnid_dbd_rply rply;
680 /* jump over rootinfo key */
681 if ( dbif_idwalk(dbd, &dbd_cnid, 0) != 1)
683 if ( dbif_idwalk(dbd_rebuild, &rebuild_cnid, 0) != 1)
686 /* Get first id from dbd_rebuild */
687 if ((dbif_idwalk(dbd_rebuild, &rebuild_cnid, 0)) == -1)
690 /* Start main loop through dbd: get CNID from dbd */
691 while ((dbif_idwalk(dbd, &dbd_cnid, 0)) == 1) {
695 if (dbif_txn_checkpoint(dbd, 0, 0, 0) < 0) {
696 dbd_log(LOGSTD, "Error checkpointing!");
701 /* This should be the normal case: CNID is in both dbs */
702 if (dbd_cnid == rebuild_cnid) {
703 /* Get next CNID from rebuild db */
704 if ((ret = dbif_idwalk(dbd_rebuild, &rebuild_cnid, 0)) == -1) {
707 } else if (ret == 0) {
708 /* end of rebuild_cnid, delete all remaining CNIDs from dbd */
709 while ((dbif_idwalk(dbd, &dbd_cnid, 0)) == 1) {
710 dbd_log(LOGSTD, "Orphaned CNID in database: %u", dbd_cnid);
711 if ( ! (dbd_flags & DBD_FLAGS_SCAN)) {
712 rqst.cnid = htonl(dbd_cnid);
713 ret = dbd_delete(dbd, &rqst, &rply, DBIF_CNID);
714 dbif_txn_close(dbd, ret);
720 /* Normal case (ret=1): continue while loop */
724 if (dbd_cnid < rebuild_cnid) {
725 /* CNID is orphaned -> delete */
726 dbd_log(LOGSTD, "Orphaned CNID in database: %u.", dbd_cnid);
727 if ( ! (dbd_flags & DBD_FLAGS_SCAN)) {
728 rqst.cnid = htonl(dbd_cnid);
729 ret = dbd_delete(dbd, &rqst, &rply, DBIF_CNID);
730 dbif_txn_close(dbd, ret);
736 if (dbd_cnid > rebuild_cnid) {
737 dbd_log(LOGSTD, "Ghost CNID: %u. This is fatal! Dumping rebuild db:\n", rebuild_cnid);
738 dbif_dump(dbd_rebuild, 0);
739 dbd_log(LOGSTD, "Send this dump and a `dbd -d ...` dump to the Netatalk Dev team!");
740 dbif_txn_close(dbd, ret);
741 dbif_idwalk(dbd, NULL, 1); /* Close cursor */
742 dbif_idwalk(dbd_rebuild, NULL, 1); /* Close cursor */
748 dbif_idwalk(dbd, NULL, 1); /* Close cursor */
749 dbif_idwalk(dbd_rebuild, NULL, 1); /* Close cursor */
754 Main func called from cmd_dbd.c
756 int cmd_dbd_scanvol(DBD *dbd_ref, struct volinfo *volinfo, dbd_flags_t flags)
760 /* Make it accessible for all funcs */
763 /* We only support unicode volumes ! */
764 if ( volinfo->v_volcharset != CH_UTF8) {
765 dbd_log( LOGSTD, "Not a Unicode volume: %s, %u != %u", volinfo->v_volcodepage, volinfo->v_volcharset, CH_UTF8);
769 /* Get volume stamp */
770 dbd_getstamp(dbd, &rqst, &rply);
771 if (rply.result != CNID_DBD_RES_OK)
773 memcpy(stamp, rply.name, CNID_DEV_LEN);
775 /* open/create rebuild dbd, copy rootinfo key */
776 if (NULL == (dbd_rebuild = dbif_init(NULL, NULL)))
778 if (0 != (dbif_open(dbd_rebuild, NULL, 0)))
780 if (0 != (dbif_copy_rootinfokey(dbd, dbd_rebuild)))
783 if (setjmp(jmp) != 0)
784 goto exit_cleanup; /* Got signal, jump from dbd_readdir */
787 if ( (scanvol(volinfo, flags)) != 0)
790 /* We can only do this in exclusive mode, otherwise we might delete CNIDs added from
791 other clients in between our pass 1 and 2 */
792 if (flags & DBD_FLAGS_EXCL)
793 delete_orphaned_cnids(dbd, dbd_rebuild, flags);
796 dbif_close(dbd_rebuild);