Add option to disallow trailing data (closes #11)
3 files changed
tree: 6e6054a8764f432bda7b10fb33f4ef305f769f88
  1. .github/
  2. example/
  3. lib/
  4. reference/
  5. test/
  6. tool/
  7. .gitignore
  8. analysis_options.yaml
  9. CHANGELOG.md
  10. LICENSE
  11. pubspec.yaml
  12. README.md
README.md

tar

Build status

This package provides stream-based readers and writers for tar files.

When working with large tar files, this library consumes considerably less memory than package:archive, although it is slightly slower.

Reading

To read entries from a tar file, use

import 'dart:convert';
import 'dart:io';
import 'package:tar/tar.dart';

Future<void> main() async {
  final reader = TarReader(File('file.tar').openRead());

  while (await reader.moveNext()) {
    final entry = reader.current;
    // Use reader.header to see the header of the current tar entry
    print(entry.header.name);
    // And reader.contents to read the content of the current entry as a stream
    print(await entry.contents.transform(utf8.decoder).first);
  }
  // Note that the reader will automatically close if moveNext() returns false or
  // throws. If you want to close a tar stream before that happens, use
  // reader.cancel();
}

To read .tar.gz files, transform the stream with gzip.decoder before passing it to the TarReader.

To easily go through all entries in a tar file, use TarReader.forEach:

Future<void> main() async {
  final inputStream = File('file.tar').openRead();

  await TarReader.forEach(inputStream, (entry) {
    print(header.name);
    print(await entry.contents.transform(utf8.decoder).first);
  });
}

Warning: Since the reader is backed by a single stream, concurrent calls to read are not allowed! Similarly, if you‘re reading from an entry’s contents, make sure to fully drain the stream before calling read() again.

Writing

You can write tar files into a StreamSink<List<int>>, such as an IOSink:

import 'dart:convert';
import 'dart:io';
import 'package:tar/tar.dart';

Future<void> main() async {
  final output = File('test.tar').openWrite();

  await Stream<TarEntry>.value(
    TarEntry.data(
      TarHeader(
        name: 'hello.txt',
        mode: int.parse('644', radix: 8),
      ),
      utf8.encode('Hello world'),
    ),
  ).pipe(tarWritingSink(output));
}

Note that tar files are always written in the pax format defined by the POSIX.1-2001 specification (--format=posix in GNU tar). When all entries have file names shorter than 100 chars and a size smaller than 8 GB, this is equivalent to the ustar format. This library won't write PAX headers when there is no reason to do so.

To write .tar.gz files, you can again transform the stream twice:

import 'dart:io';
import 'package:tar/tar.dart';

Future<void> write(Stream<TarEntry> entries) {
  return entries
      .transform(tarWriter)
      .transform(gzip.encoder)
      .pipe(File('output.tar.gz').openWrite());
}

Features

  • Supports v7, ustar, pax, gnu and star archives
  • Supports extended pax headers for long file or link names
  • Supports long file and link names generated by GNU-tar
  • Hardened against denial-of-service attacks with invalid tar files

Big thanks to Garett Tok Ern Liang for writing the initial Dart tar reader that this library is based on.