Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 17 additions & 7 deletions cmd/go7z/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,15 @@ func main() {
args := os.Args[1:]

if len(args) < 1 {
log.Printf("Usage: go7z ARCHIVE")
log.Printf("Usage: go7z ARCHIVE [PASSWORD]")
os.Exit(1)
}

password := ""
if len(args) >= 2 {
password = args[1]
}

inPath := args[0]
ext := filepath.Ext(inPath)
if ext != "" {
Expand All @@ -52,14 +57,14 @@ func main() {

is.Stats = &sz.ReadStats{}

a, err := lib.OpenArchive(is, false)
a, err := lib.OpenArchiveEx(is, password, false)
if err != nil {
log.Printf("Could not open archive by ext, trying by signature")

_, err = is.Seek(0, io.SeekStart)
must(err)

a, err = lib.OpenArchive(is, true)
a, err = lib.OpenArchiveEx(is, password, true)
}
must(err)

Expand All @@ -78,10 +83,11 @@ func main() {
indices[i] = int64(i)
}
middle := itemCount / 2

log.Printf("Doing first half...")
err = a.ExtractSeveral(indices[0:middle], ec)
must(err)
if middle > 0 {
log.Printf("Doing first half...")
err = a.ExtractSeveral(indices[0:middle], ec)
must(err)
}

for i := 0; i < 15; i++ {
is.Stats.RecordRead(0, 0)
Expand Down Expand Up @@ -187,6 +193,10 @@ func (e *ecs) GetStream(item *sz.Item) (*sz.OutStream, error) {
log.Printf("==> Symlink dest: %s", symlink)
}

if modTime, ok := item.GetFileTimeProperty(sz.PidMTime); ok {
log.Printf("==> Modify Time: %s", modTime.String())
}

isDir, _ := item.GetBoolProperty(sz.PidIsDir)
if isDir {
log.Printf("Making %s", outPath)
Expand Down
219 changes: 219 additions & 0 deletions cmd/go7z_multi/main2.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
package main

import (
"log"
"os"
"path/filepath"
"strings"

"github.com/itchio/headway/united"
"github.com/itchio/sevenzip-go/sz"
"github.com/pkg/errors"
)

type ecs struct {
// muffin
}

type mcs struct {
FirstName string
CurVolName string
f *os.File
}

//2022/07/28 03:45:46 mcs GetFirstVolumeName()
//2022/07/28 03:45:46 mcs MoveToVolume(test-magic.7z.001)
//2022/07/28 03:45:46 mcs MoveToVolume(test-magic.7z.001)
//2022/07/28 03:45:46 mcs OpenCurrentVolumeStream()
//2022/07/28 03:45:46 mcs GetCurrentVolumeSize()
//2022/07/28 03:45:46 mcs GetFirstVolumeName()
//2022/07/28 03:45:46 mcs MoveToVolume(test-magic.7z.001)
//2022/07/28 03:45:46 mcs MoveToVolume(test-magic.7z.002)
//2022/07/28 03:45:46 mcs OpenCurrentVolumeStream()
//2022/07/28 03:45:46 mcs GetCurrentVolumeSize()
//2022/07/28 03:45:46 mcs MoveToVolume(test-magic.7z.003)
//2022/07/28 03:45:46 mcs OpenCurrentVolumeStream()
//2022/07/28 03:45:46 mcs GetCurrentVolumeSize()
//2022/07/28 03:45:46 mcs MoveToVolume(test-magic.7z.004)

func (m *mcs) GetFirstVolumeName() string {
log.Printf("mcs GetFirstVolumeName()")
m.MoveToVolume(m.FirstName)
return m.FirstName
}

func (m *mcs) MoveToVolume(volumeName string) error {
log.Printf("mcs MoveToVolume(%s)", volumeName)
var err error
m.f.Close()
m.f, err = os.OpenFile(volumeName, os.O_RDONLY, 0)
if err != nil {
log.Printf("mcs MoveToVolume(%s), error: %v", volumeName, err)
return err
}
m.CurVolName = volumeName
return nil
}

func (m *mcs) GetCurrentVolumeSize() uint64 {
log.Printf("mcs GetCurrentVolumeSize()")
info, err := m.f.Stat()
if err != nil {
return 0
}
return uint64(info.Size())
}

func (m *mcs) OpenCurrentVolumeStream() (*sz.InStream, error) {
log.Printf("mcs OpenCurrentVolumeStream()")
ext := filepath.Ext(m.CurVolName)
if ext != "" {
ext = ext[1:]
}

f, err := os.OpenFile(m.CurVolName, os.O_RDONLY, 0)
if err != nil {
return nil, err
}
return sz.NewInStream(f, ext, int64(m.GetCurrentVolumeSize()))
}

func main() {
lib, err := sz.NewLib()
must(err)
log.Printf("Initialized 7-zip %s...", lib.GetVersion())
defer lib.Free()

args := os.Args[1:]

if len(args) < 1 {
log.Printf("Usage: go7z_multi FIRST_ARCHIVE [PASSWORD]")
os.Exit(1)
}

password := ""
if len(args) >= 2 {
password = args[1]
}

inPath := args[0]
ext := filepath.Ext(inPath)
if ext != "" {
ext = ext[1:]
}
log.Printf("ext = %s", ext)

f, err := os.Open(inPath)
must(err)

f.Close()

//is, err := sz.NewInStream(f, ext, stats.Size())
//must(err)
//log.Printf("Created input stream (%s, %d bytes)...", inPath, stats.Size())
//
//is.Stats = &sz.ReadStats{}
s, err := sz.NewMultiVolumeCallback(&mcs{FirstName: inPath})
log.Printf("Created input stream (%s, %d bytes)...", inPath)

a, err := lib.OpenMultiVolumeArchive(s, password, false)
must(err)

log.Printf("Opened archive: format is (%s)", a.GetArchiveFormat())

itemCount, err := a.GetItemCount()
must(err)
log.Printf("Archive has %d items", itemCount)

ec, err := sz.NewExtractCallback(&ecs{})
must(err)
defer ec.Free()

var indices = make([]int64, itemCount)
for i := 0; i < int(itemCount); i++ {
indices[i] = int64(i)
}

err = a.ExtractSeveral(indices, ec)
must(err)

errs := ec.Errors()
if len(errs) > 0 {
log.Printf("There were %d errors during extraction:", len(errs))
for _, err := range errs {
log.Printf("- %s", err.Error())
}
}
}

func must(err error) {
if err != nil {
log.Panic(err)
}
}

func (e *ecs) GetStream(item *sz.Item) (*sz.OutStream, error) {
propPath, ok := item.GetStringProperty(sz.PidPath)
if !ok {
return nil, errors.New("could not get item path")
}

outPath := filepath.ToSlash(propPath)
// Remove illegal character for windows paths, see
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx
for i := byte(0); i <= 31; i++ {
outPath = strings.Replace(outPath, string([]byte{i}), "_", -1)
}

absoluteOutPath := filepath.Join("out", outPath)

log.Printf(" ")
log.Printf("==> Extracting %d: %s", item.GetArchiveIndex(), outPath)

if attrib, ok := item.GetUInt64Property(sz.PidAttrib); ok {
log.Printf("==> Attrib %08x", attrib)
}
if attrib, ok := item.GetUInt64Property(sz.PidPosixAttrib); ok {
log.Printf("==> Posix Attrib %08x", attrib)
}
if symlink, ok := item.GetStringProperty(sz.PidSymLink); ok {
log.Printf("==> Symlink dest: %s", symlink)
}

isDir, _ := item.GetBoolProperty(sz.PidIsDir)
if isDir {
log.Printf("Making %s", outPath)

err := os.MkdirAll(absoluteOutPath, 0755)
if err != nil {
return nil, errors.WithStack(err)
}

// is a dir, just skip it
return nil, nil
}

err := os.MkdirAll(filepath.Dir(absoluteOutPath), 0755)
if err != nil {
return nil, errors.WithStack(err)
}

of, err := os.Create(absoluteOutPath)
if err != nil {
return nil, errors.WithStack(err)
}

os, err := sz.NewOutStream(of)
if err != nil {
return nil, errors.WithStack(err)
}

return os, nil
}

func (e *ecs) SetProgress(complete int64, total int64) {
log.Printf("Progress: %s / %s",
united.FormatBytes(complete),
united.FormatBytes(total),
)
}
51 changes: 51 additions & 0 deletions sz/glue.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@ int libc7zip_initialize(char *lib_path) {
LOADSYM(out_stream_free)

LOADSYM(archive_open)
LOADSYM(archive_open_ex)

LOADSYM(multivolume_callback_new)
LOADSYM(multivolume_callback_get_def)
LOADSYM(multivolume_callback_free)

LOADSYM(archive_multiopen)

LOADSYM(archive_close)
LOADSYM(archive_free)
LOADSYM(archive_get_archive_format)
Expand All @@ -63,6 +71,7 @@ int libc7zip_initialize(char *lib_path) {
LOADSYM(string_free)
LOADSYM(item_get_uint64_property)
LOADSYM(item_get_bool_property)
LOADSYM(item_get_filetime_property)
LOADSYM(item_free)

LOADSYM(archive_extract_item)
Expand Down Expand Up @@ -129,6 +138,14 @@ archive *libc7zip_archive_open(lib *l, in_stream *is, int32_t by_signature) {
return archive_open_(l, is, by_signature);
}

archive *libc7zip_archive_open_ex(lib *l, in_stream *is, const char *password, int32_t by_signature) {
return archive_open_ex_(l, is, password, by_signature);
}

archive *libc7zip_archive_multiopen(lib *l, multivolume_callback *mc, const char *password, int32_t by_signature) {
return archive_multiopen_(l, mc, password, by_signature);
}

void libc7zip_archive_close(archive *a) {
return archive_close_(a);
}
Expand Down Expand Up @@ -169,6 +186,10 @@ int32_t libc7zip_item_get_bool_property(item *i, int32_t property_index, int32_t
return item_get_bool_property_(i, property_index, success);
}

uint64_t libc7zip_item_get_filetime_property(item *i, int32_t property_index, int32_t *success) {
return item_get_filetime_property_(i, property_index, success);
}

void libc7zip_item_free(item *i) {
return item_free_(i);
}
Expand All @@ -195,6 +216,20 @@ void libc7zip_extract_callback_free(extract_callback *ec) {
extract_callback_free_(ec);
}

//-----------------

multivolume_callback *libc7zip_multivolume_callback_new() {
return multivolume_callback_new_();
}

multivolume_callback_def *libc7zip_multivolume_callback_get_def(multivolume_callback *mc) {
return multivolume_callback_get_def_(mc);
}

void libc7zip_multivolume_callback_free(multivolume_callback *mc) {
multivolume_callback_free_(mc);
}

// Gateway functions

int inSeekGo_cgo(int64_t id, int64_t offset, int32_t whence, int64_t *new_position) {
Expand Down Expand Up @@ -225,3 +260,19 @@ void ecSetOperationResultGo_cgo(int64_t id, int32_t result) {
ecSetOperationResultGo(id, result);
}

char *mcGetFirstVolumeNameGo_cgo(int64_t id) {
return mcGetFirstVolumeNameGo(id);
}

int32_t mcMoveToVolumeGo_cgo(int64_t id, char *volumeName) {
return mcMoveToVolumeGo(id, volumeName);
}

uint64_t mcGetCurrentVolumeSizeGo_cgo(int64_t id) {
return mcGetCurrentVolumeSizeGo(id);
}

in_stream *mcOpenCurrentVolumeStreamGo_cgo(int64_t id) {
return mcOpenCurrentVolumeStreamGo(id);
}

Loading