2 Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
17 #endif /* HAVE_CONFIG_H */
20 #include <sys/types.h>
29 #include <atalk/logger.h>
30 #include <atalk/globals.h>
31 #include <atalk/netatalk_conf.h>
32 #include <atalk/util.h>
33 #include <atalk/errchk.h>
37 enum dbd_cmd {dbd_scan, dbd_rebuild};
39 /* Global variables */
40 volatile sig_atomic_t alarmed; /* flags for signals */
43 static dbd_flags_t flags;
45 /***************************************************************************
47 ***************************************************************************/
51 * catch SIGINT and SIGTERM which cause clean exit. Ignore anything else.
53 static void sig_handler(int signo)
59 static void set_signal(void)
63 sv.sa_handler = sig_handler;
64 sv.sa_flags = SA_RESTART;
65 sigemptyset(&sv.sa_mask);
66 if (sigaction(SIGTERM, &sv, NULL) < 0) {
67 dbd_log( LOGSTD, "error in sigaction(SIGTERM): %s", strerror(errno));
70 if (sigaction(SIGINT, &sv, NULL) < 0) {
71 dbd_log( LOGSTD, "error in sigaction(SIGINT): %s", strerror(errno));
75 memset(&sv, 0, sizeof(struct sigaction));
76 sv.sa_handler = SIG_IGN;
77 sigemptyset(&sv.sa_mask);
79 if (sigaction(SIGABRT, &sv, NULL) < 0) {
80 dbd_log( LOGSTD, "error in sigaction(SIGABRT): %s", strerror(errno));
83 if (sigaction(SIGHUP, &sv, NULL) < 0) {
84 dbd_log( LOGSTD, "error in sigaction(SIGHUP): %s", strerror(errno));
87 if (sigaction(SIGQUIT, &sv, NULL) < 0) {
88 dbd_log( LOGSTD, "error in sigaction(SIGQUIT): %s", strerror(errno));
93 static void usage (void)
95 printf("Usage: dbd [-cfFstvV] <path to netatalk volume>\n\n"
96 "dbd scans all file and directories of AFP volumes, updating the\n"
97 "CNID database of the volume. dbd must be run with appropiate\n"
98 "permissions i.e. as root.\n\n"
100 " -s scan volume: treat the volume as read only and don't\n"
101 " perform any filesystem modifications\n"
102 " -c convert from adouble:v2 to adouble:ea\n"
103 " -F location of the afp.conf config file\n"
104 " -f delete and recreate CNID database\n"
105 " -t show statistics while running\n"
107 " -V show version info\n\n"
111 /***************************************************************************
113 ***************************************************************************/
115 void dbd_log(enum logtype lt, char *fmt, ...)
118 static char logbuffer[1024];
121 if ( (lt == LOGSTD) || (flags & DBD_FLAGS_VERBOSE)) {
123 len = vsnprintf(logbuffer, 1023, fmt, args);
127 printf("%s\n", logbuffer);
131 int main(int argc, char **argv)
134 int dbd_cmd = dbd_rebuild;
137 struct vol *vol = NULL;
138 const char *volpath = NULL;
141 while ((c = getopt(argc, argv, ":cfF:rstvV")) != -1) {
144 flags |= DBD_FLAGS_V2TOEA;
147 flags |= DBD_FLAGS_FORCE;
150 obj.cmdlineconfigfile = strdup(optarg);
157 flags |= DBD_FLAGS_SCAN;
160 flags |= DBD_FLAGS_STATS;
163 flags |= DBD_FLAGS_VERBOSE;
166 printf("dbd %s\n", VERSION);
176 if ( (optind + 1) != argc ) {
180 volpath = argv[optind];
182 if (geteuid() != 0) {
186 /* Inhereting perms in ad_mkdir etc requires this */
189 setvbuf(stdout, (char *) NULL, _IONBF, 0);
192 if ((cdir = open(".", O_RDONLY)) < 0) {
193 dbd_log( LOGSTD, "Can't open dir: %s", strerror(errno));
197 /* Setup signal handling */
201 if (afp_config_parse(&obj, "dbd") != 0) {
202 dbd_log( LOGSTD, "Couldn't load afp.conf");
206 /* Initialize CNID subsystem */
209 /* Setup logging. Should be portable among *NIXes */
210 if (flags & DBD_FLAGS_VERBOSE)
211 setuplog("default:note, cnid:debug", "/dev/tty");
213 setuplog("default:note", "/dev/tty");
215 if (load_volumes(&obj, lv_all) != 0) {
216 dbd_log( LOGSTD, "Couldn't load volumes");
220 if ((vol = getvolbypath(&obj, volpath)) == NULL) {
221 dbd_log( LOGSTD, "Couldn't find volume for '%s'", volpath);
225 if (load_charset(vol) != 0) {
226 dbd_log( LOGSTD, "Couldn't load charsets for '%s'", volpath);
231 if (STRCMP(vol->v_cnidscheme, != , "dbd") && STRCMP(vol->v_cnidscheme, != , "mysql")) {
232 dbd_log(LOGSTD, "\"%s\" isn't a \"dbd\" CNID volume", vol->v_path);
235 if ((vol->v_cdb = cnid_open(vol->v_path,
238 vol->v_flags & AFPVOL_NODEV ? CNID_FLAG_NODEV : 0,
242 vol->v_uuid)) == NULL) {
243 dbd_log(LOGSTD, "Cant initialize CNID database connection for %s", vol->v_path);
247 if (vol->v_adouble == AD_VERSION_EA)
248 dbd_log( LOGDEBUG, "adouble:ea volume");
249 else if (vol->v_adouble == AD_VERSION2)
250 dbd_log( LOGDEBUG, "adouble:v2 volume");
252 dbd_log( LOGSTD, "unknown adouble volume");
256 /* -C v2 to ea conversion only on adouble:ea volumes */
257 if ((flags & DBD_FLAGS_V2TOEA) && (vol->v_adouble!= AD_VERSION_EA)) {
258 dbd_log( LOGSTD, "Can't run adouble:v2 to adouble:ea conversion because not an adouble:ea volume");
262 /* Sanity checks to ensure we can touch this volume */
263 if (vol->v_vfs_ea != AFPVOL_EA_AD && vol->v_vfs_ea != AFPVOL_EA_SYS) {
264 dbd_log( LOGSTD, "Unknown Extended Attributes option: %u", vol->v_vfs_ea);
268 if (flags & DBD_FLAGS_FORCE) {
269 if (cnid_wipe(vol->v_cdb) != 0) {
270 dbd_log( LOGSTD, "Failed to wipe CNID db");
275 /* Now execute given command scan|rebuild|dump */
279 if (cmd_dbd_scanvol(vol, flags) < 0) {
280 dbd_log( LOGSTD, "Error repairing database.");
287 cnid_close(vol->v_cdb);
289 if (cdir != -1 && (fchdir(cdir) < 0))
290 dbd_log(LOGSTD, "fchdir: %s", strerror(errno));