void CreateTarball()

in Shared/Io/Tar.cpp [153:318]


    void CreateTarball(
        _In_ Windows::Storage::StorageFolder^ sourceFolder,
        _In_ const std::vector<std::wstring>& sourceFileNames,
        _In_ Windows::Storage::StorageFolder^ tarballFolder,
        _In_ const std::wstring& tarballFileName)
    {
        Microsoft::WRL::ComPtr<IStorageFolderHandleAccess> tarballFolderHandleAccess =
            GetStorageFolderHandleAccess(
                tarballFolder);

        HANDLE output = nullptr;

        ASSERT_SUCCEEDED(tarballFolderHandleAccess->Create(
            tarballFileName.c_str() /* fileName */,
            HCO_CREATE_ALWAYS /* creationOptions */,
            HAO_WRITE /* accessOptions */,
            HSO_SHARE_NONE /* sharingOptions */,
            HO_NONE /* options */,
            nullptr /* oplockBreakingHandler */,
            &output));

        std::vector<uint8_t> alignmentBuffer(512);
        std::vector<uint8_t> sourceFileBuffer;

        std::fill(
            alignmentBuffer.begin(),
            alignmentBuffer.end(),
            static_cast<uint8_t>(0) /* _Val */);

        DWORD numberOfBytesWritten = 0;
        DWORD numberOfBytesRead = 0;

        Microsoft::WRL::ComPtr<IStorageFolderHandleAccess> sourceFolderHandleAccess =
            GetStorageFolderHandleAccess(
                sourceFolder);

        for (const auto& sourceFileName : sourceFileNames)
        {
            HANDLE input = nullptr;

            ASSERT_SUCCEEDED(sourceFolderHandleAccess->Create(
                sourceFileName.c_str() /* fileName */,
                HCO_OPEN_EXISTING /* creationOptions */,
                HAO_READ /* accessOptions */,
                HSO_SHARE_READ /* sharingOptions */,
                HO_NONE /* options */,
                nullptr /* oplockBreakingHandler */,
                &input));

            LARGE_INTEGER fileSize = {};

            ASSERT(!!GetFileSizeEx(
                input,
                &fileSize));

            FILETIME lastWriteTime = {};

            ASSERT(!!GetFileTime(
                input,
                nullptr /* lpCreationTime */,
                nullptr /* lpLastAccessTime */,
                &lastWriteTime));

            sourceFileBuffer.resize(
                static_cast<size_t>(fileSize.QuadPart));

            ASSERT(!!ReadFile(
                input,
                &sourceFileBuffer[0],
                static_cast<DWORD>(sourceFileBuffer.size()),
                &numberOfBytesRead,
                nullptr /* lpOverlapped */));

            ASSERT(sourceFileBuffer.size() == numberOfBytesRead);

            TarHeader header;

            static_assert(
                512 == sizeof(TarHeader),
                "Size of the TarHeader structure must be equal to 512 bytes.");

            CopyStringToTarHeader<100>(
                Utf16ToUtf8(sourceFileName),
                header.FileName);

            CopyUInt64ToTarHeaderAsOctets<12>(
                static_cast<size_t>(fileSize.QuadPart),
                header.FileSize);

            CopyUInt64ToTarHeaderAsOctets<12>(
                std::chrono::duration_cast<std::chrono::seconds>(
                    UniversalToUnixTime(lastWriteTime)).count(),
                header.LastModificationTime);

            uint64_t checksum = 0;

            for (size_t i = 0; i < sizeof(header); ++i)
            {
                checksum +=
                    reinterpret_cast<uint8_t*>(&header)[i];
            }

            CopyUInt64ToTarHeaderAsOctets<7>(
                checksum,
                header.Checksum);

            ASSERT(!!WriteFile(
                output,
                &header,
                sizeof(header),
                &numberOfBytesWritten,
                nullptr /* lpOverlapped */));

            ASSERT(sizeof(header) == numberOfBytesWritten);

            ASSERT(!!WriteFile(
                output,
                &sourceFileBuffer[0],
                static_cast<DWORD>(fileSize.QuadPart),
                &numberOfBytesWritten,
                nullptr /* lpOverlapped */));

            ASSERT(fileSize.QuadPart == numberOfBytesWritten);

            const size_t lastBlockSize =
                fileSize.QuadPart % alignmentBuffer.size();

            if (0 != lastBlockSize)
            {
                const size_t lastBlockPadding =
                    alignmentBuffer.size() - lastBlockSize;

                ASSERT(lastBlockPadding < alignmentBuffer.size());

                ASSERT(!!WriteFile(
                    output,
                    &alignmentBuffer[0],
                    static_cast<DWORD>(lastBlockPadding),
                    &numberOfBytesWritten,
                    nullptr /* lpOverlapped */));

                ASSERT(lastBlockPadding == numberOfBytesWritten);
            }

            ASSERT(!!CloseHandle(
                input));
        }

        //
        // The TAR file ends with two blocks of zeroes:
        //
        for (size_t terminatorBlock = 0; terminatorBlock < 2; ++terminatorBlock)
        {
            ASSERT(!!WriteFile(
                output,
                &alignmentBuffer[0],
                static_cast<DWORD>(alignmentBuffer.size()),
                &numberOfBytesWritten,
                nullptr /* lpOverlapped */));

            ASSERT(alignmentBuffer.size() == numberOfBytesWritten);
        }

        ASSERT(!!CloseHandle(
            output));
    }