dpkg-name.pl 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. #!/usr/bin/perl
  2. #
  3. # dpkg-name
  4. #
  5. # Copyright © 1995,1996 Erick Branderhorst <branderh@debian.org>.
  6. # Copyright © 2006-2010,2012-2013 Guillem Jover <guillem@debian.org>
  7. #
  8. # This program is free software; you can redistribute it and/or modify
  9. # it under the terms of the GNU General Public License as published by
  10. # the Free Software Foundation; either version 2 of the License, or
  11. # (at your option) any later version.
  12. #
  13. # This program is distributed in the hope that it will be useful,
  14. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. # GNU General Public License for more details.
  17. #
  18. # You should have received a copy of the GNU General Public License
  19. # along with this program. If not, see <https://www.gnu.org/licenses/>.
  20. use warnings;
  21. use strict;
  22. use File::Basename;
  23. use File::Path;
  24. use Dpkg ();
  25. use Dpkg::Gettext;
  26. use Dpkg::ErrorHandling;
  27. use Dpkg::Control;
  28. use Dpkg::Arch qw(get_host_arch);
  29. textdomain('dpkg-dev');
  30. my %options = (
  31. subdir => 0,
  32. destdir => '',
  33. createdir => 0,
  34. overwrite => 0,
  35. symlink => 0,
  36. architecture => 1,
  37. );
  38. sub version()
  39. {
  40. printf(_g("Debian %s version %s.\n"), $Dpkg::PROGNAME, $Dpkg::PROGVERSION);
  41. }
  42. sub usage()
  43. {
  44. printf(_g("Usage: %s [<option>...] <file>...\n"), $Dpkg::PROGNAME);
  45. print(_g("
  46. Options:
  47. -a, --no-architecture no architecture part in filename.
  48. -o, --overwrite overwrite if file exists.
  49. -k, --symlink don't create a new file, but a symlink.
  50. -s, --subdir [dir] move file into subdir (use with care).
  51. -c, --create-dir create target dir if not there (use with care).
  52. -?, --help show this help message.
  53. -v, --version show the version.
  54. file.deb changes to <package>_<version>_<architecture>.<package_type>
  55. according to the 'underscores convention'.
  56. "));
  57. }
  58. sub fileexists($)
  59. {
  60. my ($filename) = @_;
  61. if (-f $filename) {
  62. return 1;
  63. } else {
  64. warning(_g("cannot find '%s'"), $filename);
  65. return 0;
  66. }
  67. }
  68. sub filesame($$)
  69. {
  70. my ($a, $b) = @_;
  71. my @sta = stat($a);
  72. my @stb = stat($b);
  73. # Same device and inode numbers.
  74. return (@sta and @stb and $sta[0] == $stb[0] and $sta[1] == $stb[1]);
  75. }
  76. sub getfields($)
  77. {
  78. my ($filename) = @_;
  79. # Read the fields
  80. open(my $cdata_fh, '-|', 'dpkg-deb', '-f', '--', $filename)
  81. or syserr(_g('cannot open %s'), $filename);
  82. my $fields = Dpkg::Control->new(type => CTRL_PKG_DEB);
  83. $fields->parse($cdata_fh, sprintf(_g('binary control file %s'), $filename));
  84. close($cdata_fh);
  85. return $fields;
  86. }
  87. sub getarch($$)
  88. {
  89. my ($filename, $fields) = @_;
  90. my $arch = $fields->{Architecture};
  91. if (not $fields->{Architecture} and $options{architecture}) {
  92. $arch = get_host_arch();
  93. warning(_g("assuming architecture '%s' for '%s'"), $arch, $filename);
  94. }
  95. return $arch;
  96. }
  97. sub getname($$$)
  98. {
  99. my ($filename, $fields, $arch) = @_;
  100. my $pkg = $fields->{Package};
  101. (my $version = $fields->{Version}) =~ s/.*://;
  102. my $type = $fields->{'Package-Type'} || 'deb';
  103. my $tname;
  104. if ($options{architecture}) {
  105. $tname = "$pkg\_$version\_$arch.$type";
  106. } else {
  107. $tname = "$pkg\_$version.$type";
  108. }
  109. (my $name = $tname) =~ s/ //g;
  110. if ($tname ne $name) { # control fields have spaces
  111. warning(_g("bad package control information for '%s'"), $filename);
  112. }
  113. return $name;
  114. }
  115. sub getdir($$$)
  116. {
  117. my ($filename, $fields, $arch) = @_;
  118. my $dir;
  119. if (!$options{destdir}) {
  120. $dir = dirname($filename);
  121. if ($options{subdir}) {
  122. my $section = $fields->{Section};
  123. if (!$section) {
  124. $section = 'no-section';
  125. warning(_g("assuming section '%s' for '%s'"), $section,
  126. $filename);
  127. }
  128. if ($section ne 'non-free' and $section ne 'contrib' and
  129. $section ne 'no-section') {
  130. $dir = "unstable/binary-$arch/$section";
  131. } else {
  132. $dir = "$section/binary-$arch";
  133. }
  134. }
  135. } else {
  136. $dir = $options{destdir};
  137. }
  138. return $dir;
  139. }
  140. sub move($)
  141. {
  142. my ($filename) = @_;
  143. if (fileexists($filename)) {
  144. my $fields = getfields($filename);
  145. unless (exists $fields->{Package}) {
  146. warning(_g("no Package field found in '%s', skipping it"),
  147. $filename);
  148. return;
  149. }
  150. my $arch = getarch($filename, $fields);
  151. my $name = getname($filename, $fields, $arch);
  152. my $dir = getdir($filename, $fields, $arch);
  153. if (! -d $dir) {
  154. if ($options{createdir}) {
  155. if (mkpath($dir)) {
  156. info(_g("created directory '%s'"), $dir);
  157. } else {
  158. error(_g("cannot create directory '%s'"), $dir);
  159. }
  160. } else {
  161. error(_g("no such directory '%s', try --create-dir (-c) option"),
  162. $dir);
  163. }
  164. }
  165. my $newname = "$dir/$name";
  166. my @command;
  167. if ($options{symlink}) {
  168. @command = qw(ln -s --);
  169. } else {
  170. @command = qw(mv --);
  171. }
  172. if (filesame($newname, $filename)) {
  173. warning(_g("skipping '%s'"), $filename);
  174. } elsif (-f $newname and not $options{overwrite}) {
  175. warning(_g("cannot move '%s' to existing file"), $filename);
  176. } elsif (system(@command, $filename, $newname) == 0) {
  177. info(_g("moved '%s' to '%s'"), basename($filename), $newname);
  178. } else {
  179. error(_g('mkdir can be used to create directory'));
  180. }
  181. }
  182. }
  183. my @files;
  184. while (@ARGV) {
  185. $_ = shift(@ARGV);
  186. if (m/^-\?|--help$/) {
  187. usage();
  188. exit(0);
  189. } elsif (m/^-v|--version$/) {
  190. version();
  191. exit(0);
  192. } elsif (m/^-c|--create-dir$/) {
  193. $options{createdir} = 1;
  194. } elsif (m/^-s|--subdir$/) {
  195. $options{subdir} = 1;
  196. if (-d $ARGV[0]) {
  197. $options{destdir} = shift(@ARGV);
  198. }
  199. } elsif (m/^-o|--overwrite$/) {
  200. $options{overwrite} = 1;
  201. } elsif (m/^-k|--symlink$/) {
  202. $options{symlink} = 1;
  203. } elsif (m/^-a|--no-architecture$/) {
  204. $options{architecture} = 0;
  205. } elsif (m/^--$/) {
  206. push @files, @ARGV;
  207. last;
  208. } elsif (m/^-/) {
  209. usageerr(_g("unknown option \`%s'"), $_);
  210. } else {
  211. push @files, $_;
  212. }
  213. }
  214. @files or usageerr(_g('need at least a filename'));
  215. foreach my $file (@files) {
  216. move($file);
  217. }
  218. 0;