#!/usr/bin/perl # *************************************************************************** # SQLite Active (on-demand) Pseudo(user-space)(compressed)FileSystem SAPFS v.0.2a # skeldoy@gmail.com # This is a program for packing and unpacking files into an sqlite-database # while retaining the posibility for executing and displaying contents of # the stored files. Usage is explained and if you "ls" after packing a # directory you will get the picture. # *************************************************************************** # I TAKE NO RESPONSIBILITY FOR THIS CODE AND THE MANY BAD THINGS THAT WILL # HAPPEN TO PEOPLE WHO RUN THIS WITHOUT TAKING RESPONSIBILITY FOR THEIR # OWN ACTIONS! Distribute freely and be nice! Stealing code should entail a # nice email to me ;) - Sverre Eldøy (skeldoy@gmail.com) # *************************************************************************** # You will need lzma, the DBD::SQLite and the Compress::LZMA::External (perlmod) # This is the start of main $|=0; $appName = "SAPFS"; use DBI qw(:sql_types); use Compress::LZMA::External qw(compress decompress); # This will set up the current directory with an empty database (if none exists) &dropSetup(); unless (-e "./Library") { $makeIt = `sqlite3 Library /dev/null`; print $makeIt; } my $dbh = DBI->connect("dbi:SQLite:Library"); # This is the code for packing the archive. if ($ARGV[0] =~ "DL-pack") { @files = <*>; foreach $file (@files) { if ($file =~ "$appName") { next; } # we do not pack ourself if ($file =~ "Library") { next; } # or the pack if ($file =~ "dbSetup") {next;} # or the temporary dbsetup my $blobTemp = `cat $file`; my $blob = compress($blobTemp); ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size, $atime, $mtime, $ctime, $blksize, $blocks ) = stat($file); if ( -x $file ) { $executive = 1;} else {$executive = 0; } my $sth = $dbh->prepare("INSERT INTO dynLibrary VALUES (NULL, \"$file\",?,$executive, $mode, 1)"); # for now assume architecture 1 (Intel 386 32-ELF) $sth->bind_param(1, $blob, SQL_BLOB); $sth->execute(); print "Added $file\n"; $delete = `rm $file 2>/dev/null`; $mkSymLink = `ln -s $appName $file`; } print "Finished packing\n"; } # This code is run when we want to unpack the archive. Archive will be deleted. elsif ($ARGV[0] =~ "DL-ext") { for ($n=1;$n<(&allData()+1);$n++) { $fileQuery = join(" ", "SELECT filename from dynLibrary where id=$n;"); print "Extracting $n "; $sth = $dbh->prepare("$fileQuery"); $sth->execute; my $row = $sth->fetch; $filename = $row->[0]; print $filename; print "\n"; $blobQuery = "SELECT file from dynLibrary where id=$n"; $sth=$dbh->prepare("$blobQuery"); $sth->execute; my $brow = $sth->fetch; $fileTemp = $brow->[0]; $file=decompress($fileTemp); $delSymLinks = `rm $filename 2>/dev/null`; open (OUT, ">$filename"); print OUT $file; close OUT; $XmodeQuery = "SELECT executable from dynLibrary where id=$n"; $doXMode = $dbh->prepare("$XmodeQuery"); $doXMode->execute; $modXRes = $doXMode->fetch; $executive = $modXRes->[0]; if ($executive) { $chmodIt = `chmod +x $filename`; } } $killLib = `rm Library 1>/dev/null 2>/dev/null`; } # print som help elsif (($0 =~ "$appName") | ($ARGV[0]=~"-help")) { print "SQLite Active FileSystem SAFS v0.0.1A by skeldoy\@gmail.com\n"; print "Usage:\n$0 DL-pack (for packing the files in your current directory)\n"; print "$0 DL-ext (for extracting from the package into current directory)\n"; print "./NAMEofFILEinPackage will either execute or print that file.\n"; } # This following code is called whenever we execute or open a file in the package. else { @call = split("/",$0); $called=$call[$#call]; $fileQuery = join(" ", "SELECT file from dynLibrary where filename=\"$called\";"); $sth = $dbh->prepare("$fileQuery"); $sth->execute; my $row = $sth->fetch; $fileTemp = $row->[0]; $file = decompress($fileTemp); $XmodeQuery = "SELECT executable from dynLibrary where filename=\"$called\""; $doXMode = $dbh->prepare("$XmodeQuery"); $doXMode->execute; $modXRes = $doXMode->fetch; $executive = $modXRes->[0]; if ($executive) { $killedIt = `rm $called`; open (OUT, ">$called"); print OUT $file; close $file; $chmodIT = `chmod +x $called`; #print `./$called`; print `cp $called backUp`; print `./backUp`; $slett=`rm $called 1>/dev/null 2>/dev/null;rm backUp 1>/dev/null 2>/dev/null`; $lnagain = `ln -s $appName $called`; } # in case it is not an executable we just print it (for now) else { @ProcessExtension = split(".",$called); $extension = $ProcessExtension[1]; if ($extension =~ "aiff") { `cat $file | play -n`; } elsif ($extension =~ "mp3") { `cat $file | play -n`; } elsif ($extension =~ "m4u") { `cat $file | play -n`; } elsif ($extension =~ "ogg") { `cat $file | play -n`; } elsif ($extension =~ "flac") { `cat $file | play -n`; } elsif ($extension =~ "snd") { `cat $file | play -n`; } elsif ($extension =~ "wav") { `cat $file | play -n`; } else {print $file; } } # additional handling of other formats will # with time be implemented } #This is the last thing that happens (in "main") $killSetup = `rm dbSetup 1>/dev/null 2>/dev/null`; sub allData() { $countQuery = "SELECT COUNT(id) from dynLibrary;"; $sth = $dbh->prepare("$countQuery"); $sth->execute; @count = $sth->fetch; return $count[0][0]; } # This is the configuration for the database. I put it here to contain it (cleanliness). sub dropSetup() { open (DB, ">dbSetup"); print DB ".echo on\n"; print DB ".mode col\n"; print DB ".headers on\n"; print DB ".nullvalue NULL\n"; print DB "CREATE TABLE dynLibrary (id INTEGER PRIMARY KEY,\n"; print DB "\t\t\tfileName text NOT NULL COLLATE NOCASE, \n"; print DB "\t\t\tfile blob, executable boolean, filemode int, archtype int ,UNIQUE (id,fileName));\n"; close DB; }