import 'dart:typed_data'; import 'archive.dart'; import 'archive_file.dart'; import 'tar/tar_file.dart'; import 'util/output_stream.dart'; /// Encode an [Archive] object into a tar formatted buffer. class TarEncoder { List encode(Archive archive, {OutputStreamBase? output}) { final outputStream = output ?? OutputStream(); start(outputStream); for (final file in archive.files) { add(file); } finish(); if (outputStream is OutputStream) { return outputStream.getBytes(); } return []; } void start([dynamic outputStream]) { _outputStream = outputStream ?? OutputStream(); } void add(ArchiveFile file) { if (_outputStream == null) { return; } // GNU tar files store extra long file names in a separate file if (file.name.length > 100) { final ts = TarFile(); ts.filename = '././@LongLink'; ts.fileSize = file.name.length; ts.mode = 0; ts.ownerId = 0; ts.groupId = 0; ts.lastModTime = 0; ts.content = file.name.codeUnits; ts.write(_outputStream); } final ts = TarFile(); ts.filename = file.name; ts.fileSize = file.size; ts.mode = file.mode; ts.ownerId = file.ownerId; ts.groupId = file.groupId; ts.lastModTime = file.lastModTime; ts.content = file.content; if (file.isSymbolicLink) { ts.typeFlag = TarFile.TYPE_SYMBOLIC_LINK; ts.nameOfLinkedFile = file.nameOfLinkedFile; } else if (!file.isFile) { ts.typeFlag = TarFile.TYPE_DIRECTORY; } ts.write(_outputStream); } void finish() { if (_outputStream == null) { return; } // At the end of the archive file there are two 512-byte blocks filled // with binary zeros as an end-of-file marker. final eof = Uint8List(1024); _outputStream.writeBytes(eof); _outputStream.flush(); _outputStream = null; } dynamic _outputStream; }