Files
fission-src/pkg/utils/zip.go
T
Sanket SudakeandGitHub 4bce904c96 Use mholt/archives instead of mholt/archiver (#3128)
* Use mholt/archives instead of mholt/archiver
* Fix validations
* Fix iszip function
* Fix directory
* Add better path sanitization
* ensure safe dir is passed
* Fix file permissions
* Fix config path
* Sanitize builder source path

---------

Signed-off-by: Sanket Sudake <sanketsudake@gmail.com>
2025-01-08 11:00:54 +05:30

121 lines
3.0 KiB
Go

package utils
import (
"context"
"fmt"
"io"
"os"
"path/filepath"
"github.com/mholt/archives"
)
func IsZip(ctx context.Context, filename string) (bool, error) {
f, err := os.Open(filename)
if err != nil {
return false, nil
}
result, err := archives.Zip{}.Match(ctx, filename, f)
if err != nil {
return false, err
}
if result.ByName || result.ByStream {
return true, nil
}
return false, nil
}
func MakeZipArchiveWithGlobs(ctx context.Context, targetName string, globs ...string) (string, error) {
globFiles, err := FindAllGlobs(globs...)
if err != nil {
return "", err
}
if len(globFiles) == 0 {
return "", fmt.Errorf("no files found for globs: %v", globs)
}
files := make(map[string]string, len(globFiles))
for _, file := range globFiles {
files[file] = ""
}
archiveFiles, err := archives.FilesFromDisk(ctx, nil, files)
if err != nil {
return "", fmt.Errorf("failed to read files from disk: %w", err)
}
out, err := os.Create(targetName)
if err != nil {
return "", fmt.Errorf("failed to create archive file: %w", err)
}
defer out.Close()
zip := archives.CompressedArchive{
Archival: archives.Zip{},
}
if err := zip.Archive(ctx, out, archiveFiles); err != nil {
return "", fmt.Errorf("failed to create archive: %w", err)
}
return filepath.Abs(targetName)
}
// Archive zips the contents of directory at src into a new zip file
// at dst (note that the contents are zipped, not the directory itself).
func Archive(ctx context.Context, src string, dst string) error {
srcInfo, err := os.Stat(src)
if err != nil {
return fmt.Errorf("failed to get source directory info: %w", err)
}
if srcInfo.IsDir() {
src = src + "/*"
}
_, err = MakeZipArchiveWithGlobs(ctx, dst, src)
return err
}
// Unarchive is a function that unzips a zip file to destination
func Unarchive(ctx context.Context, src string, dst string) error {
var format archives.Zip
file, err := os.Open(src)
if err != nil {
return fmt.Errorf("failed to open file: %w", err)
}
defer file.Close()
return format.Extract(ctx, file, func(ctx context.Context, f archives.FileInfo) error {
destPath := filepath.Join(dst, f.NameInArchive)
// check if the file is a directory
if f.IsDir() {
return os.MkdirAll(destPath, f.Mode())
}
// check if parent directory exists for the file
if err := os.MkdirAll(filepath.Dir(destPath), os.ModeDir|0755); err != nil {
return fmt.Errorf("failed to create parent directory: %w", err)
}
// Open file in archive
rc, err := f.Open()
if err != nil {
return fmt.Errorf("failed to open file in archive: %w", err)
}
defer rc.Close()
// Create file in destination
destFile, err := os.Create(destPath)
if err != nil {
return fmt.Errorf("failed to create file in destination: %w", err)
}
defer destFile.Close()
err = destFile.Chmod(f.Mode())
if err != nil {
return fmt.Errorf("failed to set file permissions: %w", err)
}
// Copy file contents
_, err = io.Copy(destFile, rc)
if err != nil {
return fmt.Errorf("failed to copy file contents: %w", err)
}
return nil
})
}