Trying to figure out the best way to convert files

This commit is contained in:
Caleb Gardner
2021-01-05 05:53:16 -06:00
parent 43fe4f91a2
commit 97b12090c6
+86 -95
View File
@@ -5,7 +5,6 @@ import (
"log" "log"
"os" "os"
"path" "path"
"sort"
"strings" "strings"
"github.com/CalebQ42/squashfs/internal/inode" "github.com/CalebQ42/squashfs/internal/inode"
@@ -17,10 +16,10 @@ type Writer struct {
files map[string][]*File files map[string][]*File
directories []string directories []string
symlinkTable map[string]string //symlinkTable holds info about symlink'd to files that had to be moved from their original position. [originalpath]newpath symlinkTable map[string]string //symlinkTable holds info about symlink'd to files that had to be moved from their original position. [originalpath]newpath
symTableTemp map[string]string
ResolveSymlinks bool ResolveSymlinks bool
AllowErrors bool AllowErrors bool
compression int compression int
temp []*File
} }
//NewWriter creates a new squashfs.Writer with the default settings (gzip compression, autoresolving symlinks, and allowErrors) //NewWriter creates a new squashfs.Writer with the default settings (gzip compression, autoresolving symlinks, and allowErrors)
@@ -51,87 +50,102 @@ func NewWriterWithOptions(resolveSymlinks, allowErrors bool, compressionType int
return &out, nil return &out, nil
} }
//convertFile converts the given os.File to a squashfs.File and then adds it to the Writer's temp File slice. type fileError struct {
func (w *Writer) convertFile(squashfsPath string, file *os.File, errChan chan error) { files []*File
err error
}
//convertFile converts the given os.File to a squashfs.File. Returns the errors and converted file to the channels.
func (w *Writer) convertFile(squashfsPath string, file *os.File, subDir bool, fileErrChan chan fileError) {
var out fileError
var fil File var fil File
fil.Reader = file fil.Reader = file
fil.name = path.Base(file.Name())
fil.path = squashfsPath fil.path = squashfsPath
stat, err := file.Stat() fil.name = path.Base(file.Name())
if err != nil { mode := fil.Mode()
if w.AllowErrors {
log.Println("Error while getting FileInfo for", file.Name()+":") if mode.IsRegular() {
log.Println(err)
err = nil
}
errChan <- err
return
}
if stat.IsDir() {
fil.filType = inode.BasicDirectoryType
dirs, err := file.Readdirnames(-1)
if err != nil {
if w.AllowErrors {
log.Println("Error when getting directory names for", file.Name()+":")
log.Println(err)
err = nil
}
errChan <- err
return
}
subDirErrChan := make(chan error)
for _, dir := range dirs {
go func(newFilename string, errChan chan error) {
subFil, err := os.Open(file.Name() + newFilename)
if err != nil {
if w.AllowErrors {
log.Println("Error when opening sub-directory", subFil.Name()+":")
log.Println(err)
err = nil
}
errChan <- err
return
}
subDirErrChan := make(chan error)
w.convertFile(fil.Path(), subFil, subDirErrChan)
errChan <- <-subDirErrChan
return
}(dir, subDirErrChan)
}
for range dirs {
err = <-subDirErrChan
if err != nil {
errChan <- err
return
}
}
w.temp = append(w.temp, &fil)
errChan <- nil
return
} else if stat.Mode().IsRegular() {
fil.filType = inode.BasicFileType fil.filType = inode.BasicFileType
w.temp = append(w.temp, &fil) goto successExit
errChan <- nil } else if mode.IsDir() {
return fil.filType = inode.BasicSymlinkType
} else if stat.Mode()&os.ModeSymlink == os.ModeSymlink { subDirs, err := file.Readdirnames(-1)
linkLocation, err := os.Readlink(file.Name())
if err != nil { if err != nil {
if w.AllowErrors { if w.AllowErrors && !subDir {
log.Println("Error when reading symlink's target", file.Name()+":") log.Println("Can't get sub-directories for", file.Name())
log.Println(err) log.Println(err)
err = nil } else {
out.err = err
}
goto failExit
}
subDirChan := make(chan fileError)
for _, filName := range subDirs {
go func(filename string, returnChan chan fileError) {
subFil, err := os.Open(filename)
if err != nil {
out.err = err
returnChan <- fileError{
err: err,
} }
errChan <- err
return return
} }
w.convertFile(fil.Path(), subFil, true, subDirChan)
}(file.Name()+filName, subDirChan)
}
for range subDirs {
filErr := <-subDirChan
if filErr.err != nil {
if w.AllowErrors && !subDir {
log.Println("Error while adding subdirectory of", file.Name())
log.Println(filErr.err)
} else if subDir {
if out.err == nil {
out.err = filErr.err
}
} else {
out.err = err
goto failExit
}
continue
}
out.files = append(out.files, filErr.files...)
}
goto successExit
} else if mode&os.ModeSymlink == os.ModeSymlink {
fil.filType = inode.BasicSymlinkType
symLocation, err := os.Readlink(file.Name())
if err != nil {
if w.AllowErrors && !subDir {
log.Println("Error while getting symlink's information for", file.Name())
log.Println(err)
} else {
out.err = err
}
goto failExit
}
if w.ResolveSymlinks { if w.ResolveSymlinks {
if w.symlinkTable[linkLocation] != "" { if val, ok := w.symlinkTable[symLocation]; ok {
linkLocation = w.symlinkTable[linkLocation] symLocation = val
} else if val, ok := w.symTableTemp[symLocation]; ok {
symLocation = val
} else {
//TODO: either add the file, or place the file in this location. Maybe defer this until after all the other files are added?
} }
} }
//TODO: finish symlink support //TODO: store the symLocation inside the File somehow....
} }
errChan <- errors.New("Unsupported file type") if w.AllowErrors && !subDir {
log.Println("Unsupported file type for", file.Name())
} else {
out.err = errors.New("Unsupported file type")
}
failExit: //before this is used, make sure to log or set the error.
fileErrChan <- out
return
successExit:
out.files = []*File{&fil}
fileErrChan <- out
return return
} }
@@ -145,33 +159,10 @@ func (w *Writer) AddFilesToPath(squashfsPath string, files ...*os.File) error {
if squashfsPath == "." { if squashfsPath == "." {
squashfsPath = "/" squashfsPath = "/"
} }
errChan := make(chan error) fileErrChan := make(chan fileError)
for _, fil := range files { for _, fil := range files {
go w.convertFile(squashfsPath, fil, errChan) go w.convertFile(squashfsPath, fil, false, fileErrChan)
} }
var firstError error
for range files {
err := <-errChan
if firstError != nil && err != nil {
firstError = err
}
}
if firstError != nil {
w.temp = nil
return firstError
}
for _, tempFil := range w.temp {
if tempFil.path != "/" {
ind := sort.SearchStrings(w.directories, tempFil.path)
if ind == len(w.directories) {
w.directories = append(w.directories, tempFil.path)
sort.Strings(w.directories)
}
}
w.files[tempFil.path] = append(w.files[tempFil.path], tempFil)
}
w.temp = nil
return nil
} }
//AddFiles adds all files given to the root directory //AddFiles adds all files given to the root directory