| #!/usr/bin/perl |
| |
| # Copyright (C) 2013 STRATO. All rights reserved. |
| # |
| # This program is free software; you can redistribute it and/or |
| # modify it under the terms of the GNU General Public |
| # License v2 as published by the Free Software Foundation. |
| # |
| # This program is distributed in the hope that it will be useful, |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| # General Public License for more details. |
| # |
| # You should have received a copy of the GNU General Public |
| # License along with this program; if not, write to the |
| # Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
| # Boston, MA 021110-1307, USA. |
| |
| # WARNING: if you create large tests, inode assumptions by refgen.pl will break |
| # on btrfs and on zfs. |
| |
| use strict; |
| use warnings; |
| |
| sub get_next_offset { |
| my ($old, $increment, $numbers) = @_; |
| my $new = $old; |
| while ($numbers =~ /(\d+)/g) { |
| $new = $1 + $increment if ($new < $1 + $increment); |
| } |
| return $new; |
| } |
| |
| sub line_split { |
| my $line = shift; |
| if ($line =~ s/^(mk\S+) (\S+ \S+)//) { |
| # mk* commands have <ino> <name> as first 2 args |
| } elsif ($line =~ s/^(link|rename) (\S+ \S+)//) { |
| # link|rename commands have <name> <name> as first 2 args |
| } elsif ($line =~ s/^(\S+) (\S+)//) { |
| # other commands only have <name> as first arg |
| } elsif ($line =~ s/^(\S+)$//) { |
| # snapshot|remount commands have no args at all |
| } else { |
| die "line format not recognized in line $.\n"; |
| } |
| return ($1, $2, $line); |
| } |
| |
| my $next_offset = 0; |
| my %offset = (); |
| my $remount = 0; |
| my $snap = 0; |
| while (1) { |
| my $generated = 0; |
| my $cmd = ""; |
| foreach my $file (@ARGV) { |
| if (!open(F, "<", $file)) { |
| warn "skip! cannot open $file: $!\n"; |
| next; |
| } |
| my $header = 0; |
| my $skip_snap = 0; |
| my $skip_remount = 0; |
| $offset{$file} = $next_offset if (!exists $offset{$file}); |
| while (my $line = <F>) { |
| # skip everything up to the current snapshot |
| if ($skip_snap < $snap) { |
| ++$skip_snap if ($line =~ m/^snapshot$/); |
| next; |
| } |
| if ($skip_remount < $remount) { |
| ++$skip_remount if ($line =~ m/^remount$/); |
| next; |
| } |
| next if ($line =~ /^\s*#/ or $line =~ /^\s*$/); |
| if ($line =~ /^(snapshot|remount)$/) { |
| $cmd = $1; |
| last; |
| } |
| my ($cmd, $inodes, $args) = line_split($line); |
| if (!$header) { |
| print "# start snap $snap remount $remount " . |
| "file $file inode offset $offset{$file}" . |
| "\n"; |
| $header = 1; |
| } |
| if ($snap == 0 && $remount == 0) { |
| $next_offset = get_next_offset($next_offset, |
| $offset{$file}, |
| $inodes); |
| } |
| $inodes =~ s/(\d+)/$1 + $offset{$file}/ge; |
| print $cmd, " ", $inodes, $args; |
| $generated++; |
| } |
| while ($snap == 0 && $remount == 0 && (my $line = <F>)) { |
| next if ($line =~ /^\s*#/ or $line =~ /^\s*$/); |
| my ($cmd, $inodes, $args) = line_split($line); |
| next if !defined $inodes; |
| $next_offset = get_next_offset($next_offset, |
| $offset{$file}, $inodes); |
| } |
| close(F); |
| } |
| last if (!$generated); |
| if ($cmd eq "snapshot") { |
| ++$snap; |
| $remount = 0; |
| } elsif ($cmd eq "remount") { |
| ++$remount; |
| } else { |
| die "command $cmd"; |
| } |
| print $cmd, "\n"; |
| } |