Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / packaging / MacOS / Uninstall
1 #!/usr/bin/perl -w
2 # real Perl code begins here
3 #
4 # Adapted from Apple's uninstall-devtools.pl (Version 7 for Xcode Tools 1.2)
5 #
6 # BSD License: c.f. <http://www.opensource.org/licenses/bsd-license>
7 #
8
9 use strict;
10 use File::Basename;
11
12 use vars qw ($do_nothing $print_donothing_removals $receipts_dir $verbose $noisy_warnings);
13 use vars qw ($suppress_spin $spin_counter $spin_state $spin_slower_downer);
14 use vars qw (%exception_list $gen_dirs @gen_files @rmfiles @rmdirs @rmpkg);
15
16 #----------------------------------------------------------------------------------------
17
18 $do_nothing = 0;
19 $print_donothing_removals = 1;
20 $verbose = 1;
21 $noisy_warnings = 0;
22
23 # One of rm -rf in this script uses $receipts_dir -- change with care.
24 $receipts_dir = "/Library/Receipts";
25
26 %exception_list = (
27 # '/usr/bin/aklog', '',
28 );
29
30 $gen_dirs = { };
31 #$gen_dirs->{"/"}->{"Library"}->{"OpenAFS"}->{"Tools"} = {};
32
33 @gen_files = (
34 "/var/db/openafs/etc/cacheinfo",
35 "/var/db/openafs/etc/ThisCell",
36 "/var/db/openafs/etc/config/afsd.options",
37 "/var/db/openafs/etc/config/afs.conf",
38 "/var/db/openafs/etc/CellServDB.save",
39 "/var/db/openafs/etc/CellServDB.master.last",
40 "/var/db/openafs/etc/CellServDB",
41 "/var/db/openafs/etc/config/settings.plist",
42 );
43
44 #----------------------------------------------------------------------------------------
45
46 $| = 1;
47 #if ($do_nothing == 0 && $< != 0)
48 # {
49 # die "ERROR: Must be run with root permissions--prefix command with 'sudo'.\n";
50 # }
51
52 sub main
53 {
54 # commandline args:
55 # 0: dir of packages to remove
56 # 1: flag indicating whether to keep package receipts
57 # 2: flag indicating whether to supress spin indicator
58
59 if (!@ARGV) {
60 use FindBin qw($Bin);
61 @ARGV = ("$Bin/..", 0, 0);
62 }
63 $suppress_spin = defined ($ARGV[2]) && $ARGV[2];
64
65 $spin_counter = 0;
66 $spin_state = 0;
67 spin_rate_slow ();
68
69 pre_print ();
70 print "Uninstalling OpenAFS package:\n\n";
71
72 remove_generated_files ();
73 remove_main_packages ();
74 remove_generated_directories ();
75
76 if ($do_nothing == 0) {
77 my @rmcmd = ('osascript', '-e', "do shell script \"/bin/rm -f @rmfiles; /bin/rmdir @rmdirs; /bin/rm -rf @rmpkg\" with administrator privileges");
78 system @rmcmd;
79 my $retcode = $? >> 8;
80 if ($retcode != 0) {
81 print_warning ("Warning: There may have been a problem uninstalling\n");
82 }
83 }
84
85 pre_print ();
86 print "\nFinished uninstalling.\n";
87 }
88
89 sub remove_main_packages
90 {
91 # opendir (DIR, $ARGV[0]) or die "ERROR: package directory $ARGV[0] not found\n";
92 # my @pkglist = grep /\.pkg$/, readdir DIR;
93 # closedir DIR;
94 my @pkglist = ("org.openafs.OpenAFS-debug",
95 "org.openafs.OpenAFS",
96 "OpenAFS",
97 "OpenAFS-debug-extension",
98 );
99
100 foreach (@pkglist)
101 {
102 s/\.pkg$//;
103 my $pkgname = $_;
104 my $bompath = undef;
105 my $infopath = undef;
106 my $pkgname_plist_newpath = "/var/db/receipts/$pkgname.pkg.plist";
107 my $pkgname_bom_newpath = "/var/db/receipts/$pkgname.pkg.bom";
108 my $pkgname_plist_fullpath = "/Library/Receipts/$pkgname.pkg/Contents/Info.plist";
109 my $pkgname_bom_fullpath = "/Library/Receipts/$pkgname.pkg/Contents/Archive.bom";
110
111 if (-f $pkgname_plist_newpath && -r $pkgname_plist_newpath && -f $pkgname_bom_newpath && -r $pkgname_bom_newpath) {
112 print_verbose ("Removing package $pkgname.pkg\n");
113 $bompath = $pkgname_bom_newpath;
114 $infopath = $pkgname_plist_newpath;
115 } else {
116 if (-f $pkgname_plist_fullpath && -r $pkgname_plist_fullpath && -f $pkgname_bom_fullpath && -r $pkgname_bom_fullpath) {
117 print_verbose ("Removing package $pkgname.pkg\n");
118 $bompath = $pkgname_bom_fullpath;
119 $infopath = $pkgname_plist_fullpath;
120 } else {
121 next;
122 }
123 }
124
125 next if (!defined ($bompath));
126
127 my $bomroot = "";
128 open (INFO, "$infopath") or next;
129 while (<INFO>) {
130 m/IFPkgFlagDefaultLocation/ or next;
131 $bomroot = <INFO>;
132 }
133 close (INFO);
134
135 $bomroot =~ />(.*)</;
136 $bomroot = $1;
137 $bomroot =~ s/^\/$//;
138
139 spin_rate_slow ();
140
141 open (LSBOM, "/usr/bin/lsbom -l -f -p f '$bompath' |") or next;
142 while (<LSBOM>)
143 {
144 chomp;
145 m#^\.(/.*)$#;
146 next if (!defined ($1) || $1 eq "");
147 my $filename = $bomroot . $1;
148
149 remove_a_file ($filename);
150 }
151 close (LSBOM);
152
153 my $rooth = { };
154
155 open (LSBOM, "/usr/bin/lsbom -d -p f '$bompath' |") or next;
156 while (<LSBOM>)
157 {
158 chomp;
159 m#^\.(/.*)$#;
160 next if (!defined ($1) || $1 eq "");
161 my $directory = $bomroot . $1;
162 if (-d $directory)
163 {
164 $rooth = add_directory_to_tree ($directory, $rooth);
165 }
166 else
167 {
168 if ($noisy_warnings)
169 {
170 print_warning ("Warning: \"$directory\" listed in BOM but not present on system.\n");
171 }
172 }
173 }
174 close (LSBOM);
175
176 spin_rate_fast ();
177 remove_empty_directories ($rooth, "/");
178
179 if (-d "$receipts_dir/$pkgname.pkg" ) {
180 remove_package_receipts ("$pkgname.pkg") if (!defined ($ARGV[1]) || !$ARGV[1]) ;
181 } else {
182 unshift(@rmfiles, "$bompath");
183 unshift(@rmfiles, "$infopath");
184 }
185 }
186 }
187
188 sub remove_generated_files
189 {
190 foreach (@gen_files)
191 {
192 remove_a_file ($_);
193 }
194 }
195
196 sub remove_generated_directories
197 {
198 remove_empty_directories ($gen_dirs, "/");
199 }
200
201 sub add_directory_to_tree
202 {
203 my $dir = shift;
204 my $rooth = shift;
205 my $p = $rooth;
206
207 my @pathcomp = split /\//, $dir;
208
209 progress_point ();
210 foreach (@pathcomp)
211 {
212 my $cur_name = $_;
213 if ($cur_name eq "" || !defined ($cur_name))
214 {
215 $cur_name = "/";
216 }
217 if (!defined ($p->{"$cur_name"}))
218 {
219 $p->{$cur_name} = { };
220 }
221 $p = $p->{$cur_name};
222 }
223 return $rooth;
224 }
225
226 sub remove_empty_directories
227 {
228 my $rooth = shift;
229 my $path = shift;
230 my $children = (scalar (keys %{$rooth}));
231 my $dirs_remain = 0;
232
233 if ($children > 0)
234 {
235 foreach my $dirname (sort keys %{$rooth})
236 {
237 my $printpath;
238 $printpath = "$path/$dirname";
239 $printpath =~ s#^/*#/#;
240 remove_empty_directories ($rooth->{$dirname}, "$printpath");
241 $dirs_remain = 1 if (-d "$printpath");
242 }
243 }
244
245 if ($dirs_remain == 0)
246 {
247 maybe_remove_ds_store ("$path");
248 }
249
250 remove_a_dir ("$path");
251 }
252
253 sub remove_a_file
254 {
255 my $fn = shift;
256 my $dirname = dirname ($fn);
257 my $basename = basename ($fn);
258 my $ufs_rsrc_file = "$dirname/._$basename";
259
260 progress_point ();
261 return if (!defined ($fn) || $fn eq "");
262
263 # Leave any files that are shared between packages alone.
264 if (defined($exception_list{$fn}))
265 {
266 if ($noisy_warnings)
267 {
268 print_warning ("Warning: file \"$fn\" intentionally not removed, even though it's in the BOM.\n");
269 }
270 return;
271 }
272
273 if (! -f $fn && ! -l $fn)
274 {
275 if ($noisy_warnings)
276 {
277 print_warning ("Warning: file \"$fn\" present in BOM but not found on disc.\n");
278 }
279 return;
280 }
281
282 if ($do_nothing == 1)
283 {
284 print_donothing ("rm $fn\n");
285 print_donothing ("rm $ufs_rsrc_file\n") if ( -f $ufs_rsrc_file);
286 }
287 else
288 {
289 unshift(@rmfiles, "$fn");
290 unshift(@rmfiles, "$ufs_rsrc_file") if ( -f $ufs_rsrc_file);
291 }
292 }
293
294 sub remove_a_dir
295 {
296 my $dir = shift;
297
298 progress_point ();
299 return if (!defined ($dir) || $dir eq "" || $dir eq "/" || $dir eq "/usr");
300 if (! -d $dir)
301 {
302 if ($noisy_warnings)
303 {
304 print_warning ("Warning: directory \"$dir\" present in BOM but not found on disc.\n");
305 }
306 return;
307 }
308
309 if ($do_nothing == 1)
310 {
311 print_donothing ("rmdir $dir\n");
312 }
313 else
314 {
315 push(@rmdirs, "$dir");
316 }
317 }
318
319 sub remove_package_receipts
320 {
321 my $pkgname = shift;
322 $pkgname =~ s#/##g; # There shouldn't be any path seps in the pkg name...
323 return if (!defined ($pkgname) || $pkgname eq ""
324 || $pkgname eq "." || $pkgname eq "..");
325
326 my $pkgdir = "$receipts_dir/$pkgname";
327 return if (!defined ($pkgdir) || $pkgdir eq "" || ! -d $pkgdir);
328
329 push(@rmpkg, "$pkgdir");
330 }
331
332
333 sub maybe_remove_ds_store
334 {
335 my $path = shift;
336 my $filecount = 0;
337 return if (!defined ($path) || $path eq "" || $path eq "/" || $path eq "/usr");
338 return if (! -f "$path/.DS_Store");
339
340 open (LS, "/bin/ls -a '$path' |");
341 while (<LS>)
342 {
343 chomp;
344 next if (m#^\.$# || m#^\.\.$#);
345 $filecount++;
346 }
347 close (LS);
348
349 if ($filecount == 1 && -f "$path/.DS_Store")
350 {
351 remove_a_file ("$path/.DS_Store");
352 }
353 }
354
355 sub print_donothing
356 {
357 my $msg = shift;
358 return if ($print_donothing_removals != 1);
359 pre_print ();
360 print $msg;
361 }
362
363 sub print_verbose
364 {
365 my $msg = shift;
366 return if ($verbose != 1);
367 pre_print ();
368 print $msg;
369 }
370
371 sub print_warning
372 {
373 my $msg = shift;
374 pre_print ();
375 print STDERR $msg;
376 }
377
378 sub print_error
379 {
380 my $msg = shift;
381 pre_print ();
382 print STDERR $msg;
383 }
384
385 sub pre_print
386 {
387 print " \b" unless ($suppress_spin);
388 }
389
390 sub spin_rate_slow
391 {
392 $spin_slower_downer = 150;
393 }
394
395 sub spin_rate_fast
396 {
397 $spin_slower_downer = 75;
398 }
399
400 sub progress_point
401 {
402 return if ($suppress_spin);
403 $spin_counter++;
404 if (($spin_counter % $spin_slower_downer) == 0)
405 {
406 my $spin_chars = "|/-\\";
407 my $c = substr ($spin_chars, $spin_state % 4, 1);
408 $spin_state++;
409 print "\e[7m$c\e[m\b";
410 }
411 }
412
413 main ();
414
415 #----------------------------------------------------------------------------------------