diff --git a/pkg/config/config.go b/pkg/config/config.go index 695020ad..1c405a7b 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -200,9 +200,10 @@ type LuetConfig struct { System LuetSystemConfig `mapstructure:"system"` Solver LuetSolverOptions `mapstructure:"solver"` - RepositoriesConfDir []string `mapstructure:"repos_confdir"` - CacheRepositories []LuetRepository `mapstructure:"repetitors"` - SystemRepositories []LuetRepository `mapstructure:"repositories"` + RepositoriesConfDir []string `mapstructure:"repos_confdir"` + ConfigProtectConfDir []string `mapstructure:"config_protect_confdir"` + CacheRepositories []LuetRepository `mapstructure:"repetitors"` + SystemRepositories []LuetRepository `mapstructure:"repositories"` } func NewLuetConfig(viper *v.Viper) *LuetConfig { @@ -244,6 +245,7 @@ func GenDefault(viper *v.Viper) { viper.SetDefault("system.pkgs_cache_path", "packages") viper.SetDefault("repos_confdir", []string{"/etc/luet/repos.conf.d"}) + viper.SetDefault("config_protect_confdir", []string{"/etc/luet/config.protect.d"}) viper.SetDefault("cache_repositories", []string{}) viper.SetDefault("system_repositories", []string{}) diff --git a/pkg/helpers/archive.go b/pkg/helpers/archive.go index 941b7a89..c75b6e3e 100644 --- a/pkg/helpers/archive.go +++ b/pkg/helpers/archive.go @@ -17,6 +17,7 @@ package helpers import ( "archive/tar" + "errors" "io" "os" "path/filepath" @@ -49,6 +50,67 @@ func Tar(src, dest string) error { return err } +type TarModifierWrapperFunc func(path, dst string, header *tar.Header, content io.Reader) (*tar.Header, []byte, error) +type TarModifierWrapper struct { + DestinationPath string + Modifier TarModifierWrapperFunc +} + +func NewTarModifierWrapper(dst string, modifier TarModifierWrapperFunc) *TarModifierWrapper { + return &TarModifierWrapper{ + DestinationPath: dst, + Modifier: modifier, + } +} + +func (m *TarModifierWrapper) GetModifier() archive.TarModifierFunc { + return func(path string, header *tar.Header, content io.Reader) (*tar.Header, []byte, error) { + return m.Modifier(m.DestinationPath, path, header, content) + } +} + +func UntarProtect(src, dst string, sameOwner bool, protectedFiles []string, modifier *TarModifierWrapper) error { + var ans error + + if len(protectedFiles) <= 0 { + return Untar(src, dst, sameOwner) + } + + // POST: we have files to protect. I create a ReplaceFileTarWrapper + in, err := os.Open(src) + if err != nil { + return err + } + defer in.Close() + + // Create modifier map + mods := make(map[string]archive.TarModifierFunc) + for _, file := range protectedFiles { + mods[file] = modifier.GetModifier() + } + + replacerArchive := archive.ReplaceFileTarWrapper(in, mods) + + if sameOwner { + // PRE: i have root privileged. + + opts := &archive.TarOptions{ + // NOTE: NoLchown boolean is used for chmod of the symlink + // Probably it's needed set this always to true. + NoLchown: true, + ExcludePatterns: []string{"dev/"}, // prevent 'operation not permitted' + ContinueOnError: true, + } + + ans = archive.Untar(replacerArchive, dst, opts) + } else { + // TODO + ans = errors.New("Not implemented") + } + + return ans +} + // Untar just a wrapper around the docker functions func Untar(src, dest string, sameOwner bool) error { var ans error