decodeBuffer method

Archive decodeBuffer(
  1. InputStreamBase input, {
  2. bool verify = false,
  3. bool storeData = true,
})

Implementation

Archive decodeBuffer(InputStreamBase input,
    {bool verify = false, bool storeData = true}) {
  final archive = Archive();
  files.clear();

  String? nextName;
  String? nextLinkName;

  // TarFile paxHeader = null;
  while (!input.isEOS) {
    // End of archive when two consecutive 0's are found.
    final endCheck = input.peekBytes(2).toUint8List();
    if (endCheck.length < 2 || (endCheck[0] == 0 && endCheck[1] == 0)) {
      break;
    }

    final tf = TarFile.read(input, storeData: storeData);
    // GNU tar puts filenames in files when they exceed tar's native length.
    if (tf.filename == '././@LongLink') {
      nextName = tf.rawContent!.readString();
      continue;
    }

    // In POSIX formatted tar files, a separate 'PAX' file contains extended
    // metadata for files. These are identified by having a type flag 'X'.
    // TODO: parse these metadata values.
    if (tf.typeFlag == TarFile.TYPE_G_EX_HEADER ||
        tf.typeFlag == TarFile.TYPE_G_EX_HEADER2) {
      // TODO handle PAX global header.
      continue;
    }
    if (tf.typeFlag == TarFile.TYPE_EX_HEADER ||
        tf.typeFlag == TarFile.TYPE_EX_HEADER2) {
      utf8
          .decode(tf.rawContent!.toUint8List())
          .split('\n')
          .where((s) => paxRecordRegexp.hasMatch(s))
          .forEach((record) {
        var match = paxRecordRegexp.firstMatch(record)!;
        var keyword = match.group(2);
        var value = match.group(3)!;
        switch (keyword) {
          case 'path':
            nextName = value;
            break;
          case 'linkpath':
            nextLinkName = value;
            break;
          default:
          // TODO: support other pax headers.
        }
      });
      continue;
    }

    // Fix file attributes.
    if (nextName != null) {
      tf.filename = nextName!;
      nextName = null;
    }
    if (nextLinkName != null) {
      tf.nameOfLinkedFile = nextLinkName!;
      nextLinkName = null;
    }
    files.add(tf);

    final file = ArchiveFile(tf.filename, tf.fileSize, tf.rawContent);

    file.mode = tf.mode;
    file.ownerId = tf.ownerId;
    file.groupId = tf.groupId;
    file.lastModTime = tf.lastModTime;
    file.isFile = tf.isFile;
    file.isSymbolicLink = tf.typeFlag == TarFile.TYPE_SYMBOLIC_LINK;

    if (tf.nameOfLinkedFile != null) {
      file.nameOfLinkedFile = tf.nameOfLinkedFile!;
    }

    archive.addFile(file);
  }

  return archive;
}