Working on extracting files.

This commit is contained in:
Caleb Gardner
2020-11-30 15:13:47 -06:00
parent c5c6291643
commit 1254df2861
+63 -10
View File
@@ -18,6 +18,8 @@ var (
errNotFile = errors.New("File is not a file") errNotFile = errors.New("File is not a file")
//ErrNotReading is returned when running functions that are only meant to be used when reading a squashfs //ErrNotReading is returned when running functions that are only meant to be used when reading a squashfs
errNotReading = errors.New("Function only supported when reading a squashfs") errNotReading = errors.New("Function only supported when reading a squashfs")
//ErrBrokenSymlink is returned when using ExtractWithOptions with the unbreakSymlink set to true, but the symlink's file cannot be extracted.
ErrBrokenSymlink = errors.New("Extracted symlink is probably broken")
) )
//File is the main way to interact with files within squashfs, or when putting files into a squashfs. //File is the main way to interact with files within squashfs, or when putting files into a squashfs.
@@ -203,35 +205,86 @@ func (f *File) Permission() os.FileMode {
return mode return mode
} }
//ExtractTo extracts the file to the given path. This is the same as ExtractWithOptions(path, false, os.ModePerm). //ExtractTo extracts the file to the given path. This is the same as ExtractWithOptions(path, false, os.ModePerm, false).
//Will NOT try to keep symlinks valid, folders extracted will have the permissions set by the squashfs, but the folder to make path will have full permissions (777). //Will NOT try to keep symlinks valid, folders extracted will have the permissions set by the squashfs, but the folder to make path will have full permissions (777).
// //
//Will try it's best to extract all files, and if any errors come up, they will be appended to the error slice that's returned. //Will try it's best to extract all files, and if any errors come up, they will be appended to the error slice that's returned.
func (f *File) ExtractTo(path string) []error { func (f *File) ExtractTo(path string) []error {
return f.ExtractWithOptions(path, false, os.ModePerm) return f.ExtractWithOptions(path, false, os.ModePerm, false)
} }
//ExtractWithOptions will extract the file to the given path, while allowing customization on how it works. Usually just ExtractTo is good enough. //ExtractWithOptions will extract the file to the given path, while allowing customization on how it works. ExtractTo is the "default" options.
//Will try it's best to extract all files, and if any errors come up, they will be appended to the error slice that's returned. //Will try it's best to extract all files, and if any errors come up, they will be appended to the error slice that's returned.
//Should only return multiple errors if extracting a folder.
// //
//If unbreakSymlink is set, it will also try to extract the symlink's associated file. WARNING: the symlink's file may have to go up the directory to work. //If unbreakSymlink is set, it will also try to extract the symlink's associated file. WARNING: the symlink's file may have to go up the directory to work.
//If unbreakSymlink is set and the file cannot be extracted, a ErrBrokenSymlink will be appended to the returned error slice. //If unbreakSymlink is set and the file cannot be extracted, a ErrBrokenSymlink will be appended to the returned error slice.
// //
//folderPerm only applies to the folders created to get to path. Folders from the archive are given the correct permissions defined by the archive. //folderPerm only applies to the folders created to get to path. Folders from the archive are given the correct permissions defined by the archive.
func (f *File) ExtractWithOptions(path string, unbreakSymlink bool, folderPerm os.FileMode) (errs []error) { func (f *File) ExtractWithOptions(path string, unbreakSymlink bool, folderPerm os.FileMode, verbose bool) (errs []error) {
errs = make([]error, 0)
err := os.MkdirAll(path, folderPerm) err := os.MkdirAll(path, folderPerm)
if err != nil { if err != nil {
return []error{err} return []error{err}
} }
switch { switch {
case f.IsDir(): case f.IsDir():
return []error{errors.New("Dir not supported yet")} err = os.Mkdir(path+"/"+f.Name, f.Permission())
case f.IsFile(): if err != nil {
if verbose {
case f.IsSymlink(): fmt.Println("Error while making: "+path+"/"+f.Name, f.Permission())
return []error{errors.New("Symlink not supported yet")}
} }
return errs errs = append(errs, err)
return
}
children, err := f.GetChildren()
if err != nil {
if verbose {
fmt.Println("Error while making: "+path+"/"+f.Name, f.Permission())
}
errs = append(errs, err)
return
}
finishChan := make(chan []error)
defer close(finishChan)
for _, child := range children {
go func(child *File) {
finishChan <- child.ExtractWithOptions(path, unbreakSymlink, folderPerm, verbose)
}(child)
}
for range children {
errs = append(errs, (<-finishChan)...)
}
return
case f.IsFile():
fil, err := os.Create(path + "/" + f.Name)
if err != nil {
if verbose {
fmt.Println("Error while making: "+path+"/"+f.Name, f.Permission())
}
errs = append(errs, err)
return
}
_, err = io.Copy(fil, f)
if err != nil {
if verbose {
fmt.Println("Error while Copying data to: "+path+"/"+f.Name, f.Permission())
}
errs = append(errs, err)
return
}
err = fil.Chmod(f.Permission())
if err != nil {
if verbose {
fmt.Println("Error while setting permissions for: "+path+"/"+f.Name, f.Permission())
}
errs = append(errs, err)
}
return
case f.IsSymlink():
return []error{errors.New("Symlink not supported (yet)")}
}
return
} }
//Close frees up the memory held up by the underlying reader. Should NOT be called when writing. //Close frees up the memory held up by the underlying reader. Should NOT be called when writing.