tar.um
struct File
Struct representing a file in a tar archive.
type File* = struct {
opaque Tar
A tar archive handle
type Tar* = struct{ _: ^struct{} }
fn open
Opens a tar archive at the given path with the given mode.
fn open*(path: str, mode: str): (Tar, std::Err) {
fn openBytes
Opens a tar archive from the given byte array (read only).
fn openBytes*(dat: []uint8): (Tar, std::Err) {
fn close
Closes the given tar archive.
fn (t: ^Tar) close*(): std::Err {
fn getFiles
Returns a list of files in the given tar archive.
fn (t: ^Tar) getFiles*(): ([]File, std::Err) {
fn readBin
Reads the given file from the tar archive as a byte array.
fn (t: ^Tar) read*(path: str): ([]char, std::Err) {
fn extract
Extracts the given tar archive to the given directory.
fn (t: ^Tar) extract*(dir: str): std::Err {
fn addFile
Adds the given file to the tar archive. Directories are not added recursively.
fn (t: ^Tar) addFile*(path: str): Errno {
fn finalize
Finalizes the tar archive.
fn (t: ^Tar) finalize*(): std::Err {
import (
"umbox/os/os.um"
"umbox/filepath/filepath.um"
"std.um"
)
type Errno = enum {
success = 0
failure = -1
openFail = -2
readFail = -3
writeFail = -4
seekFail = -5
badChecksum = -6
nullRecord = -7
notFound = -8
}
fn umc__tar_strerror(err: Errno): str
fn strerror(err: Errno): str {
if int(err) == 0 { return "" }
return umc__tar_strerror(err)
}
fn errFromErrno(e: Errno): std::Err {
return std::error(int(e), strerror(e), "tar.um")
}
//~~struct File
// Struct representing a file in a tar archive.
type File* = struct {
//~~
mode: uint32
owner: uint32
size: uint32
mtime: uint32
filetype: uint32
name: str
linkname: str
}
//~~opaque Tar
// A tar archive handle
type Tar* = struct{ _: ^struct{} }
//~~
fn umc__tar_open(path: str, mode: str, out: ^Tar): Errno
//~~fn open
// Opens a tar archive at the given path with the given mode.
fn open*(path: str, mode: str): (Tar, std::Err) {
//~~
var t: Tar
err := umc__tar_open(path, mode, &t)
return t, errFromErrno(err)
}
fn umc__tar_open_bytes(dat: ^[]uint8, out: ^Tar): Errno
//~~fn openBytes
// Opens a tar archive from the given byte array (read only).
fn openBytes*(dat: []uint8): (Tar, std::Err) {
//~~
var t: Tar
err := umc__tar_open_bytes(&dat, &t)
return t, errFromErrno(err)
}
fn umc__tar_close(tar: ^struct{}): Errno
//~~fn close
// Closes the given tar archive.
fn (t: ^Tar) close*(): std::Err {
//~~
err := umc__tar_close(t._)
return errFromErrno(err)
}
fn umc__tar_get_files(tar: ^struct{}, out: ^[]File, fileArrType: ^void): Errno
//~~fn getFiles
// Returns a list of files in the given tar archive.
fn (t: ^Tar) getFiles*(): ([]File, std::Err) {
//~~
var files: []File
err := umc__tar_get_files(t._, &files, typeptr([]File))
return files, errFromErrno(err)
}
fn umc__tar_read(tar: ^struct{}, path: str, out: ^[]char, bytesArrType: ^void): Errno
//~~fn readBin
// Reads the given file from the tar archive as a byte array.
fn (t: ^Tar) read*(path: str): ([]char, std::Err) {
//~~
var s: []char
err := umc__tar_read(t._, path, &s, typeptr([]char))
return s, errFromErrno(err)
}
//~~fn extract
// Extracts the given tar archive to the given directory.
fn (t: ^Tar) extract*(dir: str): std::Err {
//~~
files, err := t.getFiles()
if (err.code != 0) {
return err
}
os::mkdirp(dir)
for i:=0; i < len(files); i++ {
path := filepath::join(dir, files[i].name)
os::mkdirp(filepath::dir(path))
dat, err := t.read(files[i].name)
if (err.code != 0) {
return err
}
if filepath::file(path) == "@PaxHeader" {
continue
}
f, err := std::fopen(path, "wb")
if err.code != 0 {
return err
}
std::fwrite(f, dat)
std::fclose(f)
os::chmod(path, files[i].mode)
}
return {}
}
fn umc__tar_add_file(t: ^struct{}, path: str): Errno
//~~fn addFile
// Adds the given file to the tar archive. Directories are not added
// recursively.
fn (t: ^Tar) addFile*(path: str): Errno {
//~~
return umc__tar_add_file(t._, path)
}
fn umc__tar_finalize(t: ^struct{}): Errno
//~~fn finalize
// Finalizes the tar archive.
fn (t: ^Tar) finalize*(): std::Err {
//~~
err := umc__tar_finalize(t._)
return errFromErrno(err)
}
fn main() {
var err: std::Err
var tar: Tar
tar, err = open("test.tar", "w")
std::exitif(err)
tar.addFile("box.json")
tar.addFile("microtar/README.md")
tar.addFile("tar_linux.umi")
err = tar.finalize()
std::exitif(err)
err = tar.close()
std::exitif(err)
tar, err = open("test.tar", "r")
std::exitif(err)
var files: []File
files, err = tar.getFiles()
std::exitif(err)
printf("Files in tar file:\n")
for i in files {
printf(" %s\n", files[i].name)
}
printf("Reading box.json:\n")
var umboxJson: []char
umboxJson, err = tar.read("box.json")
std::exitif(err)
printf("%s\n", str(umboxJson))
err = tar.extract("extracted")
std::exitif(err)
err = tar.close()
std::exitif(err)
}