]> arthur.barton.de Git - netatalk.git/blob - contrib/shell_utils/cleanappledouble.pl
small adaptations for CVS tree
[netatalk.git] / contrib / shell_utils / cleanappledouble.pl
1 #! /usr/bin/perl
2 #
3 # cleanappledouble.pl
4 # Copyright (C) 2001 Heath Kehoe <hakehoe@avalon.net>
5 #
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2
9 # of the License, or (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19 #
20
21 require 5;
22 use Getopt::Std;
23
24 sub usage {
25     print STDERR <<EOF;
26 Usage: $0 [-r] [-v] directory [directory ...]
27
28 Scans each directory and:
29  1) removes orphaned .AppleDouble files (from <directory>/.AppleDouble)
30  2) fixes permissions on .AppleDouble files to match corresponding data file (minus x bits)
31  3) fixes owner/group of .AppleDouble files to match corresponding data file (root only)
32
33 Options:
34   -r   Recursively check all subdirectories of each directory
35   -R   Like -r but follows symbolic links to directories (warning: no loop-checking is done)
36   -p   Preview: no deletions or changes are actually made
37   -v   Verbose
38 EOF
39     exit 1;
40 }
41
42 $isroot = ($> == 0);
43
44 sub S_ISDIR {
45     my($mode) = @_;
46     return (($mode & 0170000) == 0040000);
47 }
48 sub S_ISREG {
49     my($mode) = @_;
50     return (($mode & 0170000) == 0100000);
51 }
52 sub S_ISLNK {
53     my($mode) = @_;
54     return (($mode & 0170000) == 0120000);
55 }
56
57
58 sub do_dir {
59     my($dir) = @_;
60     my($f, $havead, @dirlist, $mode, $uid, $gid, $fn);
61     my(%dm, %du, %dg);
62
63     print STDERR "Scanning $dir ...\n" if($opt_v);
64
65     $havead = -d "$dir/.AppleDouble";
66
67     # there's nothing more to do if we're not recursive and there's no .AppleDouble
68     return if(!$havead && !$opt_r);
69
70     opendir DIR, $dir   or do {
71                 warn "Can't opendir $dir: $!\n";
72                 return;
73     };
74     while(defined($f = readdir DIR)) {
75         next if($f eq ".");
76         next if($f eq "..");
77         next if($f eq ".AppleDouble");
78         next if($f eq ".AppleDesktop");
79
80         (undef, undef, $mode, undef, $uid, $gid) = lstat "$dir/$f";
81         next if(!defined($mode));
82
83         if(S_ISLNK($mode)) {
84             (undef, undef, $mode, undef, $uid, $gid) = stat "$dir/$f";
85             next if(!defined($mode));
86             next if(S_ISDIR($mode) && !$opt_R);
87         } 
88         if(S_ISDIR($mode)) {
89             push @dirlist, $f if($opt_r);
90         } elsif(S_ISREG($mode)) {
91             if($havead) {
92                 $dm{$f} = $mode & 0666;
93                 $du{$f} = $uid;
94                 $dg{$f} = $gid;
95             }
96         } else {
97             warn "Ignoring special file: $dir/$f\n";
98         }
99     }
100     closedir DIR;
101
102     if($havead) {
103         if(opendir DIR, "$dir/.AppleDouble") {
104             while(defined($f = readdir DIR)) {
105                 next if($f eq ".");
106                 next if($f eq "..");
107                 next if($f eq ".Parent");
108
109                 $fn = "$dir/.AppleDouble/$f";
110                 (undef, undef, $mode, undef, $uid, $gid) = stat $fn;
111                 next if(!defined($mode));
112
113                 if(S_ISDIR($mode)) {
114                     warn "Found subdirectory $f in $dir/.AppleDouble\n";
115                     next;
116                 }
117                 unless(exists $dm{$f}) {
118                     print STDERR "Deleting $fn ...\n" if($opt_v);
119                     if($opt_p) {
120                         print "rm '$fn'\n";
121                     } else {
122                         unlink "$fn" or warn "Can't unlink $fn: $!\n";
123                     }
124                     next;
125                 }
126                 $mode = $mode & 07777;
127                 if($mode != $dm{$f}) {
128                     printf STDERR "Changing permissions from %o to %o on $fn\n", $mode, $dm{$f} if($opt_v);
129                     if($opt_p) {
130                         printf "chmod %o '$fn'\n", $dm{$f};
131                     } else {
132                         chmod $dm{$f}, $fn or warn "Can't chmod $fn: $!\n";
133                     }
134                 }
135                 if($isroot && ($uid != $du{$f} || $gid != $dg{$f})) {
136                     print STDERR "Changing owner from $uid:$gid to $du{$f}:$dg{$f} on $fn\n" if($opt_v);
137                     if($opt_p) {
138                         print "chown $du{$f}:$dg{$f} '$fn'\n";
139                     } else {
140                         chown $du{$f}, $dg{$f}, $fn or warn "Can't chown $fn: $!\n";
141                     }
142                 }
143             }
144             closedir DIR;
145         } else {
146             warn "Can't opendir $dir/.AppleDouble: $!\n";
147         }
148     }
149
150     if($opt_r) {
151         foreach $f ( @dirlist ) {
152             do_dir("$dir/$f");
153         }
154     }
155 }
156
157 usage unless(getopts 'prRv');
158 usage if(@ARGV == 0);
159
160 if($opt_R) {
161     $opt_r = 1;
162 }
163
164 foreach $d ( @ARGV ) {
165     do_dir $d;
166 }
167