Skip to content

Instantly share code, notes, and snippets.

@snizovtsev
Last active April 26, 2019 07:26
Show Gist options
  • Save snizovtsev/2d282f2d58337ecbbe72356b2c041b8d to your computer and use it in GitHub Desktop.
Save snizovtsev/2d282f2d58337ecbbe72356b2c041b8d to your computer and use it in GitHub Desktop.
Tar to squashfs using pseudo file
// $ go run tar2sfs.go distro.tar > INDEX
// $ mksquashfs ./sysroot distro.img -pf INDEX -noappend
package main
import (
"archive/tar"
"flag"
"fmt"
"io"
"log"
"os"
"strconv"
"strings"
"github.com/pkg/errors"
)
func pseudoQuote(name string) string {
if strings.ContainsAny(name, "\n\" ") {
return fmt.Sprintf("\"%s\"", strings.ReplaceAll(name, "\"", "\\\""))
} else {
return name
}
}
func pseudoDef(tarpath string, block int64, hdr tar.Header) string {
var name, uid, gid, data string
var kind byte
name = pseudoQuote(hdr.Name)
mode := hdr.Mode & 07777
if hdr.Uname != "" {
uid = hdr.Uname
} else {
uid = strconv.Itoa(hdr.Uid)
}
if hdr.Gname != "" {
gid = hdr.Gname
} else {
gid = strconv.Itoa(hdr.Gid)
}
switch hdr.Typeflag {
case tar.TypeReg:
kind = 'f'
data = fmt.Sprintf(
" dd status=none if=%q bs=512 skip=%d | tar xOf - --occurrence %q",
tarpath, block, hdr.Name)
case tar.TypeDir:
kind = 'd'
case tar.TypeBlock:
kind = 'b'
data = fmt.Sprintf("%d %d", hdr.Devmajor, hdr.Devminor)
case tar.TypeChar:
kind = 'c'
data = fmt.Sprintf("%d %d", hdr.Devmajor, hdr.Devminor)
case tar.TypeSymlink:
kind = 's'
data = hdr.Linkname
case tar.TypeLink:
kind = 's'
data = hdr.Linkname
// case tar.TypeFifo:
// case tar.TypeGNUSparse:
default:
log.Fatal("Unsupported tar node type: %c", hdr.Typeflag)
}
return fmt.Sprintf("%s %c %o %s %s %s", name, kind, mode, uid, gid, data)
}
func main() {
flag.Parse()
if len(flag.Args()) != 1 {
log.Fatal("Input tar is missing")
}
tarpath := flag.Arg(0)
tarfd, err := os.Open(tarpath)
if err != nil {
log.Fatal(err)
}
defer tarfd.Close()
iter := tar.NewReader(tarfd)
var offset int64 = 0
for {
hdr, err := iter.Next()
if err == io.EOF {
break
}
if err != nil {
log.Fatal(errors.Wrap(err, tarpath))
}
fmt.Println(pseudoDef(tarpath, offset, *hdr))
offset, err = tarfd.Seek(0, io.SeekCurrent)
if offset%512 != 0 {
panic("Tar header is not aligned")
}
if hdr.Size > 0 {
offset = (offset / 512) + (hdr.Size-1)/512 + 1
} else {
offset /= 512
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment