]> git.donarmstrong.com Git - debhelper.git/blob - dh_usrlocal
r1824: * Man page type fixes (yes, more, nice to know people read the man pages).
[debhelper.git] / dh_usrlocal
1 #!/usr/bin/perl
2
3 =head1 NAME
4
5 dh_usrlocal - migrate usr/local directories to maintainer scripts
6
7 =cut
8
9 use warnings;
10 use strict;
11 use Debian::Debhelper::Dh_Lib;
12 use File::Find;
13 use File::stat;
14
15 =head1 SYNOPSIS
16
17 B<dh_usrlocal> [S<I<debhelper options>>] [B<-n>]
18
19 =head1 DESCRIPTION
20
21 dh_usrlocal is a debhelper program that can be used for building packages
22 that will provide a subdirectory in /usr/local when installed.
23
24 It finds subdirectories of usr/local in the package build directory, and
25 removes them, replacing them with maintainer script snippets (unless B<-n>
26 is used) to create the directories at install time, and remove them when
27 the package is removed, in a manner compliant with Debian policy. See
28 L<dh_installdeb(1)> for an explanation of Debhelper maintainer script
29 snippets.
30
31 If the directories found in the build tree have unusual owners, groups, or
32 permissions, then those values will be preserved in the directories made by
33 the postinst script. However, as a special exception, if a directory is owned
34 by root.root, it will be treated as if it is owned by root.staff and is mode
35 2775. This is useful, since that is the group and mode policy recommends for
36 directories in /usr/local.
37
38 =head1 OPTIONS
39
40 =over 4
41
42 =item B<-n>, B<--noscripts>
43
44 Do not modify F<postinst>/F<prerm> scripts.
45
46 =back
47
48 =head1 NOTES
49
50 Note that this command is not idempotent. "dh_clean -k" should be called
51 between invocations of this command. Otherwise, it may cause multiple
52 instances of the same text to be added to maintainer scripts.
53
54 =head1 CONFORMS TO
55
56 Debian policy, version 2.2
57
58 =cut
59
60 init();
61
62 foreach my $package (@{$dh{DOPACKAGES}}) {
63         my $tmp = tmpdir($package);
64
65         if (-d "$tmp/usr/local") {
66                 my (@dirs, @justdirs);
67                 find({bydepth => 1,
68                       no_chdir => 1,
69                       wanted => sub {
70                         my $fn = $File::Find::name;
71                         if (-d $fn) {
72                                 my $stat = stat $fn;
73                                 my $user = getpwuid $stat->uid;
74                                 my $group = getgrgid $stat->gid;
75                                 my $mode = sprintf "%04lo", ($stat->mode & 07777);
76
77                                 if ($stat->uid == 0 && $stat->gid == 0) {
78                                         $group = 'staff';
79                                         $mode = '2775';
80                                 }
81
82                                 $fn =~ s!^\Q$tmp\E!!;
83                                 return if $fn eq '/usr/local';
84                                 
85                                 # @dirs is in parents-first order for dir creation...
86                                 unshift @dirs, "$fn $mode $user $group";
87                                 # ...whereas @justdirs is depth-first for removal.
88                                 push @justdirs, $fn;
89                                 doit("rmdir $_");
90                         }
91                         else {
92                                 warning("$fn is not a directory");
93                         }
94                       }}, "$tmp/usr/local");
95                 doit("rmdir $tmp/usr/local");
96         
97                 my $bs = "\\";     # A single plain backslash
98                 my $ebs = $bs x 2; # Escape the backslash from the shell
99                 # This constructs the body of a 'sed' c\ expression which
100                 # is parsed by the shell in double-quotes
101                 my $dirs = join("$ebs\n", @dirs);
102                 pop @justdirs; # don't remove directories directly in /usr/local
103                 my $justdirs = join("$ebs\n", @justdirs);
104                 if (! $dh{NOSCRIPTS}) { 
105                         autoscript($package,"postinst", "postinst-usrlocal",
106                                    "/#DIRS#/ c${ebs}\n${dirs}");
107                         autoscript($package,"prerm", "prerm-usrlocal",
108                                    "/#JUSTDIRS#/ c${ebs}\n${justdirs}") if length $justdirs;
109                 }
110         }
111 }
112
113 =head1 SEE ALSO
114
115 L<debhelper(7)>
116
117 This program is a part of debhelper.
118
119 =head1 AUTHOR
120
121 Andrew Stribblehill <ads@debian.org>
122
123 =cut