Skip to content

Instantly share code, notes, and snippets.

@ImSingee
Created April 24, 2023 12:24
Show Gist options
  • Save ImSingee/165ae13e56ef15fdc0c40b7ef927a33c to your computer and use it in GitHub Desktop.
Save ImSingee/165ae13e56ef15fdc0c40b7ef927a33c to your computer and use it in GitHub Desktop.
Embed data in a Go program and generate new executable (just a demo, not optimized for production)
package main
import (
"bytes"
"fmt"
"io"
"os"
)
const flagStart = `-----{% start %}-----`
const flagEnd = `-----{% end %}-----`
func Self() string {
exe, err := os.Executable()
if err != nil {
panic(err)
}
return exe
}
func main() {
self := Self()
selfFile, err := os.Open(self)
if err != nil {
panic("open self failed " + err.Error())
}
defer selfFile.Close()
newOffset, err := selfFile.Seek(-int64(len(flagEnd)), 2)
if err != nil {
panic("seek self failed " + err.Error())
}
buf, err := io.ReadAll(selfFile)
if err != nil {
panic("read self end failed " + err.Error())
}
alreadyAppendData := string(buf) == flagEnd
endAt := newOffset + int64(len(flagEnd))
var embedData []byte
if alreadyAppendData {
// search start flag
_, err = selfFile.Seek(0, 0)
if err != nil {
panic("seek self to start failed " + err.Error())
}
readStartAt, err := searchInReader(selfFile, []byte(flagStart))
if err != nil {
panic("search start flag failed " + err.Error())
}
_, err = selfFile.Seek(int64(readStartAt), 0)
if err != nil {
panic("seek self to start flag failed " + err.Error())
}
allData, err := io.ReadAll(selfFile)
if err != nil {
panic("read from start flag to end failed " + err.Error())
}
embedData = allData[:len(allData)-len(flagEnd)]
endAt = int64(readStartAt - len(flagStart))
}
if len(embedData) != 0 {
fmt.Println("Embed Data Found:")
fmt.Println("=============")
fmt.Println(string(embedData))
fmt.Println("=============")
}
var newEmbedData []byte
if len(os.Args) > 1 {
newEmbedData = []byte(os.Args[1])
} else {
fmt.Println("Exit")
return
}
newFile, err := os.CreateTemp(".", "new-*")
if err != nil {
panic("create temp file failed " + err.Error())
}
//defer newFile.Close()
_, err = selfFile.Seek(0, 0)
if err != nil {
panic("seek self to start failed " + err.Error())
}
_, err = io.CopyN(newFile, selfFile, endAt)
if err != nil && err != io.EOF {
panic("copy self to new file failed " + err.Error())
}
_, err = newFile.Write([]byte(flagStart))
if err != nil {
panic("write new start flag failed " + err.Error())
}
_, err = newFile.Write(newEmbedData)
if err != nil {
panic("write new embed data failed " + err.Error())
}
_, err = newFile.Write([]byte(flagEnd))
if err != nil {
panic("write new end flag failed " + err.Error())
}
err = newFile.Close()
if err != nil {
panic("save new file failed " + err.Error())
}
fmt.Println("new file saved to " + newFile.Name())
_ = os.Chmod(newFile.Name(), 0755)
}
func searchInReader(r io.Reader, data []byte) (int, error) {
// production note: we cannot read whole file since it may be too large
all, err := io.ReadAll(r)
if err != nil {
return -1, err
}
found := bytes.LastIndex(all, data)
if found == -1 {
return -1, fmt.Errorf("not found")
}
return found + len(data), nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment