dpkg-name.pl 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. #!/usr/bin/perl
  2. #
  3. # dpkg-name
  4. #
  5. # Copyright © 1995,1996 Erick Branderhorst <branderh@debian.org>.
  6. # Copyright © 2009 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, write to the Free Software
  20. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  21. #
  22. use warnings;
  23. use strict;
  24. use File::Basename;
  25. use File::Path;
  26. use Dpkg;
  27. use Dpkg::Gettext;
  28. use Dpkg::ErrorHandling;
  29. use Dpkg::Cdata;
  30. use Dpkg::Arch qw(get_host_arch);
  31. textdomain("dpkg-dev");
  32. my %options = (
  33. subdir => 0,
  34. destdir => "",
  35. createdir => 0,
  36. overwrite => 0,
  37. symlink => 0,
  38. architecture => 1,
  39. );
  40. sub version()
  41. {
  42. printf(_g("Debian %s version %s.\n"), $progname, $version);
  43. }
  44. sub usage()
  45. {
  46. printf(_g("Usage: %s [<option>...] <file>...\n"), $progname);
  47. print(_g("
  48. Options:
  49. -a, --no-architecture no architecture part in filename.
  50. -o, --overwrite overwrite if file exists.
  51. -k, --symlink don't create a new file, but a symlink.
  52. -s, --subdir [dir] move file into subdir (use with care).
  53. -c, --create-dir create target dir if not there (use with care).
  54. -h, --help show this help message.
  55. -v, --version show the version.
  56. file.deb changes to <package>_<version>_<architecture>.<package_type>
  57. according to the 'underscores convention'.
  58. "));
  59. }
  60. sub fileexists($)
  61. {
  62. my ($filename) = @_;
  63. if (-f $filename) {
  64. return 1;
  65. } else {
  66. warning(_g("cannot find '%s'"), $filename);
  67. return 0;
  68. }
  69. }
  70. sub filesame($$)
  71. {
  72. my ($a, $b) = @_;
  73. my @sta = stat($a);
  74. my @stb = stat($b);
  75. # Same device and inode numbers.
  76. return (@sta and @stb and $sta[0] == $stb[0] and $sta[1] == $stb[1]);
  77. }
  78. sub getfields($)
  79. {
  80. my ($filename) = @_;
  81. # Read the fields
  82. open(CDATA, '-|', "dpkg-deb", "-f", "--", $filename) ||
  83. syserr(_g("cannot open %s"), $filename);
  84. my $fields = parsecdata(\*CDATA,
  85. sprintf(_g("binary control file %s"), $filename));
  86. close(CDATA);
  87. return $fields;
  88. }
  89. sub getarch($$)
  90. {
  91. my ($filename, $fields) = @_;
  92. my $arch = $fields->{Architecture};
  93. if (!$fields->{Architecture} and !$options{architecture}) {
  94. $arch = get_host_arch();
  95. warning(g_("assuming architecture '%s' for '%s'"), $arch, $filename);
  96. }
  97. return $arch;
  98. }
  99. sub getname($$$)
  100. {
  101. my ($filename, $fields, $arch) = @_;
  102. my $pkg = $fields->{Package};
  103. (my $version = $fields->{Version}) =~ s/.*://;
  104. my $revision = $fields->{Revision} || $fields->{Package_Revision};
  105. if ($revision) {
  106. $version .= "-$revision";
  107. }
  108. my $type = $fields->{'Package-Type'} || 'deb';
  109. my $tname;
  110. if ($options{architecture}) {
  111. $tname = "$pkg\_$version\_$arch.$type";
  112. } else {
  113. $tname = "$pkg\_$version.$type";
  114. }
  115. (my $name = $tname) =~ s/ //g;
  116. if ($tname ne $name) { # control fields have spaces
  117. warning("bad package control information for '%s'", $filename);
  118. }
  119. return $name;
  120. }
  121. sub getdir($$$)
  122. {
  123. my ($filename, $fields, $arch) = @_;
  124. my $dir;
  125. if (!$options{destdir}) {
  126. $dir = dirname($filename);
  127. if ($options{subdir}) {
  128. my $section = $fields->{Section};
  129. if (!$section) {
  130. $section = "no-section";
  131. warning("assuming section '%s' for '%s'", $section, $filename);
  132. }
  133. if ($section ne "non-free" and $section ne "contrib" and
  134. $section ne "no-section") {
  135. $dir = "unstable/binary-$arch/$section";
  136. } else {
  137. $dir = "$section/binary-$arch";
  138. }
  139. }
  140. } else {
  141. $dir = $options{destdir};
  142. }
  143. return $dir;
  144. }
  145. sub move($)
  146. {
  147. my ($filename) = @_;
  148. if (fileexists($filename)) {
  149. my $fields = getfields($filename);
  150. unless (exists $fields->{Package}) {
  151. warning("no Package field found in '%s', skipping it", $filename);
  152. return;
  153. }
  154. my $arch = getarch($filename, $fields);
  155. my $name = getname($filename, $fields, $arch);
  156. my $dir = getdir($filename, $fields, $arch);
  157. if (! -d $dir) {
  158. if ($options{createdir}) {
  159. if (mkpath($dir)) {
  160. info("created directory '%s'", $dir);
  161. } else {
  162. error("failed creating directory '%s'", $dir);
  163. }
  164. } else {
  165. error("no such dir '%s', try --create-dir (-c) option", $dir);
  166. }
  167. }
  168. my $newname = "$dir/$name";
  169. my @command;
  170. if ($options{symlink}) {
  171. @command = ("ln", "-s", "--");
  172. } else {
  173. @command = ("mv", "--");
  174. }
  175. if (filesame($newname, $filename)) {
  176. warning("skipping '%s'", $filename);
  177. } elsif (-f $newname and !$options{overwrite}) {
  178. warning("cannot move '%s' to existing file", $filename);
  179. } elsif (system(@command, $filename, $newname) == 0) {
  180. info("moved '%s' to '%s'", basename($filename), $newname);
  181. } else {
  182. error("mkdir can be used to create directory");
  183. }
  184. }
  185. }
  186. @ARGV || usageerr(_g("need at least a filename"));
  187. while (@ARGV) {
  188. $_ = shift(@ARGV);
  189. if (m/^-[h?]|--help$/) {
  190. usage();
  191. exit(0);
  192. } elsif (m/^-v|--version$/) {
  193. version();
  194. exit(0);
  195. } elsif (m/^-c|--create-dir$/) {
  196. $options{createdir} = 1;
  197. } elsif (m/^-s|--subdir$/) {
  198. $options{subdir} = 1;
  199. if (-d $ARGV[0]) {
  200. $options{destdir} = shift(@ARGV);
  201. }
  202. } elsif (m/^-o|--overwrite$/) {
  203. $options{overwite} = 1;
  204. } elsif (m/^-k|--symlink$/) {
  205. $options{symlink} = 1;
  206. } elsif (m/^-a|--no-architecture$/) {
  207. $options{architecture} = 0;
  208. } elsif (m/^--$/) {
  209. foreach (@ARGV) {
  210. move($_);
  211. }
  212. exit 0;
  213. } else {
  214. move($_);
  215. }
  216. }
  217. 0;