Annotation of foxridge-archiver/MPIWGStor.pm, revision 1.3

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

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