2 # real Perl code begins here
4 # Adapted from Apple's uninstall-devtools.pl (Version 7 for Xcode Tools 1.2)
6 # BSD License: c.f. <http://www.opensource.org/licenses/bsd-license>
13 use vars qw ($do_nothing $print_donothing_removals $receipts_dir $verbose $noisy_warnings);
14 use vars qw ($suppress_spin $spin_counter $spin_state $spin_slower_downer);
15 use vars qw (%exception_list $gen_dirs @gen_files @rmfiles @rmdirs @rmpkg);
17 #----------------------------------------------------------------------------------------
20 $print_donothing_removals = 1;
24 # One of rm -rf in this script uses $receipts_dir -- change with care.
25 $receipts_dir = "/Library/Receipts";
33 "/var/db/openafs/etc/cacheinfo",
34 "/var/db/openafs/etc/ThisCell",
35 "/var/db/openafs/etc/config/afsd.options",
36 "/var/db/openafs/etc/config/afs.conf",
37 "/var/db/openafs/etc/CellServDB.save",
38 "/var/db/openafs/etc/CellServDB.master.last",
39 "/var/db/openafs/etc/CellServDB",
40 "/var/db/openafs/etc/config/settings.plist",
43 #----------------------------------------------------------------------------------------
49 # 0: dir of packages to remove
50 # 1: flag indicating whether to keep package receipts
51 # 2: flag indicating whether to supress spin indicator
55 @ARGV = ("$Bin/..", 0, 0);
57 $suppress_spin = defined ($ARGV[2]) && $ARGV[2];
64 print "Uninstalling OpenAFS package:\n\n";
66 remove_generated_files ();
67 remove_main_packages ();
68 remove_generated_directories ();
70 if ($do_nothing == 0) {
71 # When osascript runs some shell commands, newlines are printed as just
72 # \r instead of \n for some reason, so anything output kinda overwrites
73 # earlier output. The final 'tr' in the pipeline here turns them back
74 # into \n newlines. pkgutil --forget at least will print output like
75 # "Forgot package 'foo'".
76 my $rmcmd = "osascript -e 'do shell script \"/bin/rm -f @rmfiles; " .
77 "/bin/rmdir @rmdirs; echo @rmpkg | xargs -n 1 " .
78 "/usr/sbin/pkgutil --forget\" with administrator " .
79 "privileges' | tr '\\r' '\\n'";
81 my $retcode = $? >> 8;
83 print_warning ("Warning: There may have been a problem uninstalling\n");
88 print "\nFinished uninstalling.\n";
91 sub remove_main_packages {
92 my @pkglist = ("org.openafs.OpenAFS-debug.pkg",
93 "org.openafs.OpenAFS.pkg",
99 my $pkg = $pkgname.".pkg";
102 if (not open(INFO, '-|', "/usr/sbin/pkgutil --pkg-info $pkg | " .
103 "grep ^volume: | cut -d' ' -f2-")) {
104 print_warning("Warning: Could not get pkg info for $pkg " .
105 "(maybe it's not installed?)\n");
110 if ((not close(INFO)) or (!defined($bomroot))) {
111 print_warning("Warning: Could not get pkg info for $pkg " .
112 "(maybe it's not installed?)\n");
119 print "\nFound pkg install root $bomroot for $pkg\n";
123 if (not open (LSBOM, '-|', "/usr/sbin/pkgutil --only-files --files $pkg")) {
124 print_warning("Warning: Error running pkgutil --only-files --files $pkg\n");
131 next if (!defined ($1) || $1 eq "");
132 my $filename = $bomroot . $1;
134 remove_a_file ($filename);
140 if (not open (LSBOM, '-|', "/usr/sbin/pkgutil --only-dirs --files $pkg")) {
141 print_warning("Warning: Error running pkgutil --only-dirs --files $pkg\n");
148 next if (!defined ($1) || $1 eq "");
149 my $directory = $bomroot . $1;
151 $rooth = add_directory_to_tree ($directory, $rooth);
153 if ($noisy_warnings) {
154 print_warning ("Warning: \"$directory\" listed in BOM " .
155 "but not present on system.\n");
162 remove_empty_directories ($rooth, $bomroot);
164 remove_package_receipts($pkg) if (!defined ($ARGV[1]) || !$ARGV[1]);
168 sub remove_generated_files {
169 foreach (@gen_files) {
174 sub remove_generated_directories {
175 remove_empty_directories ($gen_dirs, "/");
178 sub add_directory_to_tree {
183 my @pathcomp = split /\//, $dir;
186 foreach (@pathcomp) {
188 if ($cur_name eq "" || !defined ($cur_name)) {
191 if (!defined ($p->{"$cur_name"})) {
192 $p->{$cur_name} = { };
194 $p = $p->{$cur_name};
199 sub remove_empty_directories {
202 my $children = (scalar (keys %{$rooth}));
206 foreach my $dirname (sort keys %{$rooth}) {
208 $printpath = "$path/$dirname";
209 $printpath =~ s#^/*#/#;
210 remove_empty_directories ($rooth->{$dirname}, "$printpath");
211 $dirs_remain = 1 if (-d "$printpath");
215 if ($dirs_remain == 0) {
216 maybe_remove_ds_store ("$path");
219 remove_a_dir ("$path");
224 my $dirname = dirname ($fn);
225 my $basename = basename ($fn);
226 my $ufs_rsrc_file = "$dirname/._$basename";
229 return if (!defined ($fn) || $fn eq "");
231 # Leave any files that are shared between packages alone.
232 if (defined($exception_list{$fn})) {
233 if ($noisy_warnings) {
234 print_warning ("Warning: file \"$fn\" intentionally not removed, " .
235 "even though it's in the BOM.\n");
240 if (! -f $fn && ! -l $fn) {
241 if ($noisy_warnings) {
242 print_warning ("Warning: file \"$fn\" present in BOM but not found on disc.\n");
247 if ($do_nothing == 1) {
248 print_donothing ("rm $fn\n");
249 print_donothing ("rm $ufs_rsrc_file\n") if ( -f $ufs_rsrc_file);
251 unshift(@rmfiles, "$fn");
252 unshift(@rmfiles, "$ufs_rsrc_file") if ( -f $ufs_rsrc_file);
260 return if (!defined ($dir) || $dir eq "" || $dir eq "/" || $dir eq "/usr");
262 if ($noisy_warnings) {
263 print_warning ("Warning: directory \"$dir\" present in BOM " .
264 "but not found on disc.\n");
269 if ($do_nothing == 1) {
270 print_donothing ("rmdir $dir\n");
272 push(@rmdirs, "$dir");
276 sub remove_package_receipts {
278 $pkgname =~ s#/##g; # There shouldn't be any path seps in the pkg name...
279 return if (!defined ($pkgname) || $pkgname eq ""
280 || $pkgname eq "." || $pkgname eq "..");
282 if ($do_nothing == 1) {
283 print_donothing("pkgutil --forget $pkgname\n");
285 push(@rmpkg, $pkgname);
289 sub maybe_remove_ds_store {
292 return if (!defined ($path) || $path eq "" || $path eq "/" || $path eq "/usr");
293 return if (! -f "$path/.DS_Store");
295 open (LS, "/bin/ls -a '$path' |");
298 next if (m#^\.$# || m#^\.\.$#);
303 if ($filecount == 1) {
304 remove_a_file ("$path/.DS_Store");
308 sub print_donothing {
310 return if ($print_donothing_removals != 1);
317 return if ($verbose != 1);
335 print "
\b" unless ($suppress_spin);
339 $spin_slower_downer = 150;
343 $spin_slower_downer = 75;
347 return if ($suppress_spin);
349 if (($spin_counter % $spin_slower_downer) == 0) {
350 my $spin_chars = "|/-\\";
351 my $c = substr ($spin_chars, $spin_state % 4, 1);
353 print "
\e[7m$c
\e[m
\b";