Fields.pm 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565
  1. # Copyright © 2007-2009 Raphaël Hertzog <hertzog@debian.org>
  2. #
  3. # This program is free software; you can redistribute it and/or modify
  4. # it under the terms of the GNU General Public License as published by
  5. # the Free Software Foundation; either version 2 of the License, or
  6. # (at your option) any later version.
  7. #
  8. # This program is distributed in the hope that it will be useful,
  9. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. # GNU General Public License for more details.
  12. #
  13. # You should have received a copy of the GNU General Public License along
  14. # with this program; if not, write to the Free Software Foundation, Inc.,
  15. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  16. package Dpkg::Control::Fields;
  17. use strict;
  18. use warnings;
  19. use base qw(Exporter);
  20. use Dpkg::Gettext;
  21. use Dpkg::ErrorHandling;
  22. use Dpkg::Control::Types;
  23. use Dpkg::Checksums qw(@check_supported %check_supported);
  24. our @EXPORT = qw(field_capitalize field_is_official field_is_allowed_in
  25. field_transfer_single field_transfer_all
  26. field_list_src_dep field_list_pkg_dep field_get_dep_type
  27. field_ordered_list field_register
  28. field_insert_after field_insert_before);
  29. use constant {
  30. ALL_PKG => CTRL_INFO_PKG | CTRL_APT_PKG | CTRL_PKG_DEB | CTRL_FILE_STATUS,
  31. ALL_SRC => CTRL_INFO_SRC | CTRL_APT_SRC | CTRL_PKG_SRC,
  32. ALL_CHANGES => CTRL_FILE_CHANGES | CTRL_CHANGELOG,
  33. };
  34. # The canonical list of fields
  35. # Note that fields used only in dpkg's available file are not listed
  36. # Deprecated fields of dpkg's status file are also not listed
  37. our %FIELDS = (
  38. 'Architecture' => {
  39. allowed => (ALL_PKG | ALL_SRC | CTRL_FILE_CHANGES) & (~CTRL_INFO_SRC),
  40. },
  41. 'Binary' => {
  42. allowed => CTRL_PKG_SRC | CTRL_FILE_CHANGES,
  43. },
  44. 'Breaks' => {
  45. allowed => ALL_PKG,
  46. dependency => 'union',
  47. dep_order => 7,
  48. },
  49. 'Bugs' => {
  50. allowed => (ALL_PKG | CTRL_INFO_SRC | CTRL_FILE_VENDOR) & (~CTRL_INFO_PKG),
  51. },
  52. 'Build-Conflicts' => {
  53. allowed => ALL_SRC,
  54. dependency => 'union',
  55. dep_order => 3,
  56. },
  57. 'Build-Conflicts-Indep' => {
  58. allowed => ALL_SRC,
  59. dependency => 'union',
  60. dep_order => 4,
  61. },
  62. 'Build-Depends' => {
  63. allowed => ALL_SRC,
  64. dependency => 'normal',
  65. dep_order => 1,
  66. },
  67. 'Build-Depends-Indep' => {
  68. allowed => ALL_SRC,
  69. dependency => 'normal',
  70. dep_order => 2,
  71. },
  72. 'Changed-By' => {
  73. allowed => CTRL_FILE_CHANGES,
  74. },
  75. 'Changes' => {
  76. allowed => ALL_CHANGES,
  77. },
  78. 'Closes' => {
  79. allowed => ALL_CHANGES,
  80. },
  81. 'Conffiles' => {
  82. allowed => CTRL_FILE_STATUS,
  83. },
  84. 'Config-Version' => {
  85. allowed => CTRL_FILE_STATUS,
  86. },
  87. 'Conflicts' => {
  88. allowed => ALL_PKG,
  89. dependency => 'union',
  90. dep_order => 6,
  91. },
  92. 'Date' => {
  93. allowed => ALL_CHANGES,
  94. },
  95. 'Depends' => {
  96. allowed => ALL_PKG,
  97. dependency => 'normal',
  98. dep_order => 2,
  99. },
  100. 'Description' => {
  101. allowed => ALL_PKG | CTRL_FILE_CHANGES,
  102. },
  103. 'Directory' => {
  104. allowed => CTRL_APT_SRC,
  105. },
  106. 'Distribution' => {
  107. allowed => ALL_CHANGES,
  108. },
  109. 'Dm-Upload-Allowed' => {
  110. allowed => ALL_SRC,
  111. },
  112. 'Enhances' => {
  113. allowed => ALL_PKG,
  114. dependency => 'union',
  115. dep_order => 5,
  116. },
  117. 'Essential' => {
  118. allowed => ALL_PKG,
  119. },
  120. 'Filename' => {
  121. allowed => CTRL_APT_PKG,
  122. },
  123. 'Files' => {
  124. allowed => CTRL_PKG_SRC | CTRL_FILE_CHANGES,
  125. },
  126. 'Format' => {
  127. allowed => CTRL_PKG_SRC | CTRL_FILE_CHANGES,
  128. },
  129. 'Homepage' => {
  130. allowed => ALL_SRC | ALL_PKG,
  131. },
  132. 'Installed-Size' => {
  133. allowed => ALL_PKG & ~CTRL_INFO_PKG,
  134. },
  135. 'Installer-Menu-Item' => {
  136. allowed => ALL_PKG,
  137. },
  138. 'Kernel-Version' => {
  139. allowed => ALL_PKG,
  140. },
  141. 'Origin' => {
  142. allowed => (ALL_PKG | ALL_SRC) & (~CTRL_INFO_PKG),
  143. },
  144. 'Maintainer' => {
  145. allowed => CTRL_PKG_DEB | ALL_SRC | ALL_CHANGES,
  146. },
  147. 'Multi-Arch' => {
  148. allowed => ALL_PKG,
  149. },
  150. 'Package' => {
  151. allowed => ALL_PKG,
  152. },
  153. 'Package-Type' => {
  154. allowed => ALL_PKG,
  155. },
  156. 'Parent' => {
  157. allowed => CTRL_FILE_VENDOR,
  158. },
  159. 'Pre-Depends' => {
  160. allowed => ALL_PKG,
  161. dependency => 'normal',
  162. dep_order => 1,
  163. },
  164. 'Priority' => {
  165. allowed => CTRL_INFO_SRC | ALL_PKG,
  166. },
  167. 'Provides' => {
  168. allowed => ALL_PKG,
  169. dependency => 'union',
  170. dep_order => 9,
  171. },
  172. 'Recommends' => {
  173. allowed => ALL_PKG,
  174. dependency => 'normal',
  175. dep_order => 3,
  176. },
  177. 'Replaces' => {
  178. allowed => ALL_PKG,
  179. dependency => 'union',
  180. dep_order => 8,
  181. },
  182. 'Section' => {
  183. allowed => CTRL_INFO_SRC | ALL_PKG,
  184. },
  185. 'Size' => {
  186. allowed => CTRL_APT_PKG,
  187. },
  188. 'Source' => {
  189. allowed => (ALL_PKG | ALL_SRC | ALL_CHANGES) &
  190. (~(CTRL_APT_SRC | CTRL_INFO_PKG)),
  191. },
  192. 'Standards-Version' => {
  193. allowed => ALL_SRC,
  194. },
  195. 'Status' => {
  196. allowed => CTRL_FILE_STATUS,
  197. },
  198. 'Subarchitecture' => {
  199. allowed => ALL_PKG,
  200. },
  201. 'Suggests' => {
  202. allowed => ALL_PKG,
  203. dependency => 'normal',
  204. dep_order => 4,
  205. },
  206. 'Tag' => {
  207. allowed => ALL_PKG,
  208. },
  209. 'Task' => {
  210. allowed => ALL_PKG,
  211. },
  212. 'Triggers-Awaited' => {
  213. allowed => CTRL_FILE_STATUS,
  214. },
  215. 'Triggers-Pending' => {
  216. allowed => CTRL_FILE_STATUS,
  217. },
  218. 'Uploaders' => {
  219. allowed => ALL_SRC,
  220. },
  221. 'Urgency' => {
  222. allowed => ALL_CHANGES,
  223. },
  224. 'Vcs-Browser' => {
  225. allowed => ALL_SRC,
  226. },
  227. 'Vcs-Arch' => {
  228. allowed => ALL_SRC,
  229. },
  230. 'Vcs-Bzr' => {
  231. allowed => ALL_SRC,
  232. },
  233. 'Vcs-Cvs' => {
  234. allowed => ALL_SRC,
  235. },
  236. 'Vcs-Darcs' => {
  237. allowed => ALL_SRC,
  238. },
  239. 'Vcs-Git' => {
  240. allowed => ALL_SRC,
  241. },
  242. 'Vcs-Hg' => {
  243. allowed => ALL_SRC,
  244. },
  245. 'Vcs-Mtn' => {
  246. allowed => ALL_SRC,
  247. },
  248. 'Vcs-Svn' => {
  249. allowed => ALL_SRC,
  250. },
  251. 'Vendor' => {
  252. allowed => CTRL_FILE_VENDOR,
  253. },
  254. 'Vendor-Url' => {
  255. allowed => CTRL_FILE_VENDOR,
  256. },
  257. 'Version' => {
  258. allowed => (ALL_PKG | ALL_SRC | ALL_CHANGES) &
  259. (~(CTRL_INFO_SRC | CTRL_INFO_PKG)),
  260. },
  261. );
  262. my @checksum_fields = map { field_capitalize("Checksums-$_") } @check_supported;
  263. my @sum_fields = map { $_ eq "md5" ? "MD5sum" : field_capitalize($_) }
  264. @check_supported;
  265. &field_register($_, CTRL_PKG_SRC | CTRL_FILE_CHANGES) foreach @checksum_fields;
  266. &field_register($_, CTRL_APT_PKG) foreach @sum_fields;
  267. our %FIELD_ORDER = (
  268. CTRL_PKG_DEB() => [
  269. qw(Package Package-Type Source Version Kernel-Version Architecture
  270. Subarchitecture Installer-Menu-Item Essential Origin Bugs
  271. Maintainer Installed-Size), &field_list_pkg_dep(),
  272. qw(Section Priority Multi-Arch Homepage Description Tag Task)
  273. ],
  274. CTRL_PKG_SRC() => [
  275. qw(Format Source Binary Architecture Version Origin Maintainer
  276. Uploaders Dm-Upload-Allowed Homepage Standards-Version Vcs-Browser
  277. Vcs-Arch Vcs-Bzr Vcs-Cvs Vcs-Darcs Vcs-Git Vcs-Hg Vcs-Mtn
  278. Vcs-Svn), &field_list_src_dep(), @checksum_fields, qw(Files)
  279. ],
  280. CTRL_FILE_CHANGES() => [
  281. qw(Format Date Source Binary Architecture Version Distribution
  282. Urgency Maintainer Changed-By Description Closes Changes),
  283. @checksum_fields, qw(Files)
  284. ],
  285. CTRL_CHANGELOG() => [
  286. qw(Source Version Distribution Urgency Maintainer Date Closes
  287. Changes Timestamp Header Items Trailer Urgency_comment
  288. Urgency_lc)
  289. ],
  290. CTRL_FILE_STATUS() => [ # Same as fieldinfos in lib/dpkg/parse.c
  291. qw(Package Essential Status Priority Section Installed-Size Origin
  292. Maintainer Bugs Architecture Source Version Config-Version
  293. Replaces Provides Depends Pre-Depends Recommends Suggests Breaks
  294. Conflicts Enhances Conffiles Description Triggers-Pending
  295. Triggers-Awaited)
  296. ],
  297. );
  298. # Order for CTRL_APT_PKG is derived from CTRL_PKG_DEB
  299. $FIELD_ORDER{CTRL_APT_PKG()} = [ @{$FIELD_ORDER{CTRL_PKG_DEB()}} ];
  300. &field_insert_before(CTRL_APT_PKG, 'Section', 'Filename', 'Size', @sum_fields);
  301. # Order for CTRL_APT_SRC is derived from CTRL_PKG_SRC
  302. $FIELD_ORDER{CTRL_APT_SRC()} = [ @{$FIELD_ORDER{CTRL_PKG_SRC()}} ];
  303. @{$FIELD_ORDER{CTRL_APT_SRC()}} = map { $_ eq "Source" ? "Package" : $_ }
  304. @{$FIELD_ORDER{CTRL_PKG_SRC()}};
  305. &field_insert_before(CTRL_APT_SRC, "Checksums-Md5", "Directory");
  306. =head1 NAME
  307. Dpkg::Control::Fields - manage (list of official) control fields
  308. =head1 DESCRIPTION
  309. The modules contains a list of fieldnames with associated meta-data explaining
  310. in which type of control information they are allowed. The types are the
  311. CTRL_* constants exported by Dpkg::Control.
  312. =head1 FUNCTIONS
  313. =over 4
  314. =item my $f = field_capitalize($field_name)
  315. Returns the field name properly capitalized. All characters are lowercase,
  316. except the first of each word (words are separated by a dash in field names).
  317. =cut
  318. sub field_capitalize($) {
  319. my $field = lc(shift);
  320. # Some special cases due to history
  321. return "MD5sum" if $field eq "md5sum";
  322. return uc($field) if exists $check_supported{$field};
  323. # Generic case
  324. return join '-', map { ucfirst } split /-/, $field;
  325. }
  326. =item field_is_official($fname)
  327. Returns true if the field is official and known.
  328. =cut
  329. sub field_is_official($) {
  330. return exists $FIELDS{field_capitalize($_[0])};
  331. }
  332. =item field_is_allowed_in($fname, @types)
  333. Returns true (1) if the field $fname is allowed in all the types listed in
  334. the list. Note that you can use type sets instead of individual types (ex:
  335. CTRL_FILE_CHANGES | CTRL_CHANGELOG).
  336. field_allowed_in(A|B, C) returns true only if the field is allowed in C
  337. and either A or B.
  338. Undef is returned for non-official fields.
  339. =cut
  340. sub field_is_allowed_in($@) {
  341. my ($field, @types) = @_;
  342. $field = field_capitalize($field);
  343. return undef unless field_is_official($field);
  344. return 0 if not scalar(@types);
  345. foreach my $type (@types) {
  346. next if $type == CTRL_UNKNOWN; # Always allowed
  347. return 0 unless $FIELDS{$field}{'allowed'} & $type;
  348. }
  349. return 1;
  350. }
  351. =item field_transfer_single($from, $to, $field)
  352. If appropriate, copy the value of the field named $field taken from the
  353. $from Dpkg::Control object to the $to Dpkg::Control object.
  354. Official fields are copied only if the field is allowed in both types of
  355. objects. Custom fields are not copied except if the target object matches
  356. the target destination encoded in the field name. The initial X denoting
  357. custom fields can be followed by one or more letters among "S" (Source:
  358. corresponds to CTRL_PKG_SRC), "B" (Binary: corresponds to CTRL_PKG_DEB) or "C"
  359. (Changes: corresponds to CTRL_FILE_CHANGES).
  360. Returns undef if nothing has been copied or the name of the new field
  361. added to $to otherwise.
  362. =cut
  363. sub field_transfer_single($$_) {
  364. my ($from, $to, $field) = @_;
  365. my ($from_type, $to_type) = ($from->get_type(), $to->get_type());
  366. $field = field_capitalize($field);
  367. if (field_is_allowed_in($field, $from_type, $to_type)) {
  368. $to->{$field} = $from->{$field};
  369. return $field;
  370. } elsif ($field =~ /^X([SBC]*)-/i) {
  371. my $dest = $1;
  372. if (($dest =~ /B/i and $to_type == CTRL_PKG_DEB) or
  373. ($dest =~ /S/i and $to_type == CTRL_PKG_SRC) or
  374. ($dest =~ /C/i and $to_type == CTRL_FILE_CHANGES))
  375. {
  376. my $new = $field;
  377. $new =~ s/^X([SBC]*)-//i;
  378. $to->{$new} = $from->{$field};
  379. return $new;
  380. }
  381. } elsif (not field_is_allowed_in($field, $from_type)) {
  382. warning(_g("unknown information field '%s' in input data in %s"),
  383. $field, $from->get_option("name") || _g("control information"));
  384. }
  385. return undef;
  386. }
  387. =item field_transfer_all($from, $to)
  388. Transfer all appropriate fields from $from to $to. Calls
  389. field_transfer_single() on all fields available in $from.
  390. Returns the list of fields that have been added to $to.
  391. =cut
  392. sub field_transfer_all($$) {
  393. my ($from, $to) = @_;
  394. my (@res, $res);
  395. foreach my $k (keys %$from) {
  396. $res = field_transfer_single($from, $to, $k);
  397. push @res, $res if $res and defined wantarray;
  398. }
  399. return @res;
  400. }
  401. =item field_ordered_list($type)
  402. Returns an ordered list of fields for a given type of control information.
  403. This list can be used to output the fields in a predictable order.
  404. The list might be empty for types where the order does not matter much.
  405. =cut
  406. sub field_ordered_list($) {
  407. my ($type) = @_;
  408. return @{$FIELD_ORDER{$type}} if exists $FIELD_ORDER{$type};
  409. return ();
  410. }
  411. =item field_list_src_dep()
  412. List of fields that contains dependencies-like information in a source
  413. Debian package.
  414. =cut
  415. sub field_list_src_dep() {
  416. return sort {
  417. $FIELDS{$a}{'dep_order'} <=> $FIELDS{$b}{'dep_order'}
  418. } grep {
  419. field_is_allowed_in($_, CTRL_PKG_SRC) and
  420. exists $FIELDS{$_}{'dependency'}
  421. } keys %FIELDS;
  422. }
  423. =item field_list_pkg_dep()
  424. List of fields that contains dependencies-like information in a binary
  425. Debian package. The fields that express real dependencies are sorted from
  426. the stronger to the weaker.
  427. =cut
  428. sub field_list_pkg_dep() {
  429. my @keys = keys %FIELDS;
  430. return sort {
  431. $FIELDS{$a}{'dep_order'} <=> $FIELDS{$b}{'dep_order'}
  432. } grep {
  433. field_is_allowed_in($_, CTRL_PKG_DEB) and
  434. exists $FIELDS{$_}{'dependency'}
  435. } @keys;
  436. }
  437. =item field_get_dep_type($field)
  438. Return the type of the dependency expressed by the given field. Can
  439. either be "normal" for a real dependency field (Pre-Depends, Depends, ...)
  440. or "union" for other relation fields sharing the same syntax (Conflicts,
  441. Breaks, ...). Returns undef for fields which are not dependencies.
  442. =cut
  443. sub field_get_dep_type($) {
  444. my $field = field_capitalize($_[0]);
  445. return undef unless field_is_official($field);
  446. return $FIELDS{$field}{'dependency'} if exists $FIELDS{$field}{'dependency'};
  447. return undef;
  448. }
  449. =item field_register($field, $allowed_types, %opts)
  450. Register a new field as being allowed in control information of specified
  451. types. %opts is optional
  452. =cut
  453. sub field_register($$;@) {
  454. my ($field, $types, %opts) = @_;
  455. $field = field_capitalize($field);
  456. $FIELDS{$field} = {
  457. allowed => $types,
  458. %opts
  459. };
  460. }
  461. =item field_insert_after($type, $ref, @fields)
  462. Place field after another one ($ref) in output of control information of
  463. type $type.
  464. =cut
  465. sub field_insert_after($$@) {
  466. my ($type, $field, @fields) = @_;
  467. return 0 if not exists $FIELD_ORDER{$type};
  468. ($field, @fields) = map { field_capitalize($_) } ($field, @fields);
  469. @{$FIELD_ORDER{$type}} = map {
  470. ($_ eq $field) ? ($_, @fields) : $_
  471. } @{$FIELD_ORDER{$type}};
  472. return 1;
  473. }
  474. =item field_insert_before($type, $ref, @fields)
  475. Place field before another one ($ref) in output of control information of
  476. type $type.
  477. =cut
  478. sub field_insert_before($$@) {
  479. my ($type, $field, @fields) = @_;
  480. return 0 if not exists $FIELD_ORDER{$type};
  481. ($field, @fields) = map { field_capitalize($_) } ($field, @fields);
  482. @{$FIELD_ORDER{$type}} = map {
  483. ($_ eq $field) ? (@fields, $_) : $_
  484. } @{$FIELD_ORDER{$type}};
  485. return 1;
  486. }
  487. =back
  488. =head1 AUTHOR
  489. Raphaël Hertzog <hertzog@debian.org>.
  490. =cut
  491. 1;