Description: |
I've been having compact flash corruption problems lately so I decided to keep my CF as empty as possible and format it regularly. I've prepared this little script that keeps an eye on the system log to see when I plug the camera and then moves the pictures to a safe place. It needs to run as root but the real work is made in a separate, unpriviledged child. This way, all I have to do is plug the camera, watch the syslog for a while and unplug it again.
I tried quiet hard not to reinvent any wheel. If I did, please pull out your flamethrower. |
#!/usr/bin/perl -T
use warnings;
use strict;
use Sys::Syslog qw(:DEFAULT setlogsock);
use File::Tail;
use File::Copy 'mv';
use Proc::Daemon;
use POSIX qw/setuid setgid/;
my $kernlogfile = '/var/log/big_fat_file';
my $mntpath = '/media/nikon';
my $re = qr/kernel:\s+ Vendor:\s+ NIKON\s+ Model:\s+ NIKON\s+ DSC\s+ E
+2100\s+/x;
my $srcdir = "$mntpath/dcim/100nikon";
my $pixprefix = 'dscn';
my $destdir = '/home/hue/ftp/pix/priv/nikon';
my $user = 'hue';
$SIG{CHLD} = 'IGNORE';
$SIG{TERM} = \&sigterm_handler;
$ENV{PATH} = '/bin:/usr/bin';
sub sigterm_handler {
closelog;
exit 0;
}
sub do_log {
my $logstring = shift;
syslog 'LOG_DEBUG', '%s', $logstring;
}
sub move_files {
system '/bin/mount', $mntpath or do_log "Error mounting $mntpath:
+ $!", exit 1;
chdir $mntpath; # prevent fs from being unmounted under our feet
while (glob "$srcdir/$pixprefix*") {
$_ =~ m#^($srcdir/$pixprefix[0-9]{4}\.(?:jpg|mov))$#;
my $unt = $1;
do_log "Unexpected file name $_", next unless defined $unt;
do_log "Moving $unt";
mv $unt, $destdir or do_log "Error moving $_: $!"; #,
+ next;
}
chdir '/';
system '/bin/umount', $mntpath or do_log "Error unmounting $mntpat
+h: $!";
do_log "Finished moving";
exit 0;
}
Proc::Daemon::Init;
my (undef, undef, $uid, $gid) = getpwnam $user or do_log "User $user u
+nknown", exit 1;
setlogsock 'unix';
openlog 'nikon.pl', 'pid', 'LOG_LOCAL0';
my $tailfile = File::Tail->new (
name => $kernlogfile,
maxinterval => 5,
adjustafter => 10
);
while (defined (my $line = $tailfile->read)) {
next if $line !~ $re;
do_log "Camera detected";
defined (my $pid = fork) or do_log "Error forking: $!", next;
unless ($pid) {
setgid $gid;
do_log "Error setting gid $gid", exit 1 if $!;
## /bin/mount needs both uid and euid to be set
setuid $uid;
do_log "Error setting uid $uid", exit 1 if $!;
move_files;
}
}
do_log "Something wicked happened reading $kernlogfile. Exiting...";
$SIG{TERM}->();
|