dpkg-statoverride.pl 5.9 KB

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