4
# cnid_maint: A script to maintain the consistency of CNID databases.
6
# $Id: cnid_maint.in,v 1.12.2.3 2003/02/17 02:33:26 jmarcus Exp $
27
$STOP_CMD = '/usr/local/etc/rc.d/netatalk.sh stop';
28
$START_CMD = '/usr/local/etc/rc.d/netatalk.sh start';
30
# This ps command needs to output the following fields in the following order:
31
# USER,PID,PPID,COMMAND
32
# Below is the example of a BSD ps. A SYSV example is:
33
# /bin/ps -eflouid,pid,ppid,comm
34
$PS_CMD = '@PS@ -axouser,pid,ppid,command';
35
$DB_STAT = '@BDB_BIN@/db_stat';
36
$DB_RECOVER = '@BDB_BIN@/db_recover';
37
$DB_VERIFY = '@BDB_BIN@/db_verify';
38
$APPLE_VOLUMES_FILE = '@PKGCONFDIR@/AppleVolumes.default';
44
$LOCK_FILE = tmpdir() . '/cnid_maint.LOCK';
57
getopts('hsvVl', $opts);
78
die "You must be root to run this script.\n";
81
print "Beginning run of CNID DB Maintanence script at "
82
. scalar(localtime) . ".\n\n";
85
error(1, "Lock file $LOCK_FILE exists.");
89
unless (open(LOCK, ">" . $LOCK_FILE)) {
90
error(2, "Unable to create $LOCK_FILE: $!");
95
# Check to see if the AppleVolumes.default file exists. We will use this file
96
# to get a list of database environments to recover. We will ignore users'
97
# home directories since that could be a monumental under taking.
98
if (!-f $APPLE_VOLUMES_FILE) {
99
error(2, "Unable to locate $APPLE_VOLUMES_FILE");
102
# Use ps to get a list of running afpds. We will track all afpd PIDs that are
104
unless (open(PS, $PS_CMD . " | $GREP afpd | $GREP -v grep |")) {
105
error(2, "Unable to open a pipe to ps: $!");
113
my ($user, $pid, $ppid, $command) = split (/\s+/);
114
if (($user eq "root" && $ppid != 1) || ($user ne "root")) {
123
# We have some children. We cannot run recovery.
125
"Clients are still connected. Database recovery will not be run at this time."
132
# Shutdown the running afpds.
134
error(0, "Shutting down afpd process...");
135
error(2, "Failed to shutdown afpd")
136
if system($STOP_CMD . ">/dev/null 2>&1");
139
# Now, we parse AppleVolumes.default to get a list of volumes to run recovery
141
unless (open(VOLS, $APPLE_VOLUMES_FILE)) {
142
error(2, "Unable to open $APPLE_VOLUMES_FILE: $!");
144
flock(VOLS, LOCK_SH);
152
my ($path, @options) = split (/\s+/, $_);
153
next if ($path =~ /^~/);
155
foreach $option (@options) {
157
# We need to check for the dbpath option on each volume. If
158
# that option is present, we should use its path instead of
159
# the actual volume path.
160
if ($option =~ /^dbpath:/) {
171
foreach $path (@paths) {
172
my $dbpath = $path . "/.AppleDB";
174
error(1, "Database environment $dbpath does not exist");
179
"Checking database environment $dbpath for open connections..."
181
unless (open(STAT, $DB_STAT . " -h $dbpath -e |")) {
182
error(1, "Failed to open a pipe to $DB_STAT: $!");
186
# Now, check each DB environment for any open connections
187
# (db_stat calls them as references). If a volume has no
188
# references, we can do recovery on it. Only check this option
189
# if the user wants to play things extra safe.
194
if (/References\.$/) {
202
# Print out two different skip messages. This is just for
204
if ($connections == 1) {
206
"Skipping $dbpath since it has one active connection"
211
if ($connections > 0) {
213
"Skipping $dbpath since it has $connections active connections"
219
# Run the db_recover command on the environment.
220
error(0, "Running db_recover on $dbpath");
221
if (system($DB_RECOVER . " -h $dbpath >/dev/null 2>&1")) {
222
error(1, "Failed to run db_recover on $dbpath");
227
error(0, "Verifying $dbpath/cnid.db");
228
if (system($DB_VERIFY . " -q -h $dbpath cnid.db")) {
229
error(1, "Verification of $dbpath/cnid.db failed");
233
error(0, "Verifying $dbpath/devino.db");
234
if (system($DB_VERIFY . " -q -h $dbpath devino.db")) {
235
error(1, "Verification of $dbpath/devino.db failed");
239
error(0, "Verifying $dbpath/didname.db");
240
if (system($DB_VERIFY . " -q -h $dbpath didname.db")) {
241
error(1, "Verification of $dbpath/didname.db failed");
244
if (-f "$dbpath/mangle.db") {
245
error(0, "Verifying $dbpath/mangle.db");
246
if (system($DB_VERIFY . " -q -h $dbpath mangle.db")) {
248
"Verification of $dbpath/mangle.db failed"
257
# Remove the log files if told to do so.
258
unless (opendir(DIR, $dbpath)) {
259
error(1, "Failed to open $dbpath for browsing: $!");
264
while (defined($file = readdir(DIR))) {
265
if ($file =~ /^log\.\d+$/) {
266
error(0, "Removing $dbpath/$file");
267
unless (unlink($dbpath . "/" . $file)) {
269
"Failed to remove $dbpath/$file: $!"
286
foreach ($ENV{TMPDIR}, "/tmp") {
287
next unless defined && -d && -w _;
291
$tmpdir = '' unless defined $tmpdir;
296
my ($code, $msg) = @_;
304
print $err_types->{$code} . ": " . $msg . "\n";
306
end() if ($code == 2);
310
if ($START_NETATALK) {
311
error(0, "Restarting Netatalk");
312
if (system($START_CMD . " >/dev/null 2>&1")) {
313
print "ERROR: Failed to restart Netatalk\n";
320
print "\nRun of CNID DB Maintenance script ended at "
321
. scalar(localtime) . ".\n";
326
print "$0 version $VERSION\n";
330
print "usage: $0 [-hlsvV]\n";
331
print "\t-h view this message\n";
332
print "\t-l remove transaction logs after running recovery\n";
334
"\t-s be extra safe in verifying there are no open DB connections\n";
335
print "\t-v print version and exit\n";
337
"\t-V run a verification on all database files after recovery\n";