Add support for same-owner config option

This commit is contained in:
Daniele Rondina 2020-02-01 17:58:23 +01:00
parent 96f4a6c0e3
commit 524bbf990e
6 changed files with 107 additions and 27 deletions

View File

@ -17,6 +17,7 @@ package cmd
import ( import (
"os" "os"
"os/user"
"path/filepath" "path/filepath"
"runtime" "runtime"
"strings" "strings"
@ -110,8 +111,19 @@ func init() {
pflags.StringVar(&cfgFile, "config", "", "config file (default is $HOME/.luet.yaml)") pflags.StringVar(&cfgFile, "config", "", "config file (default is $HOME/.luet.yaml)")
pflags.BoolVarP(&Verbose, "verbose", "v", false, "verbose output") pflags.BoolVarP(&Verbose, "verbose", "v", false, "verbose output")
pflags.Bool("fatal", false, "Enables Warnings to exit") pflags.Bool("fatal", false, "Enables Warnings to exit")
u, err := user.Current()
if err != nil {
Fatal("failed to retrieve user identity:", err.Error())
}
sameOwner := false
if u.Uid == "0" {
sameOwner = true
}
pflags.Bool("same-owner", sameOwner, "Maintain same owner on uncompress.")
pflags.Int("concurrency", runtime.NumCPU(), "Concurrency") pflags.Int("concurrency", runtime.NumCPU(), "Concurrency")
config.LuetCfg.Viper.BindPFlag("general.same_owner", pflags.Lookup("same-owner"))
config.LuetCfg.Viper.BindPFlag("general.debug", pflags.Lookup("verbose")) config.LuetCfg.Viper.BindPFlag("general.debug", pflags.Lookup("verbose"))
config.LuetCfg.Viper.BindPFlag("general.concurrency", pflags.Lookup("concurrency")) config.LuetCfg.Viper.BindPFlag("general.concurrency", pflags.Lookup("concurrency"))
config.LuetCfg.Viper.BindPFlag("general.fatal_warnings", pflags.Lookup("fatal")) config.LuetCfg.Viper.BindPFlag("general.fatal_warnings", pflags.Lookup("fatal"))

View File

@ -35,6 +35,9 @@
# Enable warnings to exit # Enable warnings to exit
# fatal_warnings: false # fatal_warnings: false
# #
# Try extracting tree/packages with the same ownership as exists in the archive (default for superuser).
# same_owner: false
#
# --------------------------------------------- # ---------------------------------------------
# System configuration section: # System configuration section:
# --------------------------------------------- # ---------------------------------------------

View File

@ -31,6 +31,7 @@ import (
"strings" "strings"
"sync" "sync"
. "github.com/mudler/luet/pkg/config"
"github.com/mudler/luet/pkg/helpers" "github.com/mudler/luet/pkg/helpers"
. "github.com/mudler/luet/pkg/logger" . "github.com/mudler/luet/pkg/logger"
"github.com/mudler/luet/pkg/solver" "github.com/mudler/luet/pkg/solver"
@ -294,14 +295,15 @@ func (a *PackageArtifact) Unpack(dst string, keepPerms bool) error {
return errors.Wrap(err, "Cannot copy to "+a.GetPath()+".uncompressed") return errors.Wrap(err, "Cannot copy to "+a.GetPath()+".uncompressed")
} }
err = helpers.Untar(a.GetPath()+".uncompressed", dst, keepPerms) err = helpers.Untar(a.GetPath()+".uncompressed", dst,
LuetCfg.GetGeneral().SameOwner)
if err != nil { if err != nil {
return err return err
} }
return nil return nil
// Defaults to tar only (covers when "none" is supplied) // Defaults to tar only (covers when "none" is supplied)
default: default:
return helpers.Untar(a.GetPath(), dst, keepPerms) return helpers.Untar(a.GetPath(), dst, LuetCfg.GetGeneral().SameOwner)
} }
return errors.New("Compression type must be supplied") return errors.New("Compression type must be supplied")
} }

View File

@ -19,6 +19,7 @@ package config
import ( import (
"errors" "errors"
"fmt" "fmt"
"os/user"
"runtime" "runtime"
"time" "time"
@ -34,6 +35,7 @@ type LuetLoggingConfig struct {
} }
type LuetGeneralConfig struct { type LuetGeneralConfig struct {
SameOwner bool `mapstructure:"same_owner"`
Concurrency int `mapstructure:"concurrency"` Concurrency int `mapstructure:"concurrency"`
Debug bool `mapstructure:"debug"` Debug bool `mapstructure:"debug"`
ShowBuildOutput bool `mapstructure:"show_build_output"` ShowBuildOutput bool `mapstructure:"show_build_output"`
@ -125,7 +127,6 @@ func NewLuetConfig(viper *v.Viper) *LuetConfig {
} }
func GenDefault(viper *v.Viper) { func GenDefault(viper *v.Viper) {
viper.SetDefault("logging.level", "info") viper.SetDefault("logging.level", "info")
viper.SetDefault("logging.path", "") viper.SetDefault("logging.path", "")
viper.SetDefault("logging.json_format", false) viper.SetDefault("logging.json_format", false)
@ -137,6 +138,13 @@ func GenDefault(viper *v.Viper) {
viper.SetDefault("general.spinner_charset", 22) viper.SetDefault("general.spinner_charset", 22)
viper.SetDefault("general.fatal_warnings", false) viper.SetDefault("general.fatal_warnings", false)
u, _ := user.Current()
if u.Uid == "0" {
viper.SetDefault("general.same_owner", true)
} else {
viper.SetDefault("general.same_owner", false)
}
viper.SetDefault("system.database_engine", "boltdb") viper.SetDefault("system.database_engine", "boltdb")
viper.SetDefault("system.database_path", "/var/cache/luet") viper.SetDefault("system.database_path", "/var/cache/luet")
viper.SetDefault("system.rootfs", "/") viper.SetDefault("system.rootfs", "/")
@ -182,11 +190,13 @@ func (c *LuetGeneralConfig) String() string {
ans := fmt.Sprintf(` ans := fmt.Sprintf(`
general: general:
concurrency: %d concurrency: %d
same_owner: %t
debug: %t debug: %t
fatal_warnings: %t fatal_warnings: %t
show_build_output: %t show_build_output: %t
spinner_ms: %d spinner_ms: %d
spinner_charset: %d`, c.Concurrency, c.Debug, c.FatalWarns, c.ShowBuildOutput, spinner_charset: %d`, c.Concurrency, c.SameOwner, c.Debug,
c.FatalWarns, c.ShowBuildOutput,
c.SpinnerMs, c.SpinnerCharset) c.SpinnerMs, c.SpinnerCharset)
return ans return ans

View File

@ -16,13 +16,14 @@
package helpers package helpers
import ( import (
"archive/tar"
"io" "io"
"os" "os"
//"os/user" "path/filepath"
//"strconv"
. "github.com/mudler/luet/pkg/config"
"github.com/docker/docker/pkg/archive" "github.com/docker/docker/pkg/archive"
//"github.com/docker/docker/pkg/idtools"
) )
func Tar(src, dest string) error { func Tar(src, dest string) error {
@ -52,31 +53,82 @@ func Tar(src, dest string) error {
// Untar just a wrapper around the docker functions // Untar just a wrapper around the docker functions
func Untar(src, dest string, sameOwner bool) error { func Untar(src, dest string, sameOwner bool) error {
var ans error
in, err := os.Open(src) in, err := os.Open(src)
if err != nil { if err != nil {
return err return err
} }
defer in.Close() defer in.Close()
opts := &archive.TarOptions{ if LuetCfg.GetGeneral().SameOwner {
// NOTE: NoLchown boolean is used for chmod of the symlink // PRE: i have root privileged.
// Probably it's needed set this always to true.
NoLchown: true, opts := &archive.TarOptions{
ExcludePatterns: []string{"dev/"}, // prevent 'operation not permitted' // 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'
}
ans = archive.Untar(in, dest, opts)
} else {
var fileReader io.ReadCloser = in
tr := tar.NewReader(fileReader)
for {
header, err := tr.Next()
switch {
case err == io.EOF:
goto tarEof
case err != nil:
return err
case header == nil:
continue
}
// the target location where the dir/file should be created
target := filepath.Join(dest, header.Name)
// Check the file type
switch header.Typeflag {
// if its a dir and it doesn't exist create it
case tar.TypeDir:
if _, err := os.Stat(target); err != nil {
if err := os.MkdirAll(target, 0755); err != nil {
return err
}
}
// handle creation of file
case tar.TypeReg:
f, err := os.OpenFile(target, os.O_CREATE|os.O_RDWR, os.FileMode(header.Mode))
if err != nil {
return err
}
// copy over contents
if _, err := io.Copy(f, tr); err != nil {
return err
}
// manually close here after each file operation; defering would cause each
// file close to wait until all operations have completed.
f.Close()
case tar.TypeSymlink:
source := header.Linkname
err := os.Symlink(source, target)
if err != nil {
return err
}
}
}
tarEof:
} }
/* return ans
u, err := user.Current()
if err != nil {
return err
}
// TODO: This seems not sufficient for untar with normal user.
if u.Uid != "0" {
uid, _ := strconv.Atoi(u.Uid)
gid, _ := strconv.Atoi(u.Gid)
opts.ChownOpts = &idtools.Identity{UID: uid, GID: gid}
}
*/
return archive.Untar(in, dest, opts)
} }

View File

@ -34,7 +34,8 @@ func GetRepoDatabaseDirPath(name string) string {
} }
func GetSystemRepoDatabaseDirPath() string { func GetSystemRepoDatabaseDirPath() string {
dbpath := filepath.Join(config.LuetCfg.GetSystem().Rootfs, config.LuetCfg.GetSystem().DatabasePath) dbpath := filepath.Join(config.LuetCfg.GetSystem().Rootfs,
config.LuetCfg.GetSystem().DatabasePath)
err := os.MkdirAll(dbpath, os.ModePerm) err := os.MkdirAll(dbpath, os.ModePerm)
if err != nil { if err != nil {
panic(err) panic(err)