~ubuntu-branches/ubuntu/precise/netatalk/precise

« back to all changes in this revision

Viewing changes to bin/cnid/cnid_maint.in

  • Committer: Bazaar Package Importer
  • Author(s): Sebastian Rittau
  • Date: 2004-01-19 12:43:49 UTC
  • Revision ID: james.westby@ubuntu.com-20040119124349-es563jbp0hk0ae51
Tags: upstream-1.6.4
ImportĀ upstreamĀ versionĀ 1.6.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!@PERL@
 
2
 
 
3
#
 
4
# cnid_maint: A script to maintain the consistency of CNID databases.
 
5
#
 
6
# $Id: cnid_maint.in,v 1.12.2.3 2003/02/17 02:33:26 jmarcus Exp $
 
7
#
 
8
 
 
9
use strict;
 
10
use Getopt::Std;
 
11
use vars qw(
 
12
    $APPLE_VOLUMES_FILE
 
13
    $STOP_CMD
 
14
    $START_CMD
 
15
    $PS_CMD
 
16
    $GREP
 
17
    $DB_STAT
 
18
    $DB_RECOVER
 
19
    $DB_VERIFY
 
20
    $VERSION
 
21
    $START_NETATALK
 
22
    $LOCK_FILE
 
23
    $HOLDING_LOCK
 
24
);
 
25
 
 
26
## Edit ME
 
27
$STOP_CMD  = '/usr/local/etc/rc.d/netatalk.sh stop';
 
28
$START_CMD = '/usr/local/etc/rc.d/netatalk.sh start';
 
29
 
 
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';
 
39
## End edit section
 
40
 
 
41
$VERSION        = '1.0';
 
42
$GREP           = '@GREP@';
 
43
$START_NETATALK = 0;
 
44
$LOCK_FILE      = tmpdir() . '/cnid_maint.LOCK';
 
45
$HOLDING_LOCK   = 0;
 
46
 
 
47
sub LOCK_SH { 1 }
 
48
sub LOCK_EX { 2 }
 
49
sub LOCK_NB { 4 }
 
50
sub LOCK_UN { 8 }
 
51
 
 
52
my $opts        = {};
 
53
my $extra_safe  = 0;
 
54
my $do_verify   = 0;
 
55
my $remove_logs = 0;
 
56
 
 
57
getopts('hsvVl', $opts);
 
58
 
 
59
if ($opts->{'v'}) {
 
60
        version();
 
61
        exit(0);
 
62
}
 
63
if ($opts->{'h'}) {
 
64
        help();
 
65
        exit(0);
 
66
}
 
67
if ($opts->{'s'}) {
 
68
        $extra_safe = 1;
 
69
}
 
70
if ($opts->{'V'}) {
 
71
        $do_verify = 1;
 
72
}
 
73
if ($opts->{'l'}) {
 
74
        $remove_logs = 1;
 
75
}
 
76
 
 
77
if ($< != 0) {
 
78
        die "You must be root to run this script.\n";
 
79
}
 
80
 
 
81
print "Beginning run of CNID DB Maintanence script at "
 
82
    . scalar(localtime) . ".\n\n";
 
83
 
 
84
if (-f $LOCK_FILE) {
 
85
        error(1, "Lock file $LOCK_FILE exists.");
 
86
        end();
 
87
}
 
88
 
 
89
unless (open(LOCK, ">" . $LOCK_FILE)) {
 
90
        error(2, "Unable to create $LOCK_FILE: $!");
 
91
}
 
92
flock(LOCK, LOCK_EX);
 
93
$HOLDING_LOCK = 1;
 
94
 
 
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");
 
100
}
 
101
 
 
102
# Use ps to get a list of running afpds.  We will track all afpd PIDs that are
 
103
# running as root.
 
104
unless (open(PS, $PS_CMD . " | $GREP afpd | $GREP -v grep |")) {
 
105
        error(2, "Unable to open a pipe to ps: $!");
 
106
}
 
107
 
 
108
my $children  = 0;
 
109
my $processes = 0;
 
110
while (<PS>) {
 
111
        chomp;
 
112
        $processes++;
 
113
        my ($user, $pid, $ppid, $command) = split (/\s+/);
 
114
        if (($user eq "root" && $ppid != 1) || ($user ne "root")) {
 
115
                $children++;
 
116
        }
 
117
}
 
118
 
 
119
close(PS);
 
120
 
 
121
if ($children) {
 
122
 
 
123
        # We have some children.  We cannot run recovery.
 
124
        error(1,
 
125
                "Clients are still connected.  Database recovery will not be run at this time."
 
126
        );
 
127
        end();
 
128
}
 
129
 
 
130
if ($processes) {
 
131
 
 
132
        # Shutdown the running afpds.
 
133
        $START_NETATALK = 1;
 
134
        error(0, "Shutting down afpd process...");
 
135
        error(2, "Failed to shutdown afpd")
 
136
            if system($STOP_CMD . ">/dev/null 2>&1");
 
137
}
 
138
 
 
139
# Now, we parse AppleVolumes.default to get a list of volumes to run recovery
 
140
# on.
 
141
unless (open(VOLS, $APPLE_VOLUMES_FILE)) {
 
142
        error(2, "Unable to open $APPLE_VOLUMES_FILE: $!");
 
143
}
 
144
flock(VOLS, LOCK_SH);
 
145
 
 
146
my @paths = ();
 
147
while (<VOLS>) {
 
148
        s/#.*//;
 
149
        s/^\s+//;
 
150
        s/\s+$//;
 
151
        next unless length;
 
152
        my ($path, @options) = split (/\s+/, $_);
 
153
        next if ($path =~ /^~/);
 
154
        my $option = "";
 
155
        foreach $option (@options) {
 
156
 
 
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:/) {
 
161
                        push @paths, $';
 
162
                } else {
 
163
                        push @paths, $path;
 
164
                }
 
165
        }
 
166
}
 
167
 
 
168
close(VOLS);
 
169
 
 
170
my $path = "";
 
171
foreach $path (@paths) {
 
172
        my $dbpath = $path . "/.AppleDB";
 
173
        if (!-d $dbpath) {
 
174
                error(1, "Database environment $dbpath does not exist");
 
175
                next;
 
176
        }
 
177
        if ($extra_safe) {
 
178
                error(0,
 
179
                        "Checking database environment $dbpath for open connections..."
 
180
                );
 
181
                unless (open(STAT, $DB_STAT . " -h $dbpath -e |")) {
 
182
                        error(1, "Failed to open a pipe to $DB_STAT: $!");
 
183
                        next;
 
184
                }
 
185
 
 
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.
 
190
                my $connections = 0;
 
191
                while (<STAT>) {
 
192
                        chomp;
 
193
                        s/\s//g;
 
194
                        if (/References\.$/) {
 
195
                                $connections = $`;
 
196
                                last;
 
197
                        }
 
198
                }
 
199
 
 
200
                close(STAT);
 
201
 
 
202
                # Print out two different skip messages.  This is just for 
 
203
                # anality.
 
204
                if ($connections == 1) {
 
205
                        error(1,
 
206
                                "Skipping $dbpath since it has one active connection"
 
207
                        );
 
208
                        next;
 
209
                }
 
210
 
 
211
                if ($connections > 0) {
 
212
                        error(1,
 
213
                                "Skipping $dbpath since it has $connections active connections"
 
214
                        );
 
215
                        next;
 
216
                }
 
217
        }
 
218
 
 
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");
 
223
                next;
 
224
        }
 
225
 
 
226
        if ($do_verify) {
 
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");
 
230
                        next;
 
231
                }
 
232
 
 
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");
 
236
                        next;
 
237
                }
 
238
 
 
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");
 
242
                        next;
 
243
                }
 
244
                if (-f "$dbpath/mangle.db") {
 
245
                        error(0, "Verifying $dbpath/mangle.db");
 
246
                        if (system($DB_VERIFY . " -q -h $dbpath mangle.db")) {
 
247
                                error(1,
 
248
                                        "Verification of $dbpath/mangle.db failed"
 
249
                                );
 
250
                                next;
 
251
                        }
 
252
                }
 
253
        }
 
254
 
 
255
        if ($remove_logs) {
 
256
 
 
257
                # Remove the log files if told to do so.
 
258
                unless (opendir(DIR, $dbpath)) {
 
259
                        error(1, "Failed to open $dbpath for browsing: $!");
 
260
                        next;
 
261
                }
 
262
 
 
263
                my $file = "";
 
264
                while (defined($file = readdir(DIR))) {
 
265
                        if ($file =~ /^log\.\d+$/) {
 
266
                                error(0, "Removing $dbpath/$file");
 
267
                                unless (unlink($dbpath . "/" . $file)) {
 
268
                                        error(1,
 
269
                                                "Failed to remove $dbpath/$file: $!"
 
270
                                        );
 
271
                                        next;
 
272
                                }
 
273
                        }
 
274
                }
 
275
 
 
276
                closedir(DIR);
 
277
        }
 
278
 
 
279
}
 
280
 
 
281
end();
 
282
 
 
283
sub tmpdir {
 
284
        my $tmpdir;
 
285
 
 
286
        foreach ($ENV{TMPDIR}, "/tmp") {
 
287
                next unless defined && -d && -w _;
 
288
                $tmpdir = $_;
 
289
                last;
 
290
        }
 
291
        $tmpdir = '' unless defined $tmpdir;
 
292
        return $tmpdir;
 
293
}
 
294
 
 
295
sub error {
 
296
        my ($code, $msg) = @_;
 
297
 
 
298
        my $err_types = {
 
299
                0 => "INFO",
 
300
                1 => "WARNING",
 
301
                2 => "ERROR",
 
302
        };
 
303
 
 
304
        print $err_types->{$code} . ": " . $msg . "\n";
 
305
 
 
306
        end() if ($code == 2);
 
307
}
 
308
 
 
309
sub end {
 
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";
 
314
                }
 
315
        }
 
316
        if ($HOLDING_LOCK) {
 
317
                close(LOCK);
 
318
                unlink($LOCK_FILE);
 
319
        }
 
320
        print "\nRun of CNID DB Maintenance script ended at "
 
321
            . scalar(localtime) . ".\n";
 
322
        exit(0);
 
323
}
 
324
 
 
325
sub version {
 
326
        print "$0 version $VERSION\n";
 
327
}
 
328
 
 
329
sub help {
 
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";
 
333
        print
 
334
            "\t-s   be extra safe in verifying there are no open DB connections\n";
 
335
        print "\t-v   print version and exit\n";
 
336
        print
 
337
            "\t-V   run a verification on all database files after recovery\n";
 
338
}