Finished FixSymlinks (in theory)

This commit is contained in:
Caleb Gardner
2021-01-13 06:02:15 -06:00
parent dcf59a4261
commit 407d649b3d
2 changed files with 126 additions and 9 deletions
+1 -1
View File
@@ -16,7 +16,7 @@ import (
const ( const (
downloadURL = "https://github.com/srevinsaju/Firefox-Appimage/releases/download/firefox-v84.0.r20201221152838/firefox-84.0.r20201221152838-x86_64.AppImage" downloadURL = "https://github.com/srevinsaju/Firefox-Appimage/releases/download/firefox-v84.0.r20201221152838/firefox-84.0.r20201221152838-x86_64.AppImage"
appImageName = "firefox-84.0.r20201221152838-x86_64.AppImage" appImageName = "firefox-84.0.r20201221152838-x86_64.AppImage"
squashfsName = "balenaEtcher-1.5.113-x64.AppImage.sfs" //testing with a ArchLinux root fs from the live img squashfsName = "balenaEtcher-1.5.113-x64.AppImage.sfs"
) )
func TestSquashfs(t *testing.T) { func TestSquashfs(t *testing.T) {
+125 -8
View File
@@ -33,6 +33,7 @@ type Writer struct {
symlinkTable map[string]string //[oldpath]newpath symlinkTable map[string]string //[oldpath]newpath
uidGUIDTable []int uidGUIDTable []int
compressionType int compressionType int
Flags superblockFlags
allowErrors bool allowErrors bool
} }
@@ -81,6 +82,9 @@ func (w *Writer) AddFileTo(filepath string, file *os.File) error {
if !strings.HasPrefix(filepath, "/") { if !strings.HasPrefix(filepath, "/") {
filepath = "/" + filepath filepath = "/" + filepath
} }
if w.Contains(filepath) {
return errors.New("File already exists at " + filepath)
}
var holder fileHolder var holder fileHolder
holder.path, holder.name = path.Split(filepath) holder.path, holder.name = path.Split(filepath)
holder.reader = file holder.reader = file
@@ -150,6 +154,9 @@ func (w *Writer) AddReaderTo(filepath string, reader io.Reader) error {
if !strings.HasPrefix(filepath, "/") { if !strings.HasPrefix(filepath, "/") {
filepath = "/" + filepath filepath = "/" + filepath
} }
if w.Contains(filepath) {
return errors.New("File already exists at " + filepath)
}
var holder fileHolder var holder fileHolder
holder.path, holder.name = path.Split(filepath) holder.path, holder.name = path.Split(filepath)
holder.reader = reader holder.reader = reader
@@ -171,10 +178,11 @@ func (w *Writer) Remove(filepath string) bool {
for i, fil := range files { for i, fil := range files {
if match, _ = path.Match(name, fil.name); match { if match, _ = path.Match(name, fil.name); match {
matchFound = true matchFound = true
if i != len(files)-1 { if len(w.structure[structDir]) > 1 {
w.structure[structDir] = append(w.structure[structDir][:i], w.structure[structDir][i+1:]...) w.structure[structDir][i] = w.structure[structDir][len(w.structure[structDir])-1]
w.structure[structDir] = w.structure[structDir][:len(w.structure[structDir])-1]
} else { } else {
w.structure[structDir] = w.structure[structDir][:i] w.structure[structDir] = nil
} }
} }
} }
@@ -185,11 +193,120 @@ func (w *Writer) Remove(filepath string) bool {
//FixSymlinks will scan through the squashfs archive and try to find broken symlinks and fix them. //FixSymlinks will scan through the squashfs archive and try to find broken symlinks and fix them.
//This done by replacing the symlink with the target file and then pointing other symlinks to that file. //This done by replacing the symlink with the target file and then pointing other symlinks to that file.
// //If all symlinks can be resolved, the error slice will be nil, and the bool false, otherwise all errors occured will be in the slice.
//If this is not run before writing, you may end up with broken symlinks. func (w *Writer) FixSymlinks() (errs []error, problems bool) {
func (w *Writer) FixSymlinks() error { for dir, holderSlice := range w.structure {
//TODO for i, holder := range holderSlice {
return errors.New("DON'T") if !holder.symlink {
continue
}
sym := holder.symLocation
if !path.IsAbs(holder.symLocation) {
sym = path.Join(dir, holder.symLocation)
}
if path, ok := w.symlinkTable[sym]; ok {
w.structure[dir][i].symLocation = path
continue
}
if path.IsAbs(sym) || strings.HasPrefix(sym, "../") {
var symFil *os.File
var err error
if strings.HasPrefix(sym, "../") {
holderFil, ok := holder.reader.(*os.File)
if !ok {
problems = true
errs = append(errs, errors.New("Cannot resolve symlink at "+dir+holder.name))
continue
}
symFilPath := path.Dir(holderFil.Name())
symFilPath = path.Join(symFilPath, holder.symLocation)
symFil, err = os.Open(symFilPath)
} else {
symFil, err = os.Open(sym)
}
if err != nil {
problems = true
errs = append(errs, err)
continue
}
suc := w.Remove(dir + holder.name)
if !suc {
problems = true
errs = append(errs, errors.New("Cannot resolve symlink at "+dir+holder.name))
continue
}
err = w.AddFileTo(dir+holder.name, symFil)
if err != nil {
w.structure[dir] = append(w.structure[dir], holder)
problems = true
errs = append(errs, err)
continue
}
w.symlinkTable[sym] = dir + holder.name
} else {
symHolder := w.holderAt(sym)
if symHolder != nil {
w.symlinkTable[sym] = sym
continue
}
holderFil, ok := holder.reader.(*os.File)
if !ok {
problems = true
errs = append(errs, errors.New("Cannot resolve symlink at "+dir+holder.name))
continue
}
symFilPath := path.Dir(holderFil.Name())
symFilPath = path.Join(symFilPath, holder.symLocation)
symFil, err := os.Open(symFilPath)
if err != nil {
problems = true
errs = append(errs, err)
continue
}
err = w.AddFileTo(sym, symFil)
if err != nil {
problems = true
errs = append(errs, err)
continue
}
w.symlinkTable[sym] = sym
}
}
}
return
}
func (w *Writer) holderAt(filepath string) *fileHolder {
filepath = path.Clean(filepath)
if !strings.HasPrefix(filepath, "/") {
filepath = "/" + filepath
}
dir, name := path.Split(filepath)
if holderSlice, ok := w.structure[dir]; ok {
for _, holder := range holderSlice {
if holder.name == name {
return holder
}
}
}
return nil
}
//Contains returns whether a file is present at the given filepath
func (w *Writer) Contains(filepath string) bool {
filepath = path.Clean(filepath)
if !strings.HasPrefix(filepath, "/") {
filepath = "/" + filepath
}
dir, name := path.Split(filepath)
if holderSlice, ok := w.structure[dir]; ok {
for _, holder := range holderSlice {
if holder.name == name {
return true
}
}
}
return false
} }
//WriteToFilename creates the squashfs archive with the given filepath. //WriteToFilename creates the squashfs archive with the given filepath.