mirror of
https://github.com/linux-apfs/apfstests.git
synced 2026-05-01 15:01:44 -07:00
272 lines
7.4 KiB
Perl
Executable File
272 lines
7.4 KiB
Perl
Executable File
#!/usr/bin/perl -w
|
|
use strict;
|
|
#
|
|
# srcdiff is used to compare current user level code with the current
|
|
# kernel code and advise of any differences between files which are
|
|
# sharing some or all of their content.
|
|
#
|
|
# There are two classes of sharing which we will check - header files
|
|
# in the include directory, which must be exactly the same (use diff)
|
|
# and source files which contain routines which must be exactly the
|
|
# same (but the userland file is always a subset of the kernel file,
|
|
# and hence a more flexible mechanism to "diff" is required).
|
|
#
|
|
# NB: to cross check that srcdiff is finding all the functions in the
|
|
# user source file, providing you have "mkproto" installed, you
|
|
# can "cd cmd/xfsprogs/libxfs" and cut&paste this in a bourne shell:
|
|
# $ for file in xfs_*.c; do
|
|
# > mkproto -nps < $file | perl -ne '
|
|
# > END { print " $count\t- " }
|
|
# > s/^.* (xfs\w+|\*xfs\w+|xlog\w+|\*xlog\w+) \(.*/\1/ && { $count++ }'
|
|
# > echo $file
|
|
# > done
|
|
# (compare this to "srcdiff | fgrep Total:")
|
|
#
|
|
|
|
die "WORKAREA not set" unless defined $ENV{'WORKAREA'};
|
|
chdir $ENV{'WORKAREA'};
|
|
my $xdiff = $ENV{'XDIFF'};
|
|
my $quiet=0;
|
|
my $usage=0;
|
|
|
|
foreach (@ARGV) {
|
|
if (/^-q$/) {
|
|
$quiet++;
|
|
} else {
|
|
print STDERR "Illegal option $_\n";
|
|
$usage++;
|
|
}
|
|
}
|
|
|
|
if ($usage) {
|
|
print STDERR "Usage: $0 [-q]\n";
|
|
exit 1;
|
|
}
|
|
|
|
my @pkglist = qw( attr acl dmapi xfsdump xfsprogs );
|
|
my @difflist = qw(
|
|
xfs_ag.h xfs_alloc.h xfs_alloc_btree.h xfs_arch.h
|
|
xfs_attr_leaf.h xfs_attr_sf.h xfs_bit.h xfs_bmap.h
|
|
xfs_bmap_btree.h xfs_btree.h xfs_buf_item.h
|
|
xfs_da_btree.h xfs_dfrag.h xfs_dinode.h xfs_dir.h
|
|
xfs_dir2.h xfs_dir2_block.h xfs_dir2_data.h
|
|
xfs_dir2_leaf.h xfs_dir2_node.h xfs_dir2_sf.h
|
|
xfs_dir_leaf.h xfs_dir_sf.h xfs_dqblk.h xfs_dquot_item.h
|
|
xfs_extfree_item.h xfs_ialloc.h xfs_imap.h
|
|
xfs_ialloc_btree.h xfs_inode.h xfs_inode_item.h
|
|
xfs_inum.h xfs_log.h xfs_log_priv.h xfs_log_recover.h
|
|
xfs_mount.h xfs_quota.h xfs_rtalloc.h
|
|
xfs_sb.h xfs_trans.h xfs_trans_space.h xfs_types.h
|
|
xfs_fs.h xfs_acl.h xfs_cap.h xfs_mac.h
|
|
);
|
|
|
|
sub straightdiff {
|
|
my ( $file, $prefix1, $prefix2 ) = @_;
|
|
|
|
`diff $prefix1/$file $prefix2/$file >/dev/null 2>&1`;
|
|
if (!$quiet) {
|
|
print sprintf("\t%-35s ... ", $file);
|
|
if ($? != 0) { print "FAILED\n"; }
|
|
else { print "ok\n"; }
|
|
} elsif ($? != 0) {
|
|
printf("\t%-35s ... ", $file);
|
|
print "FAILED\n";
|
|
}
|
|
}
|
|
|
|
my $first = shift @pkglist;
|
|
foreach (@pkglist) {
|
|
print "\n=== Checking $_ package ===\n";
|
|
straightdiff 'buildrules', "cmd/$first/include", "cmd/$_/include";
|
|
straightdiff 'buildmacros', "cmd/$first/include", "cmd/$_/include";
|
|
}
|
|
print "\n=== Checking headers ===\n";
|
|
foreach (@difflist) {
|
|
straightdiff $_, 'cmd/xfsprogs/include', 'linux/fs/xfs';
|
|
}
|
|
straightdiff 'dmapi_kern.h', 'cmd/dmapi/include', 'linux/include/linux';
|
|
straightdiff 'dmapi.h', 'cmd/dmapi/include', 'linux/include/linux';
|
|
straightdiff 'arch.h', 'cmd/xfsprogs/include', 'linux/fs/xfs/support';
|
|
|
|
#
|
|
# setstate
|
|
# Implements a tri-state FSA, see comments for state transitions
|
|
# (knows about the way the XFS kernel code is written, & makes
|
|
# some assumptions so as to not need to parse generic C code).
|
|
# Accepts one line at a time from a source file, picking out the
|
|
# function bodies so they can be subsequently compared.
|
|
#
|
|
|
|
my $line; # line number in current source file
|
|
my $state; # current FSA state
|
|
my $funcbody; # current function body (contents)
|
|
|
|
sub setstate {
|
|
my ( $newline ) = @_;
|
|
$line++;
|
|
|
|
# - state 0:
|
|
# if line looks like start of a function, transition to 1
|
|
# & squirrel line away as line 1 of current function
|
|
if ($state == 0) {
|
|
if ($newline =~ m/^[xfs|xlog]/) {
|
|
$state = 1;
|
|
$funcbody = $newline;
|
|
}
|
|
}
|
|
|
|
# - state 1:
|
|
# if line looks like start of a function, stay here
|
|
# & squirrel line away as line 1 of current function
|
|
# otherwise if line isn't start of function body,
|
|
# squirrel line away as next line of current function
|
|
# (args/..., but not sure this is a real function yet)
|
|
# otherwise (start of function)
|
|
# squirrel line away as next line of current function
|
|
# transition to state 2
|
|
elsif ($state == 1) {
|
|
if ($newline =~ m/^[xfs|xlog]/) {
|
|
$funcbody = $newline;
|
|
}
|
|
elsif ($newline =~ m/^\{/) {
|
|
$state = 2;
|
|
$funcbody .= $newline;
|
|
}
|
|
}
|
|
|
|
# - state 2:
|
|
# if line looks like end of function body,
|
|
# squirrel line away as last line of current function
|
|
# tell someone we have a complete function ready
|
|
# transition to state 0
|
|
# otherwise
|
|
# squirrel line away as next line of current function
|
|
elsif ($state == 2) {
|
|
$funcbody .= $newline;
|
|
if ($newline =~ m/^\}/) {
|
|
$state = 0;
|
|
return $funcbody;
|
|
}
|
|
}
|
|
|
|
else {
|
|
die "unknown state transition";
|
|
}
|
|
return undef; # i.e. not at end of a function
|
|
}
|
|
|
|
sub listfuncs {
|
|
my ( $file ) = @_;
|
|
my @funcs;
|
|
|
|
$funcbody = '';
|
|
$state = $line = 0;
|
|
|
|
open(USER, "$file") || die "cannot open $file";
|
|
while (<USER>) {
|
|
my $func = setstate($_);
|
|
push @funcs, $func if (defined($func)); # store function away
|
|
}
|
|
close USER;
|
|
return @funcs;
|
|
}
|
|
|
|
sub hashfuncs {
|
|
my ( $file ) = @_;
|
|
my %funcs;
|
|
|
|
$funcbody = '';
|
|
$state = $line = 0;
|
|
|
|
open(KERN, "$file") || die "cannot open $file";
|
|
while (<KERN>) {
|
|
my $func = setstate($_);
|
|
if (defined($func)) {
|
|
$func =~ m/^([xfs|xlog]\w+)\s*\(/;
|
|
next unless defined($1);
|
|
my $name = $1;
|
|
if (defined($func)) {
|
|
$funcs{$name} = $func; # store function away
|
|
}
|
|
}
|
|
}
|
|
close KERN;
|
|
return %funcs;
|
|
}
|
|
|
|
sub diffme {
|
|
my ( $sa, $sb ) = @_;
|
|
|
|
return unless defined($xdiff);
|
|
|
|
open(FILEA, "> /tmp/diff.user.$$") || die "cannot write to /tmp/diff.user.$$";
|
|
open(FILEB, "> /tmp/diff.kern.$$") || die "cannot write to /tmp/diff.kern.$$";
|
|
print FILEA $sa;
|
|
print FILEB $sb;
|
|
close FILEA;
|
|
close FILEB;
|
|
`$xdiff /tmp/diff.user.$$ /tmp/diff.kern.$$`;
|
|
unlink ("/tmp/diff.user.$$","/tmp/diff.kern.$$");
|
|
}
|
|
|
|
sub functiondiff {
|
|
my ( $file, $prefix1, $prefix2 ) = @_;
|
|
my $plural = '';
|
|
my $count = 0;
|
|
my $name;
|
|
my $found = 0;
|
|
|
|
print "\n=== Checking $file routines ===\n" unless ($quiet);
|
|
|
|
# iterate over user funcs, match up to kernel funcs
|
|
#
|
|
my @user = listfuncs "$prefix1/$file";
|
|
my %kern = hashfuncs "$prefix2/$file";
|
|
|
|
foreach my $userfunc (@user) {
|
|
|
|
$userfunc =~ m/^([xfs|xlog]\w+)\s*\(/;
|
|
next unless (defined($1));
|
|
$name = $1;
|
|
$count++;
|
|
|
|
if (exists($kern{$name})) {
|
|
if ($userfunc ne $kern{$name}) {
|
|
print "\n=== $file routines ===\n"
|
|
if (!$found++ && $quiet);
|
|
|
|
printf("\t%-35s ... ", $name);
|
|
print "FAILED\n";
|
|
diffme $userfunc, $kern{$name};
|
|
}
|
|
elsif (!$quiet) {
|
|
printf("\t%-35s ... ", $name);
|
|
print "ok\n";
|
|
}
|
|
}
|
|
else {
|
|
print "Cannot find kernel function $userfunc";
|
|
print " in file $prefix2/$file\n";
|
|
}
|
|
}
|
|
($count != 1) && ( $plural = 's' );
|
|
print "( Total: $count routine$plural checked in $file )\n" unless ($quiet);
|
|
}
|
|
|
|
# cmd/xfsprogs/{libxfs,libxlog}/* fs/xfs/*
|
|
my @funclist = qw(
|
|
xfs_alloc.c xfs_alloc_btree.c xfs_attr_leaf.c
|
|
xfs_bmap.c xfs_bmap_btree.c xfs_btree.c xfs_da_btree.c
|
|
xfs_dir.c xfs_dir2.c xfs_dir2_block.c xfs_dir2_data.c
|
|
xfs_dir2_leaf.c xfs_dir2_node.c xfs_dir2_sf.c
|
|
xfs_dir_leaf.c xfs_ialloc.c xfs_ialloc_btree.c
|
|
xfs_inode.c xfs_rtalloc.c xfs_mount.c xfs_trans.c
|
|
);
|
|
|
|
print "\n=== Checking libxfs code ===\n";
|
|
foreach (@funclist) {
|
|
functiondiff $_, 'cmd/xfsprogs/libxfs', 'linux/fs/xfs';
|
|
}
|
|
print "\n=== Checking libxlog code ===\n";
|
|
functiondiff 'xfs_log_recover.c', 'cmd/xfsprogs/libxlog', 'linux/fs/xfs';
|