3
# Written by Oron Peled <oron@actcom.co.il>
4
# Copyright (C) 2012, Xorcom
5
# This program is free software; you can redistribute and/or
6
# modify it under the same terms as Perl itself.
8
#dahdi_sysfs_copy: Short perl script to copy dahdi related sysfs trees
9
# into a designated directory.
16
use File::Path qw(mkpath);
20
my $destdir = shift || die "Usage: $0 <destdir>\n";
26
# Starting points for recursion
28
/sys/bus/dahdi_devices
33
# Loop prevention (by inode number lookup)
35
my $ino = shift || die;
36
my $path = shift || die;
37
if(defined $inode_cash{$ino}) {
38
#print STDERR "DEBUG($ino): $path\n";
45
# Walk up a path and copy readable attributes from any
48
my $path = shift || die;
51
for (my $curr = $path; $curr; $curr =~ s'/?[^/]+$'') {
52
my ($dev, $ino, $mode, $nlink, $uid, $gid) = lstat($curr);
53
next if seen($ino, $curr); # Skip visited directories
55
opendir(my $d, $curr) || die "Failed opendir($curr): $!\n";
56
my @entries = readdir $d;
57
foreach my $entry (@entries) {
58
next if $entry =~ /^[.][.]?$/;
59
my $file = "$curr/$entry";
60
my ($dev, $ino, $mode, $nlink, $uid, $gid) = lstat($file);
62
if (-f _ && ($mode & 0004)) { # The '-r _' is buggy
63
copy($file, "$destdir$file") ||
64
die "Failed to copy '$file': $!\n";
71
# Handle a given path (directory,symlink,regular-file)
73
my $path = shift || die;
74
my ($dev, $ino, $mode, $nlink, $uid, $gid) = lstat($path);
75
# Save attributes before recursion starts
78
my $isreadable = $mode & 00004; # The '-r _' was buggy
79
return if seen($ino, $path); # Loop prevention
80
my $dest = "$destdir/$path";
83
scan_directory($path);
85
# We follow links (the seen() protect us from loops)
86
my $target = readlink($path) ||
87
die "Failed readlink($path): $!\n";
89
if ($target !~ m{^/}) { # fix relative symlinks
92
$follow = realpath("$dir/$target");
94
# Save symlink details, so we create them after all
95
# destination tree (subdirectories, files) is ready
96
die "Duplicate entry '$dest'\n" if exists $symlinks{$dest};
97
$symlinks{$dest} = "$target";
100
$walk_ups{$follow}++;
101
} elsif ($isreadable) {
102
copy($path, "$dest") ||
103
die "Failed to copy '$path': $!\n";
107
# Scan a given directory (calling handle_path for recursion)
109
my $dir = shift || die;
111
opendir(my $d, $dir) || die "Failed opendir($dir): $!\n";
112
my @dirs = readdir $d;
113
foreach my $entry (@dirs) {
114
next if $entry =~ /^[.][.]?$/;
115
handle_path("$dir/$entry");
120
# Filter out non-existing toplevels
121
my @scan = grep { lstat($_) } @toplevels;
123
# Recurse all trees, creating subdirectories and copying files
124
foreach my $path (@scan) {
128
# Now, that all sub-directories were created, we can
129
# create the wanted symlinks
130
for my $dest (keys %symlinks) {
131
my $link = $symlinks{$dest};
132
die "Missing link for '$dest'\n" unless defined $link;
133
unlink $dest if -l $dest;
134
symlink($link,$dest) ||
135
die "Failed symlink($link,$dest): $!\n";
138
# Walk up directories that were symlink destinations
139
# and fill their attributes
140
foreach my $dir (keys %walk_ups) {