File:  [Repository] / foxridge-archiver / MPIWGStor.pm
Revision 1.9: download - view: text, annotated - select for diffs - revision graph
Wed Mar 21 14:22:27 2007 UTC (17 years, 3 months ago) by casties
Branches: MAIN
CVS tags: HEAD
added silly adobe files to junk file list

    1: 
    2: #
    3: # Library with definitions and common routines for MPIWG storage system
    4: # scripts
    5: #
    6: 
    7: package MPIWGStor;
    8: 
    9: use strict;
   10: use vars qw(@ISA @EXPORT $VERSION
   11: 	    $debug %junk_files %index_files $index_file_perm $archived_index_file_perm 
   12: 	    $file_perm);
   13: use Exporter;
   14: 
   15: $VERSION = 0.6.3; #  ROC 6.3.2007
   16: 
   17: @ISA = qw(Exporter);
   18: 
   19: @EXPORT = qw($debug %junk_files %index_files $index_file_perm $archived_index_file_perm 
   20: 	     $file_perm
   21: 	     &parseargs &logger &stime  &s2stime &ymd_date &split_file_path &sstrip 
   22: 	     &valid_file_name &valid_dir_name &park_file &unpark_file
   23:              &read_xml &write_xml &add_text_element &create_element_path &create_text_path);
   24: 
   25: # debug level
   26: $debug = 0;
   27: 
   28: # junk files
   29: %junk_files = (
   30:     # netatalk stuff
   31:     '.AppleDB' => '.AppleDB',
   32:     '.AppleDesktop' => '.AppleDesktop',
   33:     '.AppleDouble' => '.AppleDouble',
   34:     '.FBCIndex' => '.FBCIndex',
   35:     '.FBCLockFolder' => '.FBCLockFolder',
   36:     ':2eTemporaryItems' => ':2eTemporaryItems',
   37:     ':2eDS_Store' => ':2eDS_Store',
   38:     ':2eBridgeSort' => ':2eBridgeSort',
   39:     # standard appleshare stuff
   40:     '.DS_Store' => '.DS_Store',
   41:     '.TemporaryItems' => '.TemporaryItems',
   42:     'Network Trash Folder' => 'Network Trash Folder',
   43:     'TheVolumeSettingsFolder' => 'TheVolumeSettingsFolder',
   44:     # old appleshare software turds
   45:     '.HSResource' => '.HSResource',
   46:     '.HSancillary' => '.HSancillary',
   47:     '.HSicon' => '.HSicon'
   48:     );
   49: 
   50: # filenames to not delete (but archive)
   51: %index_files = ( 
   52: 		     'index.meta' => 'index.meta',
   53: 		     'index.meta.old' => 'index.meta.old'
   54: 		     );
   55: 
   56: # default permissions for normal index files (rw-rw-r--)
   57: $index_file_perm = 0664;
   58: # default permissions for archived index files (rw-r--r--)
   59: $archived_index_file_perm = 0644;
   60: # default permissions for other files (rw-rw-r--)
   61: $file_perm = 0664;
   62: 
   63: 
   64: #
   65: # $param_hash = parseargs;
   66: #
   67: # reads @ARGV and returns a hash with all options like "-option=value"
   68: # and the last part of the string as "path"
   69: #
   70: sub parseargs {
   71:     my %opts;
   72:     foreach my $s (@ARGV) {
   73: 	if ($s =~ /^-([^=]+)=*(.*)$/) {
   74: 	    $opts{$1} = ($2) ? $2 : $1;
   75: 	} else {
   76: 	    $opts{'path'} = $s;
   77: 	}
   78:     }
   79:     return \%opts;
   80: }
   81: 
   82: 
   83: #
   84: # logger($level, $message)
   85: #
   86: # logs the $message (mostly to stdout)
   87: #
   88: sub logger {
   89:     my ($level, $message) = @_;
   90:     if ($debug || ($level ne "DEBUG")) {
   91: 	print "$level: $message\n";
   92:     }
   93: }
   94: 
   95: #
   96: # $stime = stime($utime)
   97: #
   98: # format utime (seconds since epoch) into string 
   99: # representation: "YYYY/MM/DD HH:MM:SS"
  100: #
  101: sub stime {
  102:     my ($utime) = @_;
  103:     my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
  104: 	localtime($utime);
  105:     my $yy = $year + 1900;
  106:     my $mm = $mon + 1;
  107:     my $stime = sprintf("%d/%02d/%02d %02d:%02d:%02d", 
  108: 			$yy, $mm, $mday, $hour, $min, $sec);
  109:     return $stime;
  110: }
  111: 
  112: #
  113: # $stime = s2stime($stime2)
  114: #
  115: # format db-like time (2003-09-19 12:43:32+02) into string 
  116: # representation: "YYYY/MM/DD HH:MM:SS"
  117: #
  118: sub s2stime {
  119:     my ($s2time) = @_;
  120:     my $stime = "";
  121:     if ($s2time =~ /(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)/) {
  122: 	my ($year,$mon,$mday,$hour,$min,$sec) = ($1, $2, $3, $4, $5, $6);
  123: 	$stime = sprintf("%d/%02d/%02d %02d:%02d:%02d", 
  124: 			$year, $mon, $mday, $hour, $min, $sec);
  125:     }
  126:     return $stime;
  127: }
  128: 
  129: #
  130: # $date = ymd_date($olddate)
  131: #
  132: # converts a date string in mm/dd/yy format to yyyy/mm/dd format
  133: #
  134: sub ymd_date {
  135:     my ($mdy) = @_;
  136:     my $ydm;
  137:     if ($mdy =~ /(\d+)\/(\d+)\/(\d+)/) {
  138: 	my $m = $1;
  139: 	my $d = $2;
  140: 	my $y = $3;
  141: 	# extend yy to yyyy
  142: 	$y = ($y < 70) ? (2000 + $y) : (($y < 100) ? ($y + 1900) : $y);
  143: 	$ydm = sprintf "%d/%02d/%02d", $y, $m, $d;
  144:     }
  145:     return $ydm;
  146: }
  147: 
  148: #
  149: # ($name, $path) = split_file_path($fn)
  150: #
  151: # splits the file path $fn into
  152: # file name (the last path element) and path
  153: #
  154: sub split_file_path {
  155:     my ($fn, $nodot) = @_;
  156: 
  157:     if ($fn =~ /^(.*)\/([^\/]+)$/) {
  158:         return ($2, $1);
  159:     } 
  160:     # only file name
  161:     if ($nodot) {
  162: 	return ($fn, '');
  163:     } else {
  164: 	return ($fn, '.');
  165:     }
  166: }
  167: 
  168: 
  169: #
  170: # $name = sstrip($name, $slash)
  171: #
  172: # strips leading and trailing whitespace from $name
  173: # replaces double slashes with single ones with $slash.
  174: #
  175: sub sstrip {
  176:     my ($name, $slash) = @_;
  177:     
  178:     if ($name =~ /^\s*(.*?)\s*$/) {
  179: 	$name = $1;
  180:     }
  181:     if ($slash) {
  182: 	# trim multiple slashes
  183: 	$name =~ s/\/+/\//g;
  184:     }
  185:     return $name;
  186: }
  187: 
  188: 
  189: #
  190: # $valid = valid_file_name($name)
  191: #
  192: # checks if $name is a valid file name
  193: #
  194: sub valid_file_name {
  195:     return valid_name($_[0], 0);
  196: }
  197: 
  198: 
  199: #
  200: # $valid = valid_dir_name($name)
  201: #
  202: # checks if $name is a valid directory name
  203: #
  204: sub valid_dir_name {
  205:     return valid_name($_[0], 1);
  206: }
  207: 
  208: 
  209: #
  210: # $valid = valid_name($name, $mode)
  211: #
  212: # checks if $name is a valid file ($mode=0) or directory name (mode=1)
  213: #
  214: sub valid_name {
  215:     my ($name, $mode) = @_;
  216: 
  217:     # whitespace?
  218:     if ($name =~ /\s+/) {
  219: 	return 0;
  220:     }
  221:     # invalid characters
  222:     if ($name !~ /^[-\w.\/]+$/) {
  223: 	return 0;
  224:     }
  225:     # files have extension
  226:     if ($mode == 0) {
  227: 	if ($name !~ /\.[-\w]+$/) {
  228: 	    return 0;
  229: 	}
  230:     }
  231:     return 1;
  232: }
  233: 
  234: 
  235: #
  236: # $newfilename = park_file($filename)
  237: #
  238: # parks a file under a new name (*.bak)
  239: #
  240: sub park_file {
  241:     my ($filename) = @_;
  242:     my $newfn = "";
  243:     if (-f $filename) {
  244: 	$newfn = "$filename.bak";
  245: 	if (! rename $filename, $newfn) {
  246: 	    logger("ABORT", "unable to rename file $filename!");
  247: 	    exit 1;
  248: 	}
  249:     }
  250:     return $newfn;
  251: }
  252:     
  253: #
  254: # $filename = unpark_file($filename)
  255: #
  256: # unparks a file
  257: #
  258: sub unpark_file {
  259:     my ($filename) = @_;
  260:     my $newfn = "$filename.bak";
  261:     if (-f $newfn) {
  262: 	if (! rename $newfn, $filename) {
  263: 	    logger("ABORT", "unable to rename file $newfn!");
  264: 	    exit 1;
  265: 	}
  266: 	return $filename;
  267:     }
  268:     return "";
  269: }
  270:     
  271: 
  272: 
  273: #
  274: # ($document, $rootnode) = read_xml($file)
  275: #
  276: # reads xml meta file $file
  277: # returns root node element
  278: #
  279: sub read_xml {
  280:     my ($file) = @_;
  281:     my $document;
  282: 
  283:     my $parser = XML::LibXML->new();
  284:     if (! $parser) {
  285: 	logger("ABORT", "unable to create parser for metadata index file!!");
  286: 	exit 1;
  287:     }
  288: 
  289:     logger("DEBUG", "index file: $file");
  290:     eval { $document = $parser->parse_file($file) };
  291:     # catch parsing errors
  292:     if ($@) {
  293: 	logger("ABORT", "XML syntax error in file $file!!");
  294: 	exit 1;
  295:     }
  296:     my $rootnode = $document->documentElement;
  297:     logger("DEBUG", "root element: \'" . $rootnode->nodeName . "\'");
  298: 
  299:     return ($document, $rootnode);
  300: }
  301: 
  302: 
  303: #
  304: # write_xml($document, $file)
  305: #
  306: # saves the XML tree of $document to the file $file
  307: #
  308: sub write_xml {
  309:     my ($document, $filename) = @_;
  310:     # keep backup copy
  311:     if (-f $filename) {
  312: 	if (! rename $filename, "$filename.old") {
  313: 	    logger("ABORT", "unable to change file $filename!");
  314: 	    exit 1;
  315: 	}
  316:     }
  317:     # write new file
  318:     my ($fn, $dir) = split_file_path($filename);
  319:     if (-d $dir && $document->toFile($filename)) {
  320: 	logger("INFO", "written new file $filename");
  321: 	chmod $index_file_perm, $filename;
  322:     } else {
  323: 	logger("ABORT", "unable to write file $filename!");
  324: 	exit 1;
  325:     }
  326: }
  327: 
  328: #
  329: # $elem = add_text_element($node, $name, $value, $namespace)
  330: #
  331: # creates an XML element with the name $name and the text content
  332: # $value attached to the node $node and returns it.
  333: #
  334: sub add_text_element {
  335:     my ($node, $name, $value, $namespace) = @_;
  336: 
  337:     my $doc = $node->ownerDocument;
  338:     my $text = $doc->createTextNode($value);
  339:     my $newnode = $node->addNewChild($namespace, $name);
  340:     $newnode->addChild($text);
  341: 
  342:     return $newnode;
  343: }
  344: 
  345: #
  346: # $elem = create_element_path($path, $root, $namespace)
  347: #
  348: # creates and returns a DOM element at the given path from the 
  349: # given root. path is e.g. meta/bib@type=book. elements are separated
  350: # by /, an additional attribute can be specified after the @.
  351: #
  352: sub create_element_path {
  353:     my ($path, $root, $namespace) = @_;
  354:     my $attribute = "";
  355:     # get attribute
  356:     if ($path =~ /^(.+)@(.+)$/) {
  357: 	$attribute = $2;
  358: 	$path = $1;
  359:     }
  360:     my $point = $root;
  361:     for my $p (split /\//, $path) {
  362: 	# check if the next path element exists
  363: 	my $n = ($point->findnodes($p))[0];
  364: 	if ($n) {
  365: 	    $point = $n;
  366: 	} else {
  367: 	    # create if it doesn't exist
  368: 	    $point = $point->addNewChild($namespace, $p);
  369: 	}
  370:     }
  371:     # add the attribute
  372:     if ($attribute) {
  373: 	my $dom = $root->getOwner();
  374: 	my ($attkey, $attval) = split /=/, $attribute; #/ silly fontlock...
  375: 	$point->addChild($dom->createAttributeNS($namespace, $attkey, $attval));
  376:     }
  377:     return $point;
  378: }
  379: 
  380: #
  381: # $elem = create_text_path($path, $text, $root, $namespace)
  382: #
  383: # creates and returns a DOM text element with the given content at the
  384: # given path from the given root.
  385: #
  386: sub create_text_path {
  387:     my ($path, $text, $root, $namespace) = @_;
  388:     my $elem = create_element_path($path, $root, $namespace)->appendTextNode($text);
  389:     return $elem;
  390: }
  391: 
  392: 
  393: 
  394: # module init
  395: return 1;

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>