Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
robert-ancell committed Jul 20, 2021
0 parents commit 533d530
Show file tree
Hide file tree
Showing 10 changed files with 591 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.dart_tool/
.packages
pubspec.lock
8 changes: 8 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# gsettings.dart Contribution Guide

If you have a problem, please [file an issue](https://github.com/canonical/gsettings.dart/issues/new).

If you have a solution, then we accept contributions via [pull requests](https://github.com/canonical/gsettings.dart/pulls).
All contributions require the author(s) to sign the [contributor license agreement](http://www.ubuntu.com/legal/contributors/).

Thanks for your help!
373 changes: 373 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[![Pub Package](https://img.shields.io/pub/v/dpkg.svg)](https://pub.dev/packages/dpkg)

Provides classes to extract Debian packages.

```dart
import 'package:dpkg/dpkg.dart';
void main() async {
}
```

## Contributing to dpkg.dart

We welcome contributions! See the [contribution guide](CONTRIBUTING.md) for more details.
1 change: 1 addition & 0 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
include: package:pedantic/analysis_options.yaml
1 change: 1 addition & 0 deletions lib/dpkg.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export 'src/deb_file.dart';
144 changes: 144 additions & 0 deletions lib/src/ar_archive.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';

/// An object used for accessing Ar format archives.
class ArArchive {
final String _path;
RandomAccessFile? _file;
List<ArFile>? _headers;
bool _signatureChecked = false;
bool _signatureIsValid = false;

/// Creates an object access an Ar achive at [path].
ArArchive(String path) : _path = path;

/// Gets the files present in this archive.
Future<List<ArFile>> getFiles() async {
if (_headers == null) {
_headers = await _readFileHeaders();
}

return _headers!;
}

/// Close the archive.
Future<void> close() async {
if (_file != null) {
await _file!.close();
}
}

// Reads [length] bytes from [offset].
Future<Uint8List> _read(int offset, int length) async {
if (_file == null) {
_file = await File(_path).open();
}
await _file!.setPosition(offset);
return _file!.read(length);
}

// Checks if the archive file has the correct signature.
Future<bool> _checkSignature() async {
if (_signatureChecked) {
return _signatureIsValid;
}
_signatureChecked = true;

var data = await _read(0, 8);
_signatureIsValid = data == ascii.encode('!<arch>\n');

return _signatureIsValid;
}

// Reads all the file headers from the archive.
Future<List<ArFile>> _readFileHeaders() async {
await _checkSignature();
var offset = 8;
var headers = <ArFile>[];
while (true) {
var header = await _readFileHeader(offset);
if (header == null) {
return headers;
}
headers.add(header);
offset += 60 + header.size;

// Align to 2 byte boundaries.
if (offset % 2 != 0) {
offset++;
}
}
}

// Reads a single file header from [offset].
Future<ArFile?> _readFileHeader(int offset) async {
var data = await _read(offset, 60);
if (data.isEmpty) {
return null;
}
if (data.length != 60) {
throw 'Invalid Ar header length';
}
var identifier = _getField(data, 0, 16);
var modificationTimestamp = int.parse(_getField(data, 16, 12));
var ownerId = int.parse(_getField(data, 28, 6));
var groupId = int.parse(_getField(data, 34, 6));
var mode = int.parse(_getField(data, 40, 8), radix: 8);
var size = int.parse(_getField(data, 48, 10));

if (data[58] != 0x60 && data[59] != 0x0a) {
throw 'Invalid Ar trailer';
}
return ArFile(
identifier: identifier,
modificationTimestamp: modificationTimestamp,
ownerId: ownerId,
groupId: groupId,
mode: mode,
offset: offset + 60,
size: size);
}

// Decodes a ascii encoded field.
String _getField(Uint8List data, int offset, int length) {
return ascii.decode(data.sublist(offset, offset + length)).trimRight();
}
}

/// Represents a file in an Ar archive.
class ArFile {
/// Identifier
final String identifier;

/// Unix timestamp file for when file was last modified.
final int modificationTimestamp;

/// Owner user ID of this file.
final int ownerId;

/// Group ID for this file.
final int groupId;

/// Unix file type and permissions.
final int mode;

/// Offset inside the archive in bytes.
final int offset;

// Size of the file in bytes.
final int size;

ArFile(
{required this.identifier,
required this.modificationTimestamp,
required this.ownerId,
required this.groupId,
required this.mode,
required this.offset,
required this.size});

@override
String toString() =>
"ArFile(identifier: '$identifier', modificationTimestamp: $modificationTimestamp, ownerId: $ownerId, groupId: $groupId, mode: $mode, offset: $offset, size: $size)";
}
27 changes: 27 additions & 0 deletions lib/src/deb_file.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import 'ar_archive.dart';

class DebFile {
// The archive that is the .deb file.
final ArArchive _archive;

DebFile(String path) : _archive = ArArchive(path);

Future<DebControl> getControl() async {
var files = await _archive.getFiles();

for (var file in files) {
if (file.identifier == 'control.tar.gz' || file.identifier == 'control.tar.xz') {
return DebControl();
}
}

throw 'Missing Debian control information';
}

/// Close the deb file.
Future<void> close() async {
await _archive.close();
}
}

class DebControl {}
14 changes: 14 additions & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
name: dpkg
version: 0.0.1

description:
Debian Package library

homepage: https://github.com/canonical/dpkg.dart

environment:
sdk: '>=2.12.0 <3.0.0'

dev_dependencies:
pedantic: ^1.9.0
test: ^1.16.8
6 changes: 6 additions & 0 deletions test/dpkg_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import 'package:dpkg/dpkg.dart';
import 'package:test/test.dart';

void main() {
test('FIXME', () async {});
}

0 comments on commit 533d530

Please sign in to comment.