Skip to content
Snippets Groups Projects
plugin.go 1.68 KiB
Newer Older
  • Learn to ignore specific revisions
  • package util
    
    import (
    	"archive/zip"
    	"io"
    	"os"
    	"path/filepath"
    
    	"github.com/google/uuid"
    	"github.com/spf13/viper"
    )
    
    // TODO: can be private in the future.
    const (
    
    	// PluginExecutableName references the unzippped name of a plugin.
    	PluginExecutableName string = "plugin"
    
    	// ManifestFileName references the name of a manifest file that has been
    	// requested while creating a new device of type plugin/csbi.
    	ManifestFileName string = "plugin.yaml"
    	// BundledPluginName references the name of a zipped plugin.
    	BundledPluginName string = "bundled_plugin.zip"
    )
    
    func UnzipPlugin(id uuid.UUID) error {
    	folderName := viper.GetString("plugin-folder")
    	path := filepath.Clean(filepath.Join(folderName, id.String(), BundledPluginName))
    
    	pluginArchive, err := zip.OpenReader(path)
    	if err != nil {
    		return err
    	}
    	defer func() {
    		if ferr := pluginArchive.Close(); ferr != nil {
    			err = ferr
    		}
    	}()
    
    	for _, file := range pluginArchive.File {
    		if err := extractFile(filepath.Dir(path), file); err != nil {
    			return err
    		}
    	}
    
    	if err := os.Remove(path); err != nil {
    		return err
    	}
    	return nil
    }
    
    func extractFile(destination string, archivedFile *zip.File) error {
    	archivedFileReader, err := archivedFile.Open()
    	if err != nil {
    		return err
    	}
    	defer func() {
    		if err := archivedFileReader.Close(); err != nil {
    			panic(err)
    		}
    	}()
    
    	destinationFile, err := os.OpenFile(filepath.Join(destination, archivedFile.Name), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, archivedFile.Mode())
    	if err != nil {
    		return err
    	}
    	defer func() {
    		if err := destinationFile.Close(); err != nil {
    			panic(err)
    		}
    	}()
    
    	_, err = io.Copy(destinationFile, archivedFileReader)
    	if err != nil {
    		return err
    	}
    
    	return nil
    }