Task 154: .DSC File Format

Task 154: .DSC File Format

.DSC File Format Specifications

The .DSC file format refers to the Debian Source Control file, which is a text-based control file used in Debian and Debian-based distributions (such as Ubuntu) to describe a source package. It follows the deb822 format (similar to RFC 822/2822 for email headers), where fields are key-value pairs separated by a colon, and values can span multiple lines (continuation lines start with whitespace). The file may optionally be wrapped in an OpenPGP ASCII Armored signature. It is not a binary format but a structured text file generated during package building (e.g., via dpkg-source). The format ensures integrity through checksum fields and defines how to build binary packages from source.

1. List of All Properties Intrinsic to This File Format

These are the fields (properties) defined in the .DSC format. Some are required, others optional or recommended. Multiline fields (e.g., Package-List, Files) have their content on subsequent lines indented with a space. The format supports case-insensitive field names but conventionally uses Title-Case.

  • Format (required): Specifies the source package format version (e.g., "3.0 (quilt)").
  • Source (required): The name of the source package.
  • Binary (optional, superseded by Package-List): Comma-separated list of binary packages built from this source.
  • Architecture (recommended): Space-separated list of target architectures or wildcards (e.g., "amd64 arm64 all any").
  • Version (required): The package version string (e.g., "1.0-1").
  • Origin (optional): The distribution origin (e.g., "Debian").
  • Maintainer (recommended): The maintainer's name and email (e.g., "John Doe john@example.com").
  • Uploaders (optional): Comma-separated list of co-maintainers' names and emails.
  • Description (optional): Short description on the first line, followed by a long multiline description (blank lines use " .").
  • Homepage (optional): URL of the upstream project's homepage.
  • Standards-Version (recommended): Version of the Debian Policy complied with (e.g., "4.6.2").
  • Vcs-Browser (optional): URL to browse the VCS repository.
  • Vcs-Arch (optional): URL of the Arch VCS repository.
  • Vcs-Bzr (optional): URL of the Bazaar VCS repository.
  • Vcs-Cvs (optional): URL of the CVS VCS repository.
  • Vcs-Darcs (optional): URL of the Darcs VCS repository.
  • Vcs-Git (optional): URL of the Git VCS repository.
  • Vcs-Hg (optional): URL of the Mercurial VCS repository.
  • Vcs-Mtn (optional): URL of the Monotone VCS repository.
  • Vcs-Svn (optional): URL of the Subversion VCS repository.
  • Testsuite (optional): Comma-separated list of test suite names (e.g., "autopkgtest").
  • Testsuite-Triggers (optional): Comma-separated list of packages triggering tests.
  • Build-Depends (optional): Package list for build dependencies.
  • Build-Depends-Arch (optional): Architecture-specific build dependencies.
  • Build-Depends-Indep (optional): Architecture-independent build dependencies.
  • Build-Conflicts (optional): Package list for build conflicts.
  • Build-Conflicts-Arch (optional): Architecture-specific build conflicts.
  • Build-Conflicts-Indep (optional): Architecture-independent build conflicts.
  • Package-List (optional, multiline): Details of binary packages (one per line: package type section priority arch).
  • Files (required, multiline): MD5 checksum, size, and filename for each source file (one per line).
  • Checksums-Sha1 (optional, multiline): SHA1 checksum, size, and filename for each source file (one per line).
  • Checksums-Sha256 (required, multiline): SHA256 checksum, size, and filename for each source file (one per line).
  • Directory (optional, for some formats like 2.0): Path to the source directory.

3. Ghost Blog Embedded HTML JavaScript for Drag-and-Drop .DSC File Dump

Here's a simple self-contained HTML page with embedded JavaScript. It creates a drag-and-drop area where users can drop a .DSC file. The script reads the file as text, parses the fields (handling multiline values), and dumps them to the screen in a readable format. Save this as an HTML file and open in a browser.

.DSC File Parser

Drag and Drop .DSC File

Drop .DSC file here

4. Python Class for .DSC File Handling

This Python class (DscFile) can open, decode (parse), read, write, and print all properties from a .DSC file. It implements a simple parser for deb822-style fields.

import os

class DscFile:
    def __init__(self, filepath=None):
        self.properties = {}
        if filepath:
            self.read(filepath)

    def read(self, filepath):
        """Read and parse the .DSC file."""
        with open(filepath, 'r') as f:
            content = f.read()
        lines = content.split('\n')
        current_key = None
        for line in lines:
            line = line.strip()
            if line.startswith('-----BEGIN PGP'):  # Skip signature
                break
            if ':' in line and not line[0].isspace():
                key, value = line.split(':', 1)
                key = key.strip()
                value = value.strip()
                current_key = key
                self.properties[current_key] = value
            elif current_key and line:
                self.properties[current_key] += '\n' + line
        print(f"Read {len(self.properties)} properties from {filepath}")

    def print_properties(self):
        """Print all properties to console."""
        for key, value in self.properties.items():
            print(f"{key}: {value}")

    def write(self, filepath):
        """Write properties to a new .DSC file."""
        with open(filepath, 'w') as f:
            for key, value in self.properties.items():
                f.write(f"{key}: {value}\n")
        print(f"Wrote properties to {filepath}")

# Example usage:
# dsc = DscFile('example.dsc')
# dsc.print_properties()
# dsc.write('output.dsc')

5. Java Class for .DSC File Handling

This Java class (DscFile) uses BufferedReader and BufferedWriter to open, parse, read, write, and print properties.

import java.io.*;
import java.util.LinkedHashMap;
import java.util.Map;

public class DscFile {
    private Map<String, String> properties = new LinkedHashMap<>();

    public DscFile(String filepath) throws IOException {
        read(filepath);
    }

    public DscFile() {
    }

    public void read(String filepath) throws IOException {
        properties.clear();
        try (BufferedReader reader = new BufferedReader(new FileReader(filepath))) {
            String line;
            String currentKey = null;
            StringBuilder valueBuilder = new StringBuilder();
            while ((line = reader.readLine()) != null) {
                line = line.trim();
                if (line.startsWith("-----BEGIN PGP")) {  // Skip signature
                    break;
                }
                if (line.matches("^[A-Za-z-]+:.*") && !Character.isWhitespace(line.charAt(0))) {
                    if (currentKey != null) {
                        properties.put(currentKey, valueBuilder.toString().trim());
                    }
                    String[] parts = line.split(":", 2);
                    currentKey = parts[0].trim();
                    valueBuilder = new StringBuilder(parts.length > 1 ? parts[1].trim() : "");
                } else if (currentKey != null && !line.isEmpty()) {
                    valueBuilder.append("\n").append(line);
                }
            }
            if (currentKey != null) {
                properties.put(currentKey, valueBuilder.toString().trim());
            }
        }
        System.out.println("Read " + properties.size() + " properties from " + filepath);
    }

    public void printProperties() {
        for (Map.Entry<String, String> entry : properties.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }
    }

    public void write(String filepath) throws IOException {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(filepath))) {
            for (Map.Entry<String, String> entry : properties.entrySet()) {
                writer.write(entry.getKey() + ": " + entry.getValue() + "\n");
            }
        }
        System.out.println("Wrote properties to " + filepath);
    }

    // Example usage:
    // public static void main(String[] args) throws IOException {
    //     DscFile dsc = new DscFile("example.dsc");
    //     dsc.printProperties();
    //     dsc.write("output.dsc");
    // }
}

6. JavaScript Class for .DSC File Handling

This JavaScript class (DscFile) can be used in Node.js (requires fs module). It parses, reads, writes, and prints properties to console.

const fs = require('fs');

class DscFile {
    constructor(filepath = null) {
        this.properties = {};
        if (filepath) {
            this.read(filepath);
        }
    }

    read(filepath) {
        const content = fs.readFileSync(filepath, 'utf8');
        const lines = content.split('\n');
        let currentKey = null;
        lines.forEach(line => {
            line = line.trim();
            if (line.startsWith('-----BEGIN PGP')) return; // Skip signature
            if (/^[A-Za-z-]+:/.test(line) && !line.startsWith(' ')) {
                const [key, ...valueParts] = line.split(':');
                currentKey = key.trim();
                this.properties[currentKey] = valueParts.join(':').trim();
            } else if (currentKey && line) {
                this.properties[currentKey] += '\n' + line;
            }
        });
        console.log(`Read ${Object.keys(this.properties).length} properties from ${filepath}`);
    }

    printProperties() {
        for (const [key, value] of Object.entries(this.properties)) {
            console.log(`${key}: ${value}`);
        }
    }

    write(filepath) {
        let output = '';
        for (const [key, value] of Object.entries(this.properties)) {
            output += `${key}: ${value}\n`;
        }
        fs.writeFileSync(filepath, output);
        console.log(`Wrote properties to ${filepath}`);
    }
}

// Example usage:
// const dsc = new DscFile('example.dsc');
// dsc.printProperties();
// dsc.write('output.dsc');

7. C++ Class for .DSC File Handling

This C++ class (DscFile) uses <fstream> and <map> to open, parse, read, write, and print properties.

#include <iostream>
#include <fstream>
#include <string>
#include <map>
#include <regex>

class DscFile {
private:
    std::map<std::string, std::string> properties;

public:
    DscFile(const std::string& filepath = "") {
        if (!filepath.empty()) {
            read(filepath);
        }
    }

    void read(const std::string& filepath) {
        properties.clear();
        std::ifstream file(filepath);
        if (!file.is_open()) {
            std::cerr << "Failed to open " << filepath << std::endl;
            return;
        }
        std::string line;
        std::string currentKey;
        std::string value;
        while (std::getline(file, line)) {
            std::string trimmed = line;
            trimmed.erase(0, trimmed.find_first_not_of(" \t"));
            if (trimmed.find("-----BEGIN PGP") == 0) {  // Skip signature
                break;
            }
            std::regex keyRegex("^([A-Za-z-]+):");
            std::smatch match;
            if (std::regex_search(trimmed, match, keyRegex) && match.position() == 0) {
                if (!currentKey.empty()) {
                    properties[currentKey] = value;
                }
                currentKey = match[1].str();
                value = trimmed.substr(match[0].length());
                value.erase(0, value.find_first_not_of(" \t"));
            } else if (!currentKey.empty() && !trimmed.empty()) {
                value += "\n" + trimmed;
            }
        }
        if (!currentKey.empty()) {
            properties[currentKey] = value;
        }
        file.close();
        std::cout << "Read " << properties.size() << " properties from " << filepath << std::endl;
    }

    void printProperties() const {
        for (const auto& pair : properties) {
            std::cout << pair.first << ": " << pair.second << std::endl;
        }
    }

    void write(const std::string& filepath) const {
        std::ofstream file(filepath);
        if (!file.is_open()) {
            std::cerr << "Failed to write to " << filepath << std::endl;
            return;
        }
        for (const auto& pair : properties) {
            file << pair.first << ": " << pair.second << "\n";
        }
        file.close();
        std::cout << "Wrote properties to " << filepath << std::endl;
    }
};

// Example usage:
// int main() {
//     DscFile dsc("example.dsc");
//     dsc.printProperties();
//     dsc.write("output.dsc");
//     return 0;
// }