summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordakkar <dakkar@thenautilus.net>2009-09-01 17:00:31 +0200
committerdakkar <dakkar@thenautilus.net>2009-09-01 17:00:31 +0200
commit8cd87b3d2746da3ff0e0b67d7c09e89aa1f6fa15 (patch)
tree9a2cd439f562128345a66a5e82e10933badbc7d9
downloadhal-automounter-8cd87b3d2746da3ff0e0b67d7c09e89aa1f6fa15.tar.gz
hal-automounter-8cd87b3d2746da3ff0e0b67d7c09e89aa1f6fa15.tar.bz2
hal-automounter-8cd87b3d2746da3ff0e0b67d7c09e89aa1f6fa15.zip
initial import
-rwxr-xr-xhal-automounter.pl194
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();