[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-look
Subject:    Extended attributes, an implementation
From:       Thomas Zander <zander () xs4all ! nl>
Date:       2000-11-09 22:09:25
[Download RAW message or body]

Hi, I had some ideas on how to implement this extended attributes stuff 
and rather then write extended documents I wrote an example implementation.

It in perl, and probably has bugs, but it works.

There are 2 programs, get and put.
Try the following commands:

    touch testfile
    ./put testfile/mimetype value=\"text/plain\"
    ./get testfile/mimetype

and

    touch testfile
    ./put testfile/application name=\"kview\"
    ./put testfile/history/save "date=\"`date`\""
    ./get testfile
    ./get testfile/history
    ./get testfile/save


I chose the interface because I think it is the most modular approuch to fit
nicely with the XML storage. Hope you agree.
The meta data is stored in a directory called .meta in the current dir with the
same protections as the current dir. This way the the unix filesystem will take
care of all protections. In principle the metafile should also get the protections
of the original file. That is quite simple to implement.

The reason I have not choosen any other way is because this is the only method 
that users can use without need of superuser rights. All other solutions need
chowns or dir creation in prefiledged dirs.

The second reason; this feels better because it will work over network shares.

What do you think?
-- 
Thomas Zander                                            zander@earthling.net
The only thing worse than failure is the fear of trying something new

["get" (text/plain)]

#!/usr/bin/perl

$fullpath = $ARGV[0];
if($fullpath eq "") {
    print "Usage: get filename/<tag>\n";
    exit;
}
if($fullpath=~/^\//) {
    $filename = ""; 
} else  {
    $filename = "."; 
}
reset @variable;

@path=split(/\//, $fullpath);
foreach $segment (@path) {
    if(!defined (@variable) && lstat("$filename/$segment")) { $filename .= "/" .$segment; next; }
    push @variable, $segment;
}
if($filename eq "." || $filename eq "/")  {
    print "File does not exist.. bailing out\n";
    exit;
}
$metafile = getMeta($filename);
if($metafile eq "") { print "No EA found for file\n"; exit();}

$node = getNode($metafile,@variable);

print "$node\n";
exit;

sub getMeta() {
    my $filename = @_[0];
    @fullname=split(/\//, $filename);
    $directory=$fullname[0];
    for($i=1; $i < $#fullname ; $i++)  {
        $directory .= "/" .$fullname[$i];
    }
    $filename=$fullname[$i];
    my $prefix = ".meta";
    opendir(DIR, "$directory/$prefix");
    $direntry = readdir(DIR);
    while (defined($direntry)) {
        open(FILE, "$prefix/$user/$direntry");
        $xmlheader=<FILE>;
        $line=<FILE>;
        if($line=~m/filename *=\"(.*?)\"/i && $1 eq $filename) { 
            closedir(DIR);
            return "$prefix/$user/$direntry";
         }
        $direntry = readdir(DIR);
    }
    closedir(DIR);
    return "";
}

sub getNode() {
    my $filename = @_[0];
    my $result="";

    my $level=0, $foundAtLevel=-1, $nodecount=1, $levelfound=0;
    if($#_==0) { $foundAtLevel=1; }
    print "$xmlheader";
    open (FILE, $filename);
    <FILE>;
    THEFILE: while((<FILE>)) {
        chomp ($_);
        $first=1;
        foreach $var (split (/\</, $_)) {
            if($first==1) { 
                if($foundAtLevel>0) {
                    $result="$result$var\n";
                }
                $first=0; 
                if($var=~m/\/\>/) { $level--; }
                next;
            }
            if($var=~m/^ *\//) { $level--; } else { $level ++; }
            if($level < $levelfound) { $levelfound=0; $nodecount=1;}
            if($foundAtLevel < 0 && $var=~m/^ *$_[$nodecount]/i) { $nodecount++; $levelfound=$level;}
            if($foundAtLevel < 0 && $nodecount== $#_+1) { $foundAtLevel=$level; }
            if($foundAtLevel > 0) {
                $prefix="  "x($level-$foundAtLevel);
                $result="$result$prefix<$var";
            }
            if($var=~m/\/\>/) { $level--; }
            if($level < $foundAtLevel) { last THEFILE; }
        }
    }
    close (FILE);
    return $result;
}

["put" (text/plain)]

#!/usr/bin/perl

$prefix = ".meta";
$fullpath = $ARGV[0];
$text = $ARGV[1];
if($text eq "") {
    print "Usage: put filename/<tag> text\n  creates a new tag with between the < and \
/> the contents of 'text'\n";  exit;
}
if($fullpath=~/^\//) {
    $filename = ""; 
} else  {
    $filename = "."; 
}
reset @variable;

@path=split(/\//, $fullpath);
foreach $segment (@path) {
    if(!defined (@variable) && lstat("$filename/$segment")) { $filename .= "/" \
.$segment; next; }  push @variable, $segment;
}

if($filename eq "." || $filename eq "/")  {
    print "File does not exist.. bailing out\n";
    exit;
}

$metafile = getMeta($filename);
$metafile=createMetaFile($metafile, $filename, @variable);

exit;



sub getMeta() {
    my $filename = @_[0];
    @fullname=split(/\//, $filename);
    $directory=$fullname[0];
    for($i=1; $i < $#fullname ; $i++)  {
        $directory .= "/" .$fullname[$i];
    }
    $filename=$fullname[$i];
    opendir(DIR, "$directory/$prefix");
    $direntry = readdir(DIR);
    while (defined($direntry)) {
        open(FILE, "$prefix/$user/$direntry");
        $xmlheader=<FILE>;
        $line=<FILE>;
        if($line=~m/filename *=\"(.*?)\"/i && $1 eq $filename) {
            closedir(DIR);
            return "$prefix/$user/$direntry";
         }
        $direntry = readdir(DIR);
    }
    closedir(DIR);
    return "";
} 

sub createMetaFile()  {
    my $metafilename = @_[0];
    my $filename = @_[1];
    @fullname=split(/\//, $filename);
    $directory=$fullname[0];
    for($i=1; $i < $#fullname ; $i++)  {
        $directory .= "/" .$fullname[$i];
    }
    $filename =$fullname[$i];
    if(! lstat("$directory/$prefix")) {
        mkdir("$directory/$prefix", (stat($directory))[2] & 07777);
    }
    if($metafilename eq "") {
        $metafilename = $prefix. "/". join '', ('.', '/', 0..9, 'A'..'Z', \
                'a'..'z')[rand 64, rand 64, rand 64, rand 64, rand 64, rand 64, rand \
                64];
        $contents="<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<meta \
filename=\"$filename\">\n";  } else {
        open (FILE, "$directory/$metafilename");
        foreach $line (<FILE>) {
            if($line=~m/\/ *meta/g) {last; }
            $contents.=$line;
        }
        close (FILE);
    }
    unlink "$directory/$metafilename";
    open (FILE, ">$directory/$metafilename");
    print FILE $contents;
    for ($i=2; $i  <= $#_; $i++) {
        print FILE "  <$_[$i] ";
        if($i == $#_) { 
            print FILE "$text />\n"; 
        } else {
            print FILE ">\n";
        }
    }
    for ($i=$#_-1; $i >=2;  $i--) {
        print FILE "  </ $_[$i]>\n";
    }
    print FILE "</meta>\n";
    close (FILE);
    return "$directory/$prefix/$metafilename";
}



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic