dpkg-statoverride.pl 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  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. &badusage("no mode specified") unless $mode;
  63. &ReadOverrides;
  64. if ($mode eq "add") {
  65. @ARGV==4 || &badusage("--add needs four arguments");
  66. $user=$ARGV[0];
  67. if ($user =~ m/^#([0-9]+)$/) {
  68. $uid=$1;
  69. &badusage("illegal user $user") if ($uid<0);
  70. } else {
  71. (($name,$pw,$uid)=getpwnam($user)) || &badusage("non-existing user $user");
  72. }
  73. $group=$ARGV[1];
  74. if ($group =~ m/^#([0-9]+)$/) {
  75. $gid=$1;
  76. &badusage("illegal group $group") if ($gid<0);
  77. } else {
  78. (($name,$pw,$gid)=getgrnam($group)) || &badusage("non-existing group $group");
  79. }
  80. $mode= $ARGV[2];
  81. (($mode<0) or (oct($mode)>07777)) && &badusage("illegal mode $mode");
  82. $file= $ARGV[3];
  83. $file =~ m/\n/ && &badusage("file may not contain newlines");
  84. if (defined $owner{$file}) {
  85. print STDERR "An override for \"$file\" already exists, ";
  86. if ($doforce) {
  87. print STDERR "but --force specified so lets ignore it.\n";
  88. } else {
  89. print STDERR "aborting\n";
  90. exit(3);
  91. }
  92. }
  93. $owner{$file}=$user;
  94. $group{$file}=$group;
  95. $mode{$file}=$mode;
  96. $dowrite=1;
  97. if ($doupdate) {
  98. if (not -e $file) {
  99. print STDERR "warning: --update given but $file does not exist\n";
  100. } else {
  101. chown ($uid,$gid,$file) || warn "failed to chown $file: $!\n";
  102. chmod (oct($mode),$file) || warn "failed to chmod $file: $!\n";
  103. }
  104. }
  105. } elsif ($mode eq "remove") {
  106. @ARGV==1 || &badusage("--remove needs one arguments");
  107. $file=$ARGV[0];
  108. if (not defined $owner{$file}) {
  109. print STDERR "No override present.\n";
  110. exit(0);
  111. }
  112. delete $owner{$file};
  113. delete $group{$file};
  114. delete $mode{$file};
  115. $dowrite=1;
  116. print STDERR "warning: --update is useless for --remove\n" if ($doupdate);
  117. } elsif ($mode eq "list") {
  118. my (@list,@ilist,$pattern,$file);
  119. @ilist= @ARGV ? @ARGV : ('*');
  120. while (defined($_=shift(@ilist))) {
  121. s/\W/\\$&/g;
  122. s/\\\?/./g;
  123. s/\\\*/.*/g;
  124. push(@list,"^$_\$");
  125. }
  126. $pat= join('|',@list);
  127. for $file (keys %owner) {
  128. next unless ($file =~ m/$pat/o);
  129. print "$owner{$file} $group{$file} $mode{$file} $file\n";
  130. }
  131. }
  132. &WriteOverrides if ($dowrite);
  133. exit(0);
  134. sub ReadOverrides {
  135. open(SO,"$admindir/statoverride") || &quit("cannot open statoverride: $!");
  136. while (<SO>) {
  137. my ($owner,$group,$mode,$file);
  138. chomp;
  139. ($owner,$group,$mode,$file)=split(' ', $_, 4);
  140. die "Multiple overrides for \"$file\", aborting"
  141. if defined $owner{$file};
  142. $owner{$file}=$owner;
  143. $group{$file}=$group;
  144. $mode{$file}=$mode;
  145. }
  146. close(SO);
  147. }
  148. sub WriteOverrides {
  149. my ($file);
  150. open(SO,">$admindir/statoverride-new") || &quit("cannot open new statoverride file: $!");
  151. foreach $file (keys %owner) {
  152. print SO "$owner{$file} $group{$file} $mode{$file} $file\n";
  153. }
  154. close(SO);
  155. chmod(0644, "$admindir/statoverride-new");
  156. unlink("$admindir/statoverride-old") ||
  157. $! == ENOENT || &quit("error removing statoverride-old: $!");
  158. link("$admindir/statoverride","$admindir/statoverride-old") ||
  159. $! == ENOENT || &quit("error creating new statoverride-old: $!");
  160. rename("$admindir/statoverride-new","$admindir/statoverride")
  161. || &quit("error installing new statoverride: $!");
  162. }
  163. sub quit { print STDERR "dpkg-statoverride: @_\n"; exit(2); }
  164. sub badusage { print STDERR "dpkg-statoverride: @_\n\n"; print("You need --help.\n"); exit(2); }
  165. # vi: ts=8 sw=8 ai si cindent