fix references to old directory structure.
[xfstests-dev.git] / tools / db-walk
1 #!/usr/bin/perl -w
2
3 #
4 #  Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
5 #  
6 #  This program is free software; you can redistribute it and/or modify it
7 #  under the terms of version 2 of the GNU General Public License as
8 #  published by the Free Software Foundation.
9 #  
10 #  This program is distributed in the hope that it would be useful, but
11 #  WITHOUT ANY WARRANTY; without even the implied warranty of
12 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 #  
14 #  Further, this software is distributed without any warranty that it is
15 #  free of the rightful claim of any third person regarding infringement
16 #  or the like.  Any license provided herein, whether implied or
17 #  otherwise, applies only to this software file.  Patent licenses, if
18 #  any, provided herein do not apply to combinations of this program with
19 #  other software, or any other product whatsoever.
20 #  
21 #  You should have received a copy of the GNU General Public License along
22 #  with this program; if not, write the Free Software Foundation, Inc., 59
23 #  Temple Place - Suite 330, Boston MA 02111-1307, USA.
24 #  
25 #  Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
26 #  Mountain View, CA  94043, or:
27 #  
28 #  http://www.sgi.com 
29 #  
30 #  For further information regarding this notice, see: 
31 #  
32 #  http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
33 #
34
35 #
36 # use db to try to traverse the entire filesystem starting at the root
37 #
38 #                                                       dxm 5/10/00
39
40 my $device;
41 my $rootino;
42 my $agcount;
43 my $versionnum;
44 my $dir_version;
45 my @dir_inodes;
46 my @bmap_blocks;
47 my @block_inodes;
48 my $mode;
49
50 sub db($)
51 {
52     my ($args)=@_;
53     my ($ret);
54     
55     $ret=`xfs_db -r $args $device 2> /dev/null`;
56     die "ERROR executing xfs_db -r $args $device" if ($?);
57     
58     return $ret;
59 }
60
61 sub fmt($)
62 {
63     my ($text)=@_;
64     my $c=0;
65     print "        ";
66     foreach (split("\n",$text)) {
67         s/^core\.//;
68         
69         if ($c+length($_) >= 70) {
70             $c=0;
71             print ",\n        ";
72         }
73         if ($c) {
74             print ", ";
75             $c+=2;
76         }
77         print "$_";
78         $c+=length($_)+2;
79     }
80     print "\n";
81 }
82
83 sub inode($)
84 {
85     my ($num)=@_;
86     my ($t);
87     
88     @dir_inodes=();
89     
90     $t=db("-c \"inode $num\" -c \"print\"");
91     print "    *** Inode $num\n";
92     fmt($t);
93     
94     ($mode)= $t=~ /^core.mode = (\d+)$/m;
95     
96     if ($t=~ /a\.bmx/m) {
97         bmap("inode $num","attr");
98         foreach (@bmap_blocks) {
99             attr_block($_);
100         }
101     }
102     if (eval "$mode & 040000") {
103         if ( $t=~ /sfdir/m) {
104             while ($t=~ /inumber(?:\.i[48])? = (\d+)$/mg) {
105                 push(@dir_inodes,$1);
106             }
107         }
108         if ( $t=~ /u\.bmx/m) {
109             bmap("inode $num","dir");
110             foreach (@bmap_blocks) {
111                 dir_block($_);
112                 push(@dir_inodes,@block_inodes);
113             }
114         }
115     } else {
116         bmap("inode $num","file") if ( $t=~ /u\.bmx/m);
117     }
118 }
119
120 sub bmap($$)
121 {
122     my ($cmd,$type)=@_;
123     my ($t);
124     
125     @bmap_blocks=();
126     
127     $flag=($type eq "attr")?"-a":"";
128     
129     $t=db("-c \"$cmd\" -c \"bmap $flag\"");
130     print "    *** bmap $type $cmd\n";
131     fmt($t);
132     
133     if ($type eq "dir" || $type eq "attr") {
134         while ($t=~ /startblock (\d+) \(.+\) count (\d+)/mg) {
135             for ($b=$1;$b<$1+$2;$b++) {
136                 push(@bmap_blocks,$b);
137             }
138         }
139     }
140 }
141
142 sub dir_block($)
143 {
144     my ($num)=@_;
145     my ($t);
146     
147     @block_inodes=();
148     
149     $type=($dir_version==2)?"dir2":"dir";
150     
151     $t=db("-c \"fsblock $num\" -c \"type $type\" -c \"print\"");
152     print "    *** $type block $num\n";
153     # need to drop . and ..
154     ($self)= $t=~ /\[(\d+)\].name = \"\.\"/m;
155     ($parent)= $t=~ /\[(\d+)\].name = \"\.\.\"/m;
156     fmt($t);
157     
158     
159     while ($t=~ /\[(\d+)\].inumber = (\d+)/mg) {
160         next if (defined $self && $1 == $self);
161         next if (defined $parent && $1 == $parent);
162         push(@block_inodes, $2);
163     }
164 }
165
166 sub attr_block($)
167 {
168     my ($num)=@_;
169     my ($t);
170     
171     $t=db("-c \"fsblock $num\" -c \"type attr\" -c \"print\"");
172     print "    *** attr block $num\n";
173
174     fmt($t);
175 }
176
177 sub sb($)
178 {
179     my ($num)=@_;
180     my ($t);
181     
182     $t=db("-c \"sb $num\" -c \"print\"");
183     print "    *** SB $num\n";
184     fmt($t);
185     
186     ($rootino)= $t=~ /^rootino = (\d+)$/m;
187     ($agcount)= $t=~ /^agcount = (\d+)$/m;
188     ($versionnum)= $t=~ /^versionnum = (0x[\da-f]+)$/m;
189     $dir_version = (eval "$versionnum & 0x2000")?2:1;
190 }
191
192 die "Usage: $0 <XFS device>\n" unless (@ARGV == 1);
193
194 $device=shift @ARGV;
195 die "can't read $device\n" unless (-r $device);
196 die "$device is not a block device\n" unless (-b _);
197
198 chomp($HOST = `hostname -s`);
199
200 print "*** db-walk host $HOST device $device\n";
201
202 sb(0);
203 for ($ag=1;$ag<$agcount;$ag++) {
204     sb($ag);
205 }
206
207 @inodes=($rootino);
208 while ($_ = shift @inodes) {
209     inode($_);
210     push(@inodes,@dir_inodes);
211 }