diff options
author | dakkar <dakkar@thenautilus.net> | 2009-09-01 17:00:31 +0200 |
---|---|---|
committer | dakkar <dakkar@thenautilus.net> | 2009-09-01 17:00:31 +0200 |
commit | 8cd87b3d2746da3ff0e0b67d7c09e89aa1f6fa15 (patch) | |
tree | 9a2cd439f562128345a66a5e82e10933badbc7d9 /hal-automounter.pl | |
download | hal-automounter-8cd87b3d2746da3ff0e0b67d7c09e89aa1f6fa15.tar.gz hal-automounter-8cd87b3d2746da3ff0e0b67d7c09e89aa1f6fa15.tar.bz2 hal-automounter-8cd87b3d2746da3ff0e0b67d7c09e89aa1f6fa15.zip |
initial import
Diffstat (limited to 'hal-automounter.pl')
-rwxr-xr-x | hal-automounter.pl | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/hal-automounter.pl b/hal-automounter.pl new file mode 100755 index 0000000..2ea4133 --- /dev/null +++ b/hal-automounter.pl @@ -0,0 +1,194 @@ +#!/usr/bin/perl +use strict; +use warnings; +use lib '/home/dakkar/perl5/lib/perl5','/home/dakkar/perl5/lib/perl5/x86_64-linux-thread-multi'; + +use Net::DBus; +use Net::DBus::Reactor; +use File::Temp; +use Cwd 'realpath'; + +sub add_to_fstab { + my ($dev_path,$mount_point,$fs_type,$opts)=@_; + + my @orig_stat=stat('/etc/fstab'); + my $tfh=File::Temp->new(DIR=>'/etc'); + $tfh->unlink_on_destroy(1); + + while(1) { + seek $tfh,0,0; + truncate $tfh,0; + open my $in_fh,'<','/etc/fstab'; + while (my $line=<$in_fh>) { + next if $line =~ m{\A \s* \#}smx; + my ($in_dev,$in_path,$in_fs,$in_opts)= + ($line=~m{\A \s* (\S+) \s+ (\S+) \s+ (\S+) \s+ (\S+) }smx) + or next; + if (-e $in_dev + && (realpath($in_dev) eq realpath($dev_path))) { + # it's already in there, abort + return $in_path; + } + } + continue { + print {$tfh} $line; + }; + print {$tfh} "$dev_path $mount_point $fs_type $opts 0 0 # dakkar\n"; + if ((stat('/etc/fstab'))[9] == $orig_stat[9]) { + rename "$tfh",'/etc/fstab'; + chmod $orig_stat[2],'/etc/fstab'; + chown @orig_stat[4,5],'/etc/fstab'; + return; + } + # fstab has changed, re-run the whole thing + } +} + +sub remove_from_fstab { + my ($mount_point)=@_; + + my @orig_stat=stat('/etc/fstab'); + my $tfh=File::Temp->new(DIR=>'/etc'); + $tfh->unlink_on_destroy(1); + + my $was_there=0; + + while(1) { + seek $tfh,0,0; + truncate $tfh,0; + open my $in_fh,'<','/etc/fstab'; + while (my $line=<$in_fh>) { + next if $line =~ m{\A \s* \#}smx; + my ($in_dev,$in_path,$in_fs,$in_opts,$comms)= + ($line=~m{\A \s* (\S+) \s+ (\S+) \s+ (\S+) \s+ (\S+) \s+ \d+ \s+ \d+ (?: \s* \# (.*) )?}smx); + if (defined($comms) && ($comms eq " dakkar\n") + && ($in_path eq $mount_point)) { + # ok, it's the right line, kill it + $line='';$was_there=1; + } + } + continue { + print {$tfh} $line; + }; + if ((stat('/etc/fstab'))[9] == $orig_stat[9]) { + rename "$tfh",'/etc/fstab'; + chmod $orig_stat[2],'/etc/fstab'; + chown @orig_stat[4,5],'/etc/fstab'; + return 1 if $was_there; + return; + } + # fstab has changed, re-run the whole thing + } +} + +my $bus=Net::DBus->system(); +my $hal=$bus->get_service('org.freedesktop.Hal'); + +my %ignore;my %mounted; + +sub sanitize { + my ($path)=@_; + + $path=~s{\s}{-}g; + $path=~s{/+}{_}g; + + return $path; +} + +sub safe_get_property { + my ($dev,$prop)=@_; + + local $@; + return eval {$dev->GetProperty($prop)} +} + +sub device_added { + my $dev=$hal->get_object($_[0],'org.freedesktop.Hal.Device'); + my $caps=safe_get_property($dev,'info.capabilities'); + return unless $caps; + my %caps;@caps{@$caps}=(); + + if (exists($caps{storage})) { + my $should_automount= + safe_get_property($dev,'storage.automount_enabled_hint'); + if (!$should_automount) { + $ignore{$_[0]}=1; + } + return; + } + + if (exists($caps{volume})) { + + my $parent=safe_get_property($dev,'info.parent'); + + if ($ignore{$parent}) { + warn "ignoring $_[0]\n"; + return; + } + + if (safe_get_property($dev,'volume.ignore')) { + warn "ignoring $_[0]\n"; + return; + } + + my $uuid=safe_get_property($dev,'volume.uuid'); + + my $dev_path=safe_get_property($dev,'linux.device_file') + ||safe_get_property($dev,'volume.linux.device_file') + ||($uuid?'/dev/disk/by-uuid/'.$uuid:undef) + || 'unknown'; + if ($dev_path eq 'unknown') { + warn "unknown path for $_[0]\n"; + return; + } + + my $usage=safe_get_property($dev,'volume.fsusage'); + return unless $usage eq 'filesystem'; + + my $label=safe_get_property($dev,'volume.label'); + + my $fstype=safe_get_property($dev,'volume.fstype'); + + return unless defined $fstype; + + my $mountpoint='/mnt/'.(sanitize($label)||$uuid); + + if (-e $mountpoint) { + $mountpoint.='-0'; + while (-e $mountpoint) {++$mountpoint}; + } + + my $manual_mountpoint=add_to_fstab($dev_path,$mountpoint,$fstype,'users,noauto,noatime,nodiratime,nosuid,nodev'); + + $mountpoint=$manual_mountpoint if defined $manual_mountpoint; + + $mounted{$_[0]}=$mountpoint; + mkdir $mountpoint; + chown -1,scalar(getgrnam('plugdev')),$mountpoint; + chmod 0775,$mountpoint; + } + + return; +} + +sub device_removed { + delete $ignore{$_[0]}; + if (exists $mounted{$_[0]}) { + system('umount',$mounted{$_[0]}); + if (remove_from_fstab($mounted{$_[0]})) { + rmdir $mounted{$_[0]}; + } + delete $mounted{$_[0]}; + } + return; +} + +my $reactor=Net::DBus::Reactor->main(); + +my $manager = $hal->get_object('/org/freedesktop/Hal/Manager', + 'org.freedesktop.Hal.Manager'); + +$manager->connect_to_signal('DeviceAdded',\&device_added); +$manager->connect_to_signal('DeviceRemoved',\&device_removed); + +$reactor->run(); |