dpkg-statoverride.pl 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. #! /usr/bin/perl
  2. use POSIX;
  3. use POSIX qw(:errno_h :signal_h);
  4. $admindir= "/var/lib/dpkg"; # This line modified by Makefile
  5. $version= '1.3.0'; # This line modified by Makefile
  6. $verbose= 1;
  7. $doforce= 0;
  8. $doupdate= 0;
  9. $mode= "";
  10. sub UsageVersion {
  11. print STDERR <<EOF || &quit("failed to write usage: $!");
  12. Debian dpkg-statoverride $version.
  13. Copyright (C) 2000 Wichert Akkerman.
  14. This is free software; see the GNU General Public Licence version 2 or later
  15. for copying conditions. There is NO warranty.
  16. Usage:
  17. dpkg-statoverride [options] --add <owner> <group> <mode> <file>
  18. dpkg-statoverride [options] --remove <file>
  19. dpkg-statoverride [options] --list [<glob-pattern>]
  20. Options:
  21. --update immediately update file permissions
  22. --force force an action even if a sanity check fails
  23. --quiet quiet operation, minimal output
  24. --help print this help screen and exit
  25. --admindir <directory> set the directory with the statoverride file
  26. EOF
  27. }
  28. sub CheckModeConflict {
  29. return unless $mode;
  30. &badusage("two modes specified: $_ and --$mode");
  31. }
  32. while (@ARGV) {
  33. $_=shift(@ARGV);
  34. last if m/^--$/;
  35. if (!m/^-/) {
  36. unshift(@ARGV,$_); last;
  37. } elsif (m/^--help$/) {
  38. &UsageVersion; exit(0);
  39. } elsif (m/^--update$/) {
  40. $doupdate=1;
  41. } elsif (m/^--quiet$/) {
  42. $verbose=0;
  43. } elsif (m/^--force$/) {
  44. $doforce=1;
  45. } elsif (m/^--admindir$/) {
  46. @ARGV || &badusage("--admindir needs a directory argument");
  47. $admindir= shift(@ARGV);
  48. } elsif (m/^--add$/) {
  49. &CheckModeConflict;
  50. $mode= 'add';
  51. } elsif (m/^--remove$/) {
  52. &CheckModeConflict;
  53. $mode= 'remove';
  54. } elsif (m/^--list$/) {
  55. &CheckModeConflict;
  56. $mode= 'list';
  57. } else {
  58. &badusage("unknown option \`$_'");
  59. }
  60. }
  61. $dowrite=0;
  62. $exitcode=0;
  63. &badusage("no mode specified") unless $mode;
  64. &ReadOverrides;
  65. if ($mode eq "add") {
  66. @ARGV==4 || &badusage("--add needs four arguments");
  67. $user=$ARGV[0];
  68. if ($user =~ m/^#([0-9]+)$/) {
  69. $uid=$1;
  70. &badusage("illegal user $user") if ($uid<0);
  71. } else {
  72. (($name,$pw,$uid)=getpwnam($user)) || &badusage("non-existing user $user");
  73. }
  74. $group=$ARGV[1];
  75. if ($group =~ m/^#([0-9]+)$/) {
  76. $gid=$1;
  77. &badusage("illegal group $group") if ($gid<0);
  78. } else {
  79. (($name,$pw,$gid)=getgrnam($group)) || &badusage("non-existing group $group");
  80. }
  81. $mode= $ARGV[2];
  82. (($mode<0) or (oct($mode)>07777)) && &badusage("illegal mode $mode");
  83. $file= $ARGV[3];
  84. $file =~ m/\n/ && &badusage("file may not contain newlines");
  85. $file =~ s,/+$,, && print STDERR "stripping trailing /\n";
  86. if (defined $owner{$file}) {
  87. print STDERR "An override for \"$file\" already exists, ";
  88. if ($doforce) {
  89. print STDERR "but --force specified so lets ignore it.\n";
  90. } else {
  91. print STDERR "aborting\n";
  92. exit(3);
  93. }
  94. }
  95. $owner{$file}=$user;
  96. $group{$file}=$group;
  97. $mode{$file}=$mode;
  98. $dowrite=1;
  99. if ($doupdate) {
  100. if (not -e $file) {
  101. print STDERR "warning: --update given but $file does not exist\n";
  102. } else {
  103. chown ($uid,$gid,$file) || warn "failed to chown $file: $!\n";
  104. chmod (oct($mode),$file) || warn "failed to chmod $file: $!\n";
  105. }
  106. }
  107. } elsif ($mode eq "remove") {
  108. @ARGV==1 || &badusage("--remove needs one arguments");
  109. $file=$ARGV[0];
  110. $file =~ s,/+$,, && print STDERR "stripping trailing /\n";
  111. if (not defined $owner{$file}) {
  112. print STDERR "No override present.\n";
  113. exit(0) if ($doforce);
  114. exit(2);
  115. }
  116. delete $owner{$file};
  117. delete $group{$file};
  118. delete $mode{$file};
  119. $dowrite=1;
  120. print STDERR "warning: --update is useless for --remove\n" if ($doupdate);
  121. } elsif ($mode eq "list") {
  122. my (@list,@ilist,$pattern,$file);
  123. @ilist= @ARGV ? @ARGV : ('*');
  124. while (defined($_=shift(@ilist))) {
  125. s/\W/\\$&/g;
  126. s/\\\?/./g;
  127. s/\\\*/.*/g;
  128. s,/+$,, && print STDERR "stripping trailing /\n";
  129. push(@list,"^$_\$");
  130. }
  131. $pat= join('|',@list);
  132. $exitcode=1;
  133. for $file (keys %owner) {
  134. next unless ($file =~ m/$pat/o);
  135. $exitcode=0;
  136. print "$owner{$file} $group{$file} $mode{$file} $file\n";
  137. }
  138. }
  139. &WriteOverrides if ($dowrite);
  140. exit($exitcode);
  141. sub ReadOverrides {
  142. open(SO,"$admindir/statoverride") || &quit("cannot open statoverride: $!");
  143. while (<SO>) {
  144. my ($owner,$group,$mode,$file);
  145. chomp;
  146. ($owner,$group,$mode,$file)=split(' ', $_, 4);
  147. die "Multiple overrides for \"$file\", aborting"
  148. if defined $owner{$file};
  149. $owner{$file}=$owner;
  150. $group{$file}=$group;
  151. $mode{$file}=$mode;
  152. }
  153. close(SO);
  154. }
  155. sub WriteOverrides {
  156. my ($file);
  157. open(SO,">$admindir/statoverride-new") || &quit("cannot open new statoverride file: $!");
  158. foreach $file (keys %owner) {
  159. print SO "$owner{$file} $group{$file} $mode{$file} $file\n";
  160. }
  161. close(SO);
  162. chmod(0644, "$admindir/statoverride-new");
  163. unlink("$admindir/statoverride-old") ||
  164. $! == ENOENT || &quit("error removing statoverride-old: $!");
  165. link("$admindir/statoverride","$admindir/statoverride-old") ||
  166. $! == ENOENT || &quit("error creating new statoverride-old: $!");
  167. rename("$admindir/statoverride-new","$admindir/statoverride")
  168. || &quit("error installing new statoverride: $!");
  169. }
  170. sub quit { print STDERR "dpkg-statoverride: @_\n"; exit(2); }
  171. sub badusage { print STDERR "dpkg-statoverride: @_\n\n"; print("You need --help.\n"); exit(2); }
  172. # vi: ts=8 sw=8 ai si cindent