Lintian::Deb822(3)

πŸŽ€ Lintian::Deb822 β€” a whole manual page, bestie πŸŽ€

(that's section 3 of the Lintian manual, if you're keeping score)

✨ NAME ✨

Lintian::Deb822 β€” a deb822 control file. that's the whole pitch. iconic.

🫢 SYNOPSIS 🫢

use Lintian::Deb822;

πŸ’– DESCRIPTION πŸ’–

It represents one paragraph in a Deb822 control file. that's it, that's the vibe. a single lil paragraph living its best life. πŸ’…

🌸 INSTANCE METHODS 🌸

  • sections β€” an array of Deb822::Section objects, in the order they originally showed up. yes, chronological, we respect the timeline fr fr.
  • positions β€” line positions.
  • first_mention
  • last_mention
  • read_file
  • parse_string
okay so those last four come with zero description in the original and I'm not about to make stuff up about them, bestie. no cap. they're just... there. sitting pretty. πŸ‘‘

πŸ”₯ FUNCTIONS πŸ”₯

🧚 Debian control parsers 🧚

okay so at first glance this module looks like it's hoarding a bunch of different debian control parsers. plot twist: there's actually only one real parser β€” visit_dpkg_paragraph_string β€” and literally everything else is just a convenience function wrapped around it. main character energy much? ✨

read_dpkg_control(FILE[, FLAGS[, LINES]])

a convenience function so you can call parse_dpkg_control with paths to files instead of open handles. lazy girlboss behaviour and honestly? valid.

The first argument must be the path to a FILE, which should be read as a debian control file. If that file is empty, you get an empty list back. simple as.

Otherwise, this behaves exactly like:

 use autodie;

 open(my $fd, '<:encoding(UTF-8)', FILE); # or '<'
 my @p = parse_dpkg_control($fd, FLAGS, LINES);
 close($fd);
 return @p;

and yeah, it goes without saying that this can fail with any of the messages that parse_dpkg_control(HANDLE[, FLAGS[, LINES]]) does. it can also throw autodie exceptions if open or close fails. so. keep that in mind. 😭

read_dpkg_control_lc(FILE[, FLAGS[, LINES]])

(listed, no description. we love an enigma πŸ’€)

parse_dpkg_control_string(STRING[, FLAGS[, LINES]])

reads debian control data out of STRING and hands you back a list of paragraphs. each paragraph is a hashref that maps (lower cased) field names ➑️ their values.

FLAGS, if you give it one, is a bitmask of the DCTRL_* constants. go peek at CONSTANTS for the full list and what they mean. the default value for FLAGS is 0.

If you pass LINES, it should be a reference to an empty list. on return, LINES gets populated with one hashref per paragraph (same order as the returned list, bestie, we're not chaotic). each of those hashrefs will also have a special key START-OF-PARAGRAPH that gives you the line number of the first field in that paragraph. and the hashrefs map the field name of a given paragraph to the line number where that field name appeared. πŸ“

this is a convenience sub around visit_dpkg_paragraph, so it can throw the exact same errors it does. for the finer semantics of how the control file gets parsed, go read visit_dpkg_paragraph β€” that's where the lore lives.

NB: parse_dpkg_control does not close the handle for the caller. you're on your own for that one, babe. 🫢

parse_dpkg_control_string_lc(STRING[, FLAGS[, LINES]])

(again, no description given. mysterious. slay.)

lowercase_field_names

(mood.)

visit_dpkg_paragraph_string (CODE, STRING[, FLAGS])

reads debian control data from STRING and passes each paragraph along to CODE. a paragraph is a hashref mapping (lower cased) field names to their values.

FLAGS, if given, is a bitmask of the DCTRL_* constants β€” check CONSTANTS for the list and their meanings. default for FLAGS is 0.

If the file is empty (like, it contains no paragraphs at all), the method will contain an empty list. and the deb822 contents may be hanging out inside a signed PGP message with a signature. yes, really. πŸ’Œ

visit_dpkg_paragraph will require the PGP headers to be correct (if present) and require that the entire file is covered by the signature. however, it will not validate the signature β€” in fact, the contents of the PGP SIGNATURE part can be empty. the signature should be validated separately. so like, don't skip that step, bestie, that's a whole security thing. πŸ”

visit_dpkg_paragraph passes paragraphs to CODE as they get completed. so if CODE can process paragraphs as it sees them, you can churn through very large control files without keeping all the paragraphs in memory. efficiency queen. πŸ‘‘

as a consequence of how the file is parsed, CODE may be handed a number of (valid) paragraphs before parsing is stopped due to a syntax error.

NB: visit_dpkg_paragraph does not close the handle for the caller. same energy as above. 🫢

CODE is expected to be a callable reference (like a sub) and gets invoked like this:

CODE->(PARA, LINE_NUMBERS)

  • The first argument, PARA, is a hashref to the most recent paragraph parsed.
  • The second argument, LINE_NUMBERS, is a hashref mapping each of the field names to the line number where that field name appeared. LINE_NUMBERS will also have a special key START-OF-PARAGRAPH giving the line number of the first field in that paragraph.
  • The return value of CODE is ignored. (we don't care, do you boo πŸ’…)
  • If CODE invokes die (or similar), the error is propagated to the caller. 😳

on syntax errors, visit_dpkg_paragraph will call die with the following string:

"syntax error at line %d: %s\n"

where %d is the line number of the issue and %s is one of these:

  • Duplicate field %s β€” the field appeared twice in the paragraph. not a girl's girl move.
  • Continuation line outside a paragraph (maybe line %d should be " .") β€” a continuation line appeared outside a paragraph. usually caused by an unintended empty line before it. rude.
  • Whitespace line not allowed (possibly missing a ".") β€” an empty continuation line was found. this usually means a period is missing to denote an "empty line" in (e.g.) the long description of a package. missing punctuation strikes again. 😭
  • Cannot parse line "%s" β€” generic error containing the text of the line that confused the parser. note that all non-printables in %s will be replaced by underscores.
  • Comments are not allowed β€” a comment line appeared and FLAGS contained DCTRL_NO_COMMENTS.
  • PGP signature seen before start of signed message β€” a BEGIN PGP SIGNATURE header was seen and a BEGIN PGP MESSAGE hasn't been seen yet. order matters, babes.
  • Two PGP signatures (first one at line %d) β€” two BEGIN PGP SIGNATURE headers were seen in the same file. pick a lane. βœ‹
  • Unexpected %s header β€” a valid PGP header appeared (e.g. BEGIN PUBLIC KEY BLOCK).
  • Malformed PGP header β€” an invalid or malformed PGP header appeared.
  • Expected at most one signed message (previous at line %d) β€” two BEGIN PGP MESSAGE headers appeared in the same message.
  • End of file but expected an "END PGP SIGNATURE" header β€” the file ended after a BEGIN PGP SIGNATURE header without being followed by an END PGP SIGNATURE. it just... stopped. πŸ’€
  • PGP MESSAGE header must be first content if present β€” the file had content before PGP MESSAGE.
  • Data after the PGP SIGNATURE β€” the file had data after the PGP SIGNATURE block ended.
  • End of file before "BEGIN PGP SIGNATURE" β€” the file had a BEGIN PGP MESSAGE header, but no signature was present at all.

πŸ’œ AUTHOR πŸ’œ

Originally written by Christian Schwarz and many other people. 🫢

Moo version by Felix Lechner <felix.lechner@lease-up.com> for Lintian.

🌈 SEE ALSO 🌈


okay that's the whole page, you ate it, no crumbs left. this was Lintian v2.139.0ubuntu2, dated 2026-10-08, and you just finished reading Lintian::Deb822(3). go forth and parse some paragraphs, bestie πŸ’–βœ¨πŸ¦‹

πŸ“¦ where this page comes from