File btrfs-dev-clear-sb of Package btrfsprogs

#!/usr/bin/perl

# clear btrfs signature from a device

use Fcntl;

use constant BTRFS_SUPER_INFO_OFFSET => 64 * 1024;
use constant BTRFS_SUPER_INFO_SIZE => 4096;

use constant BTRFS_SUPER_MIRROR_MAX => 3;
use constant BTRFS_SUPER_MIRROR_SHIFT => 12;

use constant BTRFS_MAGIC => "_BHRfS_M";
use constant BTRFS_DEAD  => '_BHRf$_M';

sub btrfs_sb_offset($) {
	my $mirror =$_[0];
	my $start = 16 * 1024;
	if ($mirror>0) {
		return $start << (BTRFS_SUPER_MIRROR_SHIFT * $mirror);
	}
	return BTRFS_SUPER_INFO_OFFSET;
}

my $dbg=1;
my $savesb=0;

# main
my $dev=$ARGV[0];
my $size;
if(!-b $dev) {
	print("Not a block device: $dev\n");
	$size=(stat($dev))[7];
} else {
	$size=`blkdev --getsize64 "$dev"`;
}
sysopen(F, $dev, O_EXCL | O_RDWR) or die("Cannot open $dev exclusively: $!");
sysseek(F, 0, 2);
$size=tell(F);
print("Device size: $size\n") if($dbg);
for(my $i=0;$i<6;$i++) {
	my $off=btrfs_sb_offset($i);
	if($off > $size) {
		print("Offset for SB $i beyond EOF\n") if($dbg);
		last;
	}
	print("Offset $i is $off\n") if($dbg);
	sysseek(F, $off, 0);
	sysread(F, $buf, BTRFS_SUPER_INFO_SIZE);
	if($savesb) {
		open(Q,">SB$i");
		print Q ($buf);
		close(Q);
	}
	my $sbmagic=substr($buf, 0x40, length(BTRFS_MAGIC));
	print("SB magic: $sbmagic\n") if($dbg);
	if(BTRFS_MAGIC eq $sbmagic) {
		print("Found a valid signature of superblock $i\n");
		sysseek(F, $off + 0x40, 0);
		print("Clearing...\n");
		syswrite(F, BTRFS_DEAD, length(BTRFS_DEAD));
	} elsif(BTRFS_DEAD eq $sbmagic) {
		print("Found a signature of a dead superblock $i\n");
	} else {
		print("Superblock $i does not look like a btrfs one\n");
	}
}
close(F);
print("Syncing dev\n");
system("fsync \'$dev\'");
openSUSE Build Service is sponsored by