Skip to content

Commit

Permalink
First commit
Browse files Browse the repository at this point in the history
  • Loading branch information
tizbac committed Dec 2, 2023
0 parents commit c91b9a4
Show file tree
Hide file tree
Showing 2 changed files with 273 additions and 0 deletions.
8 changes: 8 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module proxmoxbackupgo

go 1.19

require (
github.com/dchest/siphash v1.2.3 // indirect
github.com/silvasur/buzhash v0.0.0-20160816060738-9bdec3dec7c6 // indirect
)
265 changes: 265 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,265 @@
package main

import (
"bytes"
"encoding/binary"
"os"
"fmt"
// "github.com/silvasur/buzhash"
// "io/ioutil"
"path/filepath"
"github.com/dchest/siphash"
)



const (
PXAR_ENTRY uint64 = 0xd5956474e588acef
PXAR_ENTRY_V1 uint64 = 0x11da850a1c1cceff
PXAR_FILENAME uint64 = 0x16701121063917b3
PXAR_SYMLINK uint64 = 0x27f971e7dbf5dc5f
PXAR_DEVICE uint64 = 0x9fc9e906586d5ce9
PXAR_XATTR uint64 = 0x0dab0229b57dcd03
PXAR_ACL_USER uint64 = 0x2ce8540a457d55b8
PXAR_ACL_GROUP uint64 = 0x136e3eceb04c03ab
PXAR_ACL_GROUP_OBJ uint64 = 0x10868031e9582876
PXAR_ACL_DEFAULT uint64 = 0xbbbb13415a6896f5
PXAR_ACL_DEFAULT_USER uint64 = 0xc89357b40532cd1f
PXAR_ACL_DEFAULT_GROUP uint64 = 0xf90a8a5816038ffe
PXAR_FCAPS uint64 = 0x2da9dd9db5f7fb67
PXAR_QUOTA_PROJID uint64 = 0xe07540e82f7d1cbb
PXAR_HARDLINK uint64 = 0x51269c8422bd7275
PXAR_PAYLOAD uint64 = 0x28147a1b0b7c1a25
PXAR_GOODBYE uint64 = 0x2fec4fa642d5731d
PXAR_GOODBYE_TAIL_MARKER uint64 = 0xef5eed5b753e1555
)

const (
IFMT uint64 = 0o0170000
IFSOCK uint64 = 0o0140000
IFLNK uint64 = 0o0120000
IFREG uint64 = 0o0100000
IFBLK uint64 = 0o0060000
IFDIR uint64 = 0o0040000
IFCHR uint64 = 0o0020000
IFIFO uint64 = 0o0010000

ISUID uint64 = 0o0004000
ISGID uint64 = 0o0002000
ISVTX uint64 = 0o0001000
)
type MTime struct {
secs uint64
nanos uint32
padding uint32

}
type PXARFileEntry struct {
hdr uint64
len uint64
mode uint64
flags uint64
uid uint32
gid uint32
mtime MTime
}

type PXARFilenameEntry struct {
hdr uint64
len uint64

}

type GoodByeItem struct {
hash uint64
offset uint64
len uint64
}

type PXAROutCB func([]byte)

type PXARArchive struct {
//Create(filename string, writeCB PXAROutCB)
//AddFile(filename string)
//AddDirectory(dirname string)
writeCB PXAROutCB
buffer bytes.Buffer
pos uint64
}

func (a *PXARArchive) Flush() {
b := make([]byte, 64*1024);
count, _ := a.buffer.Read(b)
a.writeCB(b[:count])
a.pos = a.pos + uint64(count)
fmt.Printf("Flush %d bytes\n", count)
}

func (a *PXARArchive) Create() {
a.pos = 0

}

func (a *PXARArchive) WriteDir(path string, dirname string, toplevel bool){
fmt.Printf("Write dir %s at %d\n", path, a.pos)
files, err := os.ReadDir(path)
if err != nil {
return
}

fileInfo, err := os.Stat(path)
if err != nil {
fmt.Printf("Failed to stat %s\n", path)
return
}

if (!toplevel) {
fname_entry := &PXARFilenameEntry{
hdr: PXAR_FILENAME,
len: uint64(16)+uint64(len(dirname))+1,
}

binary.Write(&a.buffer, binary.LittleEndian, fname_entry)

a.buffer.WriteString(dirname)
a.buffer.WriteByte(0x00)
}

entry := &PXARFileEntry{
hdr: PXAR_ENTRY,
len: 56,
mode: IFDIR | 0o777,
flags: 0,
uid: 1000,
gid: 1000,
mtime: MTime{
secs: uint64(fileInfo.ModTime().Unix()),
nanos: 0,
padding: 0,
},
}
binary.Write(&a.buffer, binary.LittleEndian, entry)

posmap := make(map[string]uint64)
lenmap := make(map[string]uint64)
for _ , file := range files {
if file.IsDir() {
posmap[file.Name()] = a.pos
a.WriteDir(filepath.Join(path, file.Name()), file.Name(), false)
lenmap[file.Name()] = a.pos-posmap[file.Name()]
}else{
posmap[file.Name()] = a.pos
a.WriteFile(filepath.Join(path, file.Name()), file.Name())
lenmap[file.Name()] = a.pos-posmap[file.Name()]
}
}

binary.Write(&a.buffer, binary.LittleEndian, PXAR_GOODBYE)
goodbyelen := uint64(16 + 24*(len(posmap)+1))
binary.Write(&a.buffer, binary.LittleEndian, goodbyelen)

for filename, pos := range posmap {
gi := &GoodByeItem{
offset: a.pos-pos,
len: lenmap[filename],
hash: siphash.Hash(0x83ac3f1cfbb450db, 0xaa4f1b6879369fbd, []byte(filename)),
}
binary.Write(&a.buffer, binary.LittleEndian, gi)
}

gi := &GoodByeItem{
offset: a.pos,
len: goodbyelen,
hash: 0xef5eed5b753e1555,
}

binary.Write(&a.buffer, binary.LittleEndian, gi)

a.Flush()

}


//Prima deve essere scritta una directory!!
func (a *PXARArchive) WriteFile(path string, basename string) {
fmt.Printf("Write file %s at %d\n", path, a.pos)
fileInfo, err := os.Stat(path)
if err != nil {
fmt.Printf("Failed to stat %s\n", path)
return
}

file, err := os.Open(path)

if err != nil {
fmt.Printf("Failed to open %s\n", path)
return
}

defer file.Close()


fname_entry := &PXARFilenameEntry{
hdr: PXAR_FILENAME,
len: uint64(16)+uint64(len(basename))+1,
}

binary.Write(&a.buffer, binary.LittleEndian, fname_entry)

a.buffer.WriteString(basename)
a.buffer.WriteByte(0x00)

entry := &PXARFileEntry{
hdr: PXAR_ENTRY,
len: 56,
mode: IFREG | 0o777,
flags: 0,
uid: 1000,
gid: 1000,
mtime: MTime{
secs: uint64(fileInfo.ModTime().Unix()),
nanos: 0,
padding: 0,
},
}
binary.Write(&a.buffer, binary.LittleEndian, entry)

binary.Write(&a.buffer, binary.LittleEndian, PXAR_PAYLOAD)
filesize := uint64(fileInfo.Size())+16 //Dimensione del file + Header

binary.Write(&a.buffer, binary.LittleEndian, filesize)

a.Flush()


readbuffer := make([]byte, 1024*64)

for {
nread, err := file.Read(readbuffer)
if nread <= 0 {
break
}
if err != nil {
panic(err.Error())
}
a.buffer.Write(readbuffer[:nread])
a.Flush()
}





a.Flush()
}

func main() {
A := &PXARArchive{}
f, _ := os.Create("test.pxar")
defer f.Close()
A.writeCB = func(b []byte) {
f.Write(b)
}
A.WriteDir("./test","",true)

}

0 comments on commit c91b9a4

Please sign in to comment.