]> arthur.barton.de Git - netatalk.git/commitdiff
apple_dump: Extended Attributes AppleDouble support
authorHAT <hat@fa2.so-net.ne.jp>
Tue, 22 May 2012 12:25:57 +0000 (21:25 +0900)
committerHAT <hat@fa2.so-net.ne.jp>
Tue, 22 May 2012 12:25:57 +0000 (21:25 +0900)
BUG: *BSD is not supported yet

NEWS
contrib/shell_utils/apple_dump.in

diff --git a/NEWS b/NEWS
index 54b61dc3921981e64f14e1458196a290f2683897..5a47f408981acb9fd0ffae366c203e74906d4776 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,8 @@ Changes in 3.0 beta1
        "afp read locks" (default: no) which disables that the server
        applies UNIX byte range locks to regions of files in AFP read and
        write calls.
+* UPD: apple_dump: Extended Attributes AppleDouble support.
+       (*BSD is not supported yet)
 
 Changes in 3.0 alpha3
 =====================
@@ -14,8 +16,8 @@ Changes in 3.0 alpha3
        reservation locking primitives. Enabled by default, set global
        "solaris share reservations" option to false to disable it.
 * NEW: ad: ad set subcommand for changing Mac metadata on the server
-* UPD: unix charset is UTF8 by default
-       vol charset is same value as unix charset by default
+* UPD: unix charset is UTF8 by default.
+       vol charset is same value as unix charset by default.
 * UPD: .AppleDesktop/ are stored in $localstatedir/netatalk/CNID
        (default: /var/netatalk/CNID), databases found in AFP volumes are
        automatically moved
index 65eec7908e0b4ea2c61e5f52308a1c2b5f537a13..e7cc759adb828b9e31289f6c0a673c5ae8ed766f 100755 (executable)
@@ -2,7 +2,7 @@
 #
 # AppleSingle/AppleDouble dump
 #
-# (c) 2009-2010 by HAT <hat@fa2.so-net.ne.jp>
+# (c) 2009-2012 by HAT <hat@fa2.so-net.ne.jp>
 #
 #  This program is free software; you can redistribute it and/or modify
 #  it under the terms of the GNU General Public License as published by
 
 use File::Basename;
 use File::Spec;
+use File::Temp qw /tempfile/;
 use bigint; # require perl >= 5.8
 
+# check command for extended attributes -----------------------------------
+
+if (     0 == system("which getfattr > /dev/null 2>&1")) {
+    $eacommand = 1;
+} elsif (0 == system("which xattr > /dev/null 2>&1")) {
+    $eacommand = 2;
+} elsif (0 == system("which runat > /dev/null 2>&1")) {
+    $eacommand = 3;
+} else {
+    $eacommand = 0;
+}
+
+#printf ( "eacommand = %d\n", $eacommand );   # debug
+
 # parse command line -----------------------------------------------
 
+$eaoption = 0;
 $finderinfo = 0;              #  0: unknown   1: file   2: directory
 while ($arg = shift @ARGV)
 {
     if  ($arg =~ /^(-h|-help|--help)$/ ) {
         printf ("usage: %s [-a] FILE|DIR\n"           ,basename($0));
+        printf (" or:   %s -e FILE|DIR\n"             ,basename($0));
         printf (" or:   %s -f FILE\n"                 ,basename($0));
         printf (" or:   %s -d FILE\n"                 ,basename($0));
         printf (" or:   %s -h|-help|--help\n"         ,basename($0));
         printf (" or:   %s -v|-version|--version\n"   ,basename($0));
-        printf ("Dump AppleSingle/AppleDouble format file.\n");
+        printf ("Dump AppleSingle/AppleDouble format data.\n");
         printf ("\n");
-        printf ("  -a (default)     Dump a AppleSingle/AppleDouble file for FILE or DIR\n");
+        printf ("  -a (default)     Dump a AppleSingle/AppleDouble data for FILE or DIR\n");
         printf ("                   automatically.\n");
-        printf ("                   Extrapolate FinderInfo type from absolute path.\n");
         printf ("                   If FILE is not AppleSingle/AppleDouble format,\n");
-        printf ("                   look for '.AppleDouble/FILE' and '._FILE'.\n");
-        printf ("                   If DIR, look for 'DIR/.AppleDouble/.Parent' and '._DIR'.\n");
+        printf ("                   look for extended attribute, .AppleDouble/FILE and ._FILE.\n");
+        printf ("                   If DIR, look for extended attribute,\n");
+       printf ("                   DIR/.AppleDouble/.Parent and ._DIR.\n");
+        printf ("  -e               Dump extended attribute of FILE or DIR\n");
         printf ("  -f               Dump FILE. Assume FinderInfo to be FileInfo.\n");
         printf ("  -d               Dump FILE. Assume FinderInfo to be DirInfo.\n");
         printf ("  -h,-help,--help  Display this help and exit\n");
@@ -78,7 +96,7 @@ while ($arg = shift @ARGV)
         printf ("By default, %s examins whether file or directory,\n"   ,basename($0));
         printf ("a parent directory is .AppleDouble, filename is ._*, filename is .Parent,\n");
         printf ("and so on.\n");
-        printf ("If setting option -f or -d, %s assume FinderInfo and doesn't look for\n");
+        printf ("If setting option -e, -f or -d, %s assume FinderInfo and doesn't look for\n");
         printf ("another file.\n");
         exit 1;
     } elsif ($arg =~ /^(-v|-version|--version)$/ ) {
@@ -86,6 +104,13 @@ while ($arg = shift @ARGV)
         exit 1;
     } elsif ($arg eq "-a") {
         $finderinfo = 0;
+    } elsif ($arg eq "-e") {
+        if ($eacommand == 0) {
+           printf (STDERR "%s: unsupported option -e\n", basename($0));
+           printf (STDERR "because neither getfattr, xattr nor runat is not found.\n");
+           exit 1;
+       }
+       $eaoption = 1;
     } elsif ($arg eq "-f") {
         $finderinfo = 1;
     } elsif ($arg eq "-d") {
@@ -113,18 +138,33 @@ if (!( -e $afile)) {
 $abspath = File::Spec->rel2abs($afile);
 ($basename, $path, $ext) = fileparse($abspath);
 
-if ( $finderinfo != 0 ) {
+if ( $eaoption == 1 ) {
+    if ( -f $afile ) {
+       $finderinfo = 1;
+    } elsif ( -d $afile ) {
+       $finderinfo = 2;
+    } else {
+       printf (STDERR "unknown error: %s\n", $afile);
+       exit 1;
+    }
+    if ( 0 == checkea($afile) ) {
+       printf (STDERR "\"%s\"'s extended attribute is not found\n",  $afile);
+       exit 1;
+    }
+    $openfile = eaopenfile($afile);
+    $openmessage = "Dumping \"$afile\"'s extended attribute...\n";
+} elsif ( $finderinfo != 0 ) {
     ;
 } elsif ( -f $afile ) {
     if ( $basename eq ".Parent") {
        $finderinfo = 2;
     } elsif ( $path =~ /\/.AppleDouble\/$/ ) {
-       $finderinfo =1;
+        $finderinfo = 1;
     } elsif ( $basename =~ /^._/ ) {
        if ( -f $path.substr($basename, 2) ) {
-           $finderinfo =1;
+           $finderinfo = 1;
        } elsif ( -d $path.substr($basename, 2) ) {
-           $finderinfo =2;
+           $finderinfo = 2;
        }
     }
     if (!open(INFILE, "<$afile")) {
@@ -135,46 +175,72 @@ if ( $finderinfo != 0 ) {
     $val = unpack("N", $buf );
     close(INFILE);
     if ($val == 0x00051600 || $val == 0x00051607) {
-       ;
+        $openfile = $afile;
+       $openmessage = "Dumping \"$openfile\"...\n";
     } else {
-       printf ("\"%s\" is not AppleSingle/AppleDouble format.\n", $afile);
-       $finderinfo = 1;
-       $netatalkfile = $path.".AppleDouble/".$basename;
-       $osxfile = $path."._".$basename;
-
-       if (( -e $netatalkfile ) && !( -e $osxfile )) {
-           $afile = $netatalkfile;
-       } elsif (!( -e $netatalkfile ) && ( -e $osxfile )) {
-           $afile = $osxfile;
-       } elsif (( -e $netatalkfile ) && ( -e $osxfile )) {
-           printf ("\"%s\" found.\n", $netatalkfile);
-           printf ("\"%s\" found.\n", $osxfile);
-           printf ("Specify which of file.\n");
-           exit 1;
-       } else {
-           printf ("\"%s\" not found.\n", $netatalkfile);
-           printf ("\"%s\" not found.\n", $osxfile);
-           exit 1;
+        printf ("\"%s\" is not AppleSingle/AppleDouble format.\n", $afile);
+        $finderinfo = 1;
+        $adcount = 0;
+        $netatalkfile = $path.".AppleDouble/".$basename;
+        $osxfile = $path."._".$basename;
+
+        if ( 1 == checkea($afile) ) {
+           printf ("extended attribute of \"%s\" is found.\n", $afile);
+            $adcount++;
+           $openfile = eaopenfile($afile);
+           $openmessage = "Dumping \"$afile\"'s extended attribute...\n";
+       }
+       if ( -e $netatalkfile ) {
+            printf ("\"%s\" is found.\n", $netatalkfile);
+           $openfile = $netatalkfile;
+           $openmessage = "Dumping \"$openfile\"...\n";
+        }
+       if ( -e $osxfile ) {
+            printf ("\"%s\" is found.\n", $osxfile);
+            $adcount++;
+           $openfile = $osxfile;
+           $openmessage = "Dumping \"$openfile\"...\n";
+        }
+       if ( $adcount == 0 ) {
+            printf ("AppleSingle/AppleDouble data is not found.\n");
+            exit 1;
+       }
+       if ( $adcount != 1 ) {
+            printf ("Specify which.\n");
+            exit 1;
        }
     }
 } elsif ( -d $afile) {
     printf ("\"%s\" is a directory.\n", $afile);
-    $finderinfo =2;
+    $finderinfo = 2;
+    $adcount = 0;
     $netatalkfile = $path.$basename."/.AppleDouble/.Parent";
     $osxfile = $path."._".$basename;
 
-    if (( -e $netatalkfile ) && !( -e $osxfile )) {
-       $afile = $netatalkfile;
-    } elsif (!( -e $netatalkfile ) && ( -e $osxfile )) {
-       $afile = $osxfile;
-    } elsif (( -e $netatalkfile ) && ( -e $osxfile )) {
+    if ( 1 == checkea($afile) ) {
+       printf ("extended attribute of \"%s\" is found.\n", $afile);
+       $adcount++;
+       $openfile = eaopenfile($afile);
+       $openmessage = "Dumping \"$afile\"'s extended attribute...\n";
+    }
+    if ( -e $netatalkfile ) {
        printf ("\"%s\" found.\n", $netatalkfile);
+       $adcount++;
+       $openfile= $netatalkfile;
+       $openmessage = "Dumping \"$openfile\"...\n";
+    }
+    if ( -e $osxfile ) {
        printf ("\"%s\" found.\n", $osxfile);
-       printf ("Specify which of file.\n");
+       $adcount++;
+       $openfile = $osxfile;
+       $openmessage = "Dumping \"$openfile\"...\n";
+    }
+    if ( $adcount == 0 ) {
+       printf ("AppleSingle/AppleDouble data is not found.\n");
        exit 1;
-    } else {
-       printf ("\"%s\" not found.\n", $netatalkfile);
-       printf ("\"%s\" not found.\n", $osxfile);
+    }
+    if ( $adcount != 1 ) {
+       printf ("Specify which.\n");
        exit 1;
     }
 } else {
@@ -182,11 +248,14 @@ if ( $finderinfo != 0 ) {
     exit 1;
 }
 
-if (!open(INFILE, "<$afile")) {
+if (!open(INFILE, "<$openfile")) {
     printf (STDERR "cannot open %s\n",  $afile);
     exit 1;
 }
-printf ("%s:\n\n", $afile);
+
+printf ($openmessage);
+
+#Dump --------------------------------------------------------
 
 # Magic Number -----------------------------------------------
 
@@ -761,4 +830,61 @@ sub hexdump {
     print "\n";
 }
 
+sub checkea {
+    my ($file) = @_;
+
+    if ( $eacommand == 1 ) {
+       open(EALIST, "getfattr ".$file." |");
+       while(<EALIST>) {
+           if ( $_ eq "user.org.netatalk.Metadata\n" ) {
+               close (EALIST);
+               return 1;
+           }
+       }
+       close (EALIST);
+       return 0;
+    } elsif ( $eacommand == 2 ) {
+       open(EALIST, "attr -q -l ".$file." |");
+       while(<EALIST>) {
+           if ( $_ eq "org.netatalk.Metadata\n" ) {
+               close (EALIST);
+               return 1;
+           }
+       }
+       close (EALIST);
+       return 0;
+    } elsif ( $eacommand == 3 ) {
+       open(EALIST, "runat ".$file." ls -1 |");
+       while(<EALIST>) {
+           if ( $_ eq "org.netatalk.Metadata\n" ) {
+               close (EALIST);
+               return 1;
+           }
+       }
+       close (EALIST);
+       return 0;
+    } else {
+       return 0;
+    }
+}
+
+sub eaopenfile {
+    my ($file) = @_;
+
+    ($eatempfh, $eatempfile) = tempfile(UNLINK => 1);
+
+    if ( $eacommand == 1 ) {
+       system("getfattr --only-values -n user.org.netatalk.Metadata $file > $eatempfile");
+    } elsif ( $eacommand == 2 ) {
+       system("attr -q -g org.netatalk.Metadata $file > $eatempfile");
+    } elsif ( $eacommand == 3 ) {
+       system("runat $file cat org.netatalk.Metadata > $eatempfile");
+    } else {
+       return "";
+    }
+
+    close($eatempfh);
+    return $eatempfile;
+}
+
 #EOF