TarWriter Class Reference

#include <Pt/System/TarWriter.h>

Writes a tar archive to a stream. More...

Public Member Functions

 TarWriter ()
 Creates a writer with no stream attached.
 TarWriter (std::ostream &os)
 Creates a writer that appends to os.
 ~TarWriter ()
 Destructor.
void attach (std::ostream &os)
 Attaches os as the destination.
void detach ()
 Detaches the current destination.
void reset ()
 Detaches the destination and clears the writer state.
void addFile (const TarEntry &entry, const char *data, std::size_t size)
 Writes a regular file from a memory buffer.
void addDirectory (const TarEntry &entry)
 Writes a directory member.
void addSymlink (const TarEntry &entry)
 Writes a symbolic link.
void addHardlink (const TarEntry &entry)
 Writes a hard link.
void beginFile (const TarEntry &entry)
 Writes the header of a file whose content follows in chunks.
void writeFile (const char *data, std::size_t size)
 Writes the next content chunk of the open streamed file.
void endFile ()
 Finishes the streamed file opened by beginFile().
void finish ()
 Writes the end-of-archive marker.

Detailed Description

A TarWriter appends archive members to a std::ostream, in order, and blocks on each write. The caller builds a TarEntry for the metadata and passes that entry to the writer. The writer does not invent an owner, a group, or a modification time. Whatever the entry carries is what the archive stores, and whatever the entry leaves unset stays unset.

A complete member is one call. addFile() writes a regular file whose bytes are already in memory. addDirectory() writes a directory. addSymlink() and addHardlink() write a link, and they take the link target, the permissions, the modification time, and the owner and group from the entry, the same fields a file carries. The type flag in the archive comes from the method, so the caller does not have to set TarEntry::type(). The path, the size, and the link target do have to be set, because those are the member's identity.

A file too large to hold in one buffer is written in three steps. beginFile() writes the header and declares TarEntry::size() as the total number of content bytes. writeFile() delivers those bytes in as many chunks as needed. endFile() writes the padding that rounds the member up to a 512-byte block, and it fails if the chunks so far do not add up to the declared size. Starting another member, or calling finish(), while a streamed file is still open fails the same way: the open member has to be closed first.

finish() writes the two zero blocks that mark the end of the archive. A reader treats an archive without that marker as truncated, so finish() belongs before the stream is closed.

Names, ids, sizes, and times that fit in a UStar header are stored there. A path or a link target longer than 99 bytes, a name that is not ASCII, an owner or group name longer than 31 bytes, a numeric id above 07777777, or a size above eleven octal digits is stored in a Pax extended header that precedes the member. The caller does not choose the form. Reading the result back yields the same TarEntry fields either way.

The writer throws Pt::IOError when the stream is missing or a write fails, when writeFile() is asked for more bytes than the header declared, when endFile() is called before those bytes have all been written, and when a new member is started while a streamed file is still open.

std::ofstream out("archive.tar", std::ios::binary);
TarWriter writer(out);
dir.setPath(Path("src"));
writer.addDirectory(dir);
TarEntry file;
file.setPath(Path("src/main.cpp"));
file.setSize(source.size());
file.setMtime(DateTime(2024, 6, 1, 12, 0, 0));
file.setOwnerId(1000);
file.setOwnerName(String("marc"));
writer.addFile(file, source.data(), source.size());
writer.finish();
DateTime()
Default Constructor.
Definition DateTime.h:70
Unicode capable basic_string.
Definition Api-String.h:67
@ OwnerAll
All owner permissions.
Definition FileInfo.h:122
@ OwnerRead
Owner read permission.
Definition FileInfo.h:119
Path()
Default constructor.
One entry in a tar archive.
Definition TarEntry.h:72
void setPath(const Pt::System::Path &path)
Sets the archive path.
Definition TarEntry.h:213
void setPermissions(Pt::System::FileInfo::Perms permissions)
Sets the POSIX permission bits.
Definition TarEntry.h:236
void setOwnerName(const Pt::String &name)
Sets the owner name.
Definition TarEntry.h:256
void setSize(std::size_t size)
Sets the content length declared in the header.
Definition TarEntry.h:221
void setOwnerId(Pt::uint32_t id)
Sets the numeric owner id.
Definition TarEntry.h:248
void setMtime(const Pt::DateTime &mtime)
Sets the modification time in UTC.
Definition TarEntry.h:241
TarWriter()
Creates a writer with no stream attached.

Member Function Documentation

◆ attach()

void attach ( std::ostream & os)

A streamed file that is still open on the previous stream stays open. Call endFile() before detaching if that member should be finished.

◆ reset()

void reset ( )

An open streamed file is abandoned. Its header may already have been written to the previous stream.

◆ addFile()

void addFile ( const TarEntry & entry,
const char * data,
std::size_t size )

size is the number of content bytes taken from data. The header declares TarEntry::size(). For a member that should round-trip, the two lengths are equal.

Parameters
entryMetadata of the file. TarEntry::path() and TarEntry::size() are written into the header.
dataContent bytes. May be null when size is 0.
sizeNumber of bytes to write from data.

◆ addDirectory()

void addDirectory ( const TarEntry & entry)
Parameters
entryMetadata of the directory. TarEntry::path() is the archive path. A trailing slash is added in the archive when the path does not already end with one.

◆ addSymlink()

void addSymlink ( const TarEntry & entry)
Parameters
entryMetadata of the link. TarEntry::linkTarget() is the path the link points at. Permissions, modification time, owner, and group are stored the same way as for a file.

◆ addHardlink()

void addHardlink ( const TarEntry & entry)
Parameters
entryMetadata of the link. TarEntry::linkTarget() is the archive path of the existing member. Permissions, modification time, owner, and group are stored the same way as for a file.

◆ beginFile()

void beginFile ( const TarEntry & entry)

TarEntry::size() is the total number of bytes writeFile() must deliver before endFile(). The header is written immediately, so the size cannot be changed afterwards.

Parameters
entryMetadata of the file, including the total content length.
Exceptions
Pt::IOErrorif a previous streamed file was not closed with endFile().

◆ writeFile()

void writeFile ( const char * data,
std::size_t size )

The sum of every size passed between beginFile() and endFile() must equal TarEntry::size().

Parameters
dataContent bytes. May be null when size is 0.
sizeNumber of bytes to write from data.
Exceptions
Pt::IOErrorif size exceeds the number of bytes still expected for this member.

◆ endFile()

void endFile ( )

Writes the padding that rounds the member up to a 512-byte block.

Exceptions
Pt::IOErrorif writeFile() has not yet delivered every byte declared by TarEntry::size().

◆ finish()

void finish ( )

The marker is two 512-byte blocks of zeros. Call this before closing the stream.

Exceptions
Pt::IOErrorif a streamed file is still open.