#!/usr/bin/perl #H# This script performs regular maintenance tasks to keep my database in sync with #H# my file system. #H# #H# Commands: #H# info [filename] #H# Prints the information about a file from sored in the db #H# add [filename] #H# Initially adds a file to the system and the db. #H# File will be moved to /home/asylum/kmk/graphics/pics #H# And a thumbnail in /home/asylum/kmk/graphics/pics/.thumbnails #H# rename [old filename] [new filename] #H# Renames a file and updates the db. #H# kill [filename] #H# Removes a file from both the database and the filesystem! #H# takedown [filename] #H# Marks a file as not available but doesn't hurt it. #H# verify [filename] #H# Verifies the validity of a file based on the md5sum sored in the db #H# verifyall [q] #H# Verifies all files in the db #H# [q] is an optional parameter that silences all of the "OK" lines. #H# md5 [filename] #H# Updates the md5sum in the db #H# replace [old filename] [new filename] #H# replaces an existing file with a new one # print out help info if requested if ($ARGV[0] eq "-h" || $ARGV[0] eq "--help" || $ARGV[0] eq "help" || $ARGV[0] eq "") { open (SELF, $0); while () { if ($_ =~ /^#H# /) { $_ =~ s/^#H# //; print $_; } } exit; } # open the music database and load modules use Date::Format; use DBI; $DB= DBI->connect("DBI:mysql:www:asylum.sanitarium.net" . ";mysql_read_default_file=/home/asylum/kmk/.my.cnf", kmk, $password); # figure out which command we are running here $Command=$ARGV[0]; chomp $Command; if ($Command ne "verifyall") { # Might as well figure all this crap out before even bothering to figure out what # command we are processing since almost all will need it. # The verifydir and index commands don't use any params so there is nothing to # do for them until the command specific stuff. # The file name is almost always the first param (after the command) so suck it in now # and replace it later if needed. $FileNameParam=$ARGV[1]; # find the real full path to the file name so I can use relative paths on the CLI $FullPath=`realpath "$FileNameParam"`; chomp $FullPath; @PathParts = split (/\//,$FullPath); foreach $PathPart (@PathParts) { $FileName=$PathPart; } if ($Command ne "add") { # Might as well grab this here to unless the command isn't going to need it. # This pulls the current info on the file out of the db so it will be on hand later. # The add and tag commands assume the file isn't in the db yet. $ID="N"; $SafeFileName=$FileName; $SafeFileName =~ s/'/\\'/g; $QueryString="select * from pics where PicFileName='$SafeFileName'"; $QueryHandle=$DB->prepare($QueryString); $QueryHandle->execute; while (@Data=$QueryHandle->fetchrow_array) { ($PicID,$PicFileName,$PicWidth,$PicHeight,$PicSize,$ThumbWidth,$ThumbHeight,$pichitcount,$IsAvailable,$DateAdded,$md5sum,$Location)=@Data; } } } if ($Command eq "info") { # code for info command # sanity check to make sure the file actually existed in the query above. if ($PicID eq "N") { die "File not found in database!\n"; } $PicResolution="$PicWidth" . "x" . "$PicHeight"; $ThumbResolution="$ThumbWidth" . "x" . "$ThumbHeight"; print "PicID: $PicID\n"; print "PicFileName: $PicFileName\n"; print "PicResolution: $PicResolution\n"; print "PicSize: $PicSize\n"; print "ThumbResolution: $ThumbResolution\n"; print "pichitcount: $pichitcount\n"; print "IsAvailable: $IsAvailable\n"; print "DateAdded: $DateAdded\n"; print "md5sum: $md5sum\n"; print "Location: $Location\n"; } elsif ($Command eq "add") { # code for add command. # quick check for params before we start touching things. # make sure that the file exists. Then get info about it. $FileName=$FileNameParam; open (FH, "$FileName") || die "Can't open file."; ($FileSize,$Ctime)=(stat(FH))[7,10]; close(FH); # grab an md5sum... open (TH, qq[md5sum "$FileName" |]); $MD5SumText=; close (TH); chomp $MD5SumText; ($MD5Sum,$junk)=split (/ /,$MD5SumText,2); # check for already existing file or md5sum (both are fatal) $QueryString="select PicFileName,md5sum from pics where PicFileName='$FileName' or md5sum='$MD5Sum'"; $QueryHandle=$DB->prepare($QueryString); $QueryHandle->execute; while (@Data=$QueryHandle->fetchrow_array) { ($ExistingFileName,$ExistingMD5Sum)=@Data; if ($ExistingFileName eq $FileName) { die "ERROR: $ExistingFileName already exists!\n"; } if ($ExistingMD5Sum eq $MD5Sum) { die "ERROR: $ExistingFileName is the same file!\n"; } } # move the file... $PicDir="/home/asylum/kmk/graphics/pics"; $ThumbDir="/home/asylum/kmk/graphics/pics/.thumbnails"; system ("mv -v $FileName $PicDir/"); $Line=`/usr/bin/convert -verbose -geometry 100x100 "$PicDir/$FileName" "$ThumbDir/$FileName" | tail -n 1`; chomp $Line; # /home/asylum/kmk/graphics/pics/2009-FXSTC-left-bags-640.jpg=>/home/asylum/kmk/graphics/pics/.thumbnails/2009-FXSTC-left-bags-640.jpg JPEG 640x398=>100x62 100x62+0+0 8-bit DirectClass 0.060u 0:00.029 # 640x398=>100x62 $Line =~ s/[\[\]\(\)]//g; ($Junk,$Junk,$Res,$Junk)=split (/ /,$Line,4); #$Res =~ s/\+0//g; ($PicRes,$ThumbRes)=split (/=>/,$Res,2); ($PicWidth,$PicHeight)=split (/x/,$PicRes,2); ($ThumbWidth,$ThumbHeight)=split (/x/,$ThumbRes,2); # fix perms... system (qq[chmod 644 "$PicDir/$FileName" "$ThumbDir/$FileName"]); system (qq[touch "$PicDir/$FileName" "$ThumbDir/$FileName"]); # do the insert $InsertString="insert into pics values (null,'$FileName','$PicWidth','$PicHeight','$FileSize','$ThumbWidth','$ThumbHeight',0,'Y',now(),'$MD5Sum','asylum')"; $InsertHandle=$DB->prepare($InsertString); $InsertHandle->execute; } elsif ($Command eq "rename") { # rename code here. # quick sanity check... if ($PicID eq "N") { die "File not found in database!\n"; } $NewFileName=$ARGV[2]; # Rename the file first system (qq[mv -v "$FileName" "$NewFileName"]); # rename the thumbnail too... system (qq[mv -v ".thumbnails/$FileName" ".thumbnails/$NewFileName"]); # update the db entry. $UpdateString="update pics set PicFileName='$NewFileName' where PicID=$PicID"; $UpdateHandle=$DB->prepare($UpdateString); $UpdateHandle->execute; } elsif ($Command eq "kill") { # file deleting code here... # quick sanity check if ($PicID eq "N") { die "File not found in database!\n"; } print "Deleting ID# $PicID\n"; # actually delete the file and the thumbnail system (qq[rm -v "/home/asylum/kmk/graphics/pics/$FileNameParam" "/home/asylum/kmk/graphics/pics/.thumbnails/$FileNameParam"]); # I don't actually remove db entries for pics. $UpdateString="delete from pics where PicID=$PicID"; $UpdateHandle=$DB->prepare($UpdateString); $UpdateHandle->execute; } elsif ($Command eq "takedown") { # file deleting code here... # quick sanity check if ($PicID eq "N") { die "File not found in database!\n"; } print "Taging down ID# $PicID\n"; # I don't actually remove db entries for pics. $UpdateString="update pics set IsAvailable='N' where PicID=$PicID"; $UpdateHandle=$DB->prepare($UpdateString); $UpdateHandle->execute; } elsif ($Command eq "verify") { # file verify code here... # quick sanity check if ($PicID eq "N") { die "File not found in database!\n"; } print "$FileNameParam: "; # Open the file and get the current size of it. # no sense in md5summing the file if it isn't even the same size. open (FH, "$FileNameParam") || die "Can't open file."; ($CurrentFileSize,$Ctime)=(stat(FH))[7,10]; close(FH); if ($CurrentFileSize != $PicSize) { print "FAILED (wrong size)\n"; } else { # grab the current md5sum of the file and compare open (TH, qq[md5sum "$FileNameParam" |]); $MD5SumText=; close (TH); chomp $MD5SumText; ($CurrentMD5Sum,$junk)=split (/ /,$MD5SumText,2); if ($CurrentMD5Sum ne $md5sum) { print "FAILED (md5)\n"; } else { print "OK\n"; } } } elsif ($Command eq "verifyall") { # file verifydir code here... # there are NO params for this command. # get the current dir # Find all files in the current dir and the dirs under it (from the db) $QueryString="select PicFileName,md5sum from pics where IsAvailable='Y' order by PicFileName"; $QueryHandle=$DB->prepare($QueryString); $QueryHandle->execute; # this will be a standard md5sum file in a minute open (MD5FILE, ">/tmp/temp.kmk.picdb.verifyall.md5"); while (@Data=$QueryHandle->fetchrow_array) { ($FileName,$md5sum)=@Data; # write out the md5sum file print (MD5FILE "$md5sum $FileName\n"); } close (MD5FILE); # verify the files with md5sum -c open (MD5, qq[md5sum -c "/tmp/temp.kmk.picdb.verifyall.md5" |]); while () { if ($ARGV[1] !~ /q/) { print $_; } else { if ($_ !~ /OK$/) { print $_; } } } close (MD5); # get rid of the temp file system (qq[rm "/tmp/temp.kmk.picdb.verifyall.md5"]); } elsif ($Command eq "md5") { # file md5 code here... # quick sanity check if ($PicID eq "N") { die "File not found in database!\n"; } # grab the current md5sum of the file open (TH, qq[md5sum "$FileNameParam" |]); $MD5SumText=; close (TH); chomp $MD5SumText; ($MD5Sum,$junk)=split (/ /,$MD5SumText,2); # update the db $UpdateString="update pics set md5sum='$MD5Sum' where PicID=$PicID"; $UpdateHandle=$DB->prepare($UpdateString); $UpdateHandle->execute; } elsif ($Command eq "replace") { die "Replace doesn't work yet!\n"; # quick sanity check if ($PicID eq "N") { die "File not found in database!\n"; } $ReplacementFileName=$ARGV[1]; # remove the old file... system (qq[picdb kill "$FileNameParam"]) || die "Something went wrong with the delete.\n"; # add the new file... system (qq[picdb add "$ReplacementFileName"]) || die "Something went wrong with the add.\n"; # update the db to match the info from the old file... $UpdateStrings="update pics set PicID=$PicID, pichitcount=$pichitcount, IsAvailable='$IsAvailable', DateAdded='$DateAdded', Location='$Location' where PicFileName='$ReplacementFileName'"; $UpdateHandle=$DB->prepare($UpdateString); $UpdateHandle->execute; } else { die "Invalid command specified!"; }