Imported Upstream version 3.1.0
[debian/amanda] / ndmp-src / idx_dump.pl
1 #!/usr/bin/perl
2 #
3 #
4
5 use strict;
6 use Socket;
7 use integer;
8
9 my $prog = $0;
10 $prog =~ s/^.*\/(\S+)$/$1/;
11
12 my $debug = 0;
13 my $do_dirs = 0;
14 my $do_empty_dirs = 0;
15 my $do_inode = 0;
16 my $do_fhinfo = 0;
17
18
19 #
20 # parse switches
21 #
22 while ($ARGV[0] =~ /^-\S+/) {
23     if ($ARGV[0] eq "-d" || $ARGV[0] eq "-debug") {
24         $debug = 1;
25     } elsif ($ARGV[0] eq "-dirs") {
26         $do_dirs = 1;
27     } elsif ($ARGV[0] eq "-empty_dirs") {
28         $do_empty_dirs = 1;
29     } elsif ($ARGV[0] eq "-i") {
30         $do_inode = 1;
31     } elsif ($ARGV[0] eq "-fhinfo") {
32         $do_fhinfo = 1;
33     } else {
34         print STDERR "Unknown switch $ARGV[0]\n";
35         exit -1;
36     }
37     shift @ARGV;
38 }
39 if (@ARGV != 1) {
40     print STDERR "Usage: $prog [-d|-debug] [-dirs] [-i] [-fhinfo] <index file>\n";
41     exit 1;
42 }
43
44 #
45 # parse index file
46 #
47 my $idxfile = $ARGV[0];
48 open(IDXFILE, $idxfile) ||
49     die "$prog: can not open '$idxfile': $!";
50
51 my $root_node = "";
52 my %dir_inode;
53 my %dir_entry_count;
54 my %inode;
55 my %first_ino_ref;
56
57 sub find_path {
58     my ($i) = @_;
59
60     print "find_path called on $i\n" if $debug;
61
62     # check root
63     if ($i == $root_node) {
64         return "";
65     }
66
67     # find the inode of the directory that refers to this inode
68     if (!exists $first_ino_ref{$i}) {
69         print "find_path failed first_ino_ref on $i\n";
70         return "";
71     }
72     my $dir_i = $first_ino_ref{$i};
73
74     # find the directory entry that refers to this inode
75     my $ilist;
76     if (exists $dir_inode{$dir_i}) {
77         $ilist = $dir_inode{$dir_i};
78     } else {
79         print "find_path failed dir_inode for $dir_i on $i\n";
80         return "";
81     }
82
83     # search through the directory for the name entry
84     my $inode_entry_name = "";
85     foreach my $nam (keys %$ilist) {
86         if (($nam eq ".") || ($nam eq "..")) {
87             next;
88         }
89         if ($ilist->{$nam} == $i) {
90             # found entry
91             $inode_entry_name = $nam;
92             last;
93         }
94     }
95     print "find_path found name '$inode_entry_name' for $i\n" if $debug;
96
97     # get the path for the directory
98     if ($dir_i != $i) {
99         my $path = &find_path ($dir_i);
100         if ($path ne "") {
101             return "$path/$inode_entry_name";
102         }
103     }
104     return $inode_entry_name;
105 }
106
107 # Pass #1: get directory information
108 while (<IDXFILE>) {
109     chomp;
110     # emacs sucks with perl
111     if (/^#/) {
112         next;
113     }
114     if (/^CM\s+/) {
115         next;
116     }
117     if (/^DE\s+(.+)\s*$/) {
118         print "Environment: $1\n" if $debug;
119         next;
120     }
121     if (/^DHr\s+(.+)\s*$/) {
122         if ($1 ne "") {
123             $root_node = $1;
124         }
125         next;
126     }
127     if (/^DHd\s+([0-9]+)\s+(\S+)\s+UNIX+\s+([0-9]+)\s*$/) {
128         # directory entry inode $1 has name $2 pointing to inode $3
129         print "$1 => $2 $3\n" if $debug;
130
131         my $ilist;
132         if (exists $dir_inode{$1}) {
133             $ilist = $dir_inode{$1};
134         } else {
135             $ilist = {};
136         }
137         $ilist->{$2} = $3;
138         $dir_inode{$1} = $ilist;
139
140         # if not "." or ".." then record the first reference to the inode
141         if (($2 eq ".") || ($2 eq "..")) {
142             next;
143         }
144
145         # count the directory entry
146         if (exists $dir_entry_count{$1}) {
147             $dir_entry_count{$1}++;
148         } else {
149             $dir_entry_count{$1} = 1;
150         }
151
152         if (!exists $first_ino_ref{$3}) {
153             $first_ino_ref{$3} = $1;
154         }
155
156
157         next;
158     }
159
160     if (/^DHn\s+([0-9]+)\s+UNIX\s+f([dc])\s+m(\S+)\s+u(\S+)\s+g(\S+)\s+tm(\S+)\s*$/) {
161         $inode{$1} = {
162             TYPE => $2,
163             MODE => $3,
164             UID => $4,
165             GID => $5,
166             MTIME => $6,
167             FHINFO => "0",
168         };
169         next;
170     }
171     if (/^DHn\s+([0-9]+)\s+UNIX\s+f([dc])\s+m(\S+)\s+u(\S+)\s+g(\S+)\s+tm(\S+)\s+@([-0-9]+)\s*$/) {
172         $inode{$1} = {
173             TYPE => $2,
174             MODE => $3,
175             UID => $4,
176             GID => $5,
177             MTIME => $6,
178             FHINFO => $7
179         };
180         next;
181     }
182     if (/^DHn\s+([0-9]+)\s+UNIX\s+f(\S+)\s+m(\S+)\s+u(\S+)\s+g(\S+)\s+s(\S+)\s+tm(\S+)\s*$/) {
183         $inode{$1} = {
184             TYPE => $2,
185             MODE => $3,
186             UID => $4,
187             GID => $5,
188             SIZE => $6,
189             MTIME => $7,
190             FHINFO => "0"
191         };
192         next;
193     }
194     if (/^DHn\s+([0-9]+)\s+UNIX\s+f(\S+)\s+m(\S+)\s+u(\S+)\s+g(\S+)\s+s(\S+)\s+tm(\S+)\s+@([-0-9]+)\s*$/) {
195         $inode{$1} = {
196             TYPE => $2,
197             MODE => $3,
198             UID => $4,
199             GID => $5,
200             SIZE => $6,
201             MTIME => $7,
202             FHINFO => $8
203         };
204         next;
205     }
206     print "Unknown keyword line: $_\n";
207 }
208
209 print "Root node: '$root_node'\n" if $debug;
210
211 # rewind input
212 seek (IDXFILE, 0, 0);
213
214 # Pass 2: get file information including multiple names (hard links) for the
215 #         same file
216
217
218 my $last_path = "";
219 my $last_inode = 0;
220 while (<IDXFILE>) {
221     chomp;
222     # emacs sucks with perl
223     if (/^#/) {
224         next;
225     }
226     if (/^DHd\s+([0-9]+)\s+(\S+)\s+UNIX+\s+([0-9]+)\s*$/) {
227         # directory entry inode $1 has name $2 pointing to inode $3
228         print "$1 => $2 $3\n" if $debug;
229
230         if (($2 eq ".") || ($2 eq "..")) {
231             next;
232         }
233
234         # find the pathname for this directory
235         my $path;
236         if ($last_inode == $1) {
237             $path = $last_path;
238         } else {
239            $last_path = $path = &find_path ($1);
240            $last_inode = $1;
241         }
242
243
244         # see if it is a directory
245         if ($inode{$3}{TYPE} eq "d") {
246             if ($do_empty_dirs && !$do_dirs) {
247                 if (exists $dir_entry_count{$3}) {
248                     next;
249                 }
250             } elsif (!$do_dirs) {
251                 # ignore directories
252                 next;
253             }
254         }
255
256
257         # print out path name for this entry
258         my $full_path;
259         if ($path eq "") {
260             $full_path = "$2";
261         } else {
262             $full_path = "$path/$2";
263         }
264
265         # translate "=" into %3d".
266         $full_path =~ s/=/%3d/g;
267
268         if ($do_inode != 0 || $debug) {
269             if ($do_fhinfo) {
270                 print "$inode{$3}{FHINFO} " . "$3" . ": $full_path\n";
271             } else {
272                 print "$3" . ": $full_path\n";
273             }
274         } else {
275             if ($do_fhinfo) {
276                 print "$inode{$3}{FHINFO} " . "$full_path\n";
277             } else {
278                 print "$full_path\n";
279             }
280         }
281
282         next;
283     }
284 }
285
286 close(IDXFILE);
287
288
289 #
290 # all done
291 #
292 exit 0;
293