The following pull request was submitted through Github.
It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/3789

This e-mail was sent by the LXC bot, direct replies will not reach the author
unless they happen to be subscribed to this list.

=== Description (from pull-request) ===
Move idmap-related functions to the `shared/idmap` package.

Fixes #3787
From 662161d239e152f017fa27a9fd6c03a5f9e44432 Mon Sep 17 00:00:00 2001
From: Alberto Donato <[email protected]>
Date: Fri, 8 Sep 2017 12:00:38 +0200
Subject: [PATCH] shared: move idmap/acl functions to a separate package

Signed-off-by: Alberto Donato <[email protected]>
---
 fuidshift/main.go                         |  12 +--
 lxd/container.go                          |   5 +-
 lxd/container_lxc.go                      |  33 +++---
 lxd/container_lxc_utils.go                |  12 +--
 lxd/main_activateifneeded.go              |   3 +-
 lxd/main_init.go                          |   3 +-
 lxd/migrate.go                            |  21 ++--
 lxd/storage.go                            |   9 +-
 lxd/storage_btrfs.go                      |   3 +-
 lxd/storage_ceph_migration.go             |   3 +-
 lxd/storage_dir.go                        |   3 +-
 lxd/storage_lvm.go                        |   3 +-
 lxd/storage_migration.go                  |   3 +-
 lxd/storage_mock.go                       |   4 +-
 lxd/storage_zfs.go                        |   3 +-
 lxd/sys/os.go                             |   3 +-
 lxd/util/sys.go                           |   8 +-
 shared/{ => idmap}/idmapset_linux.go      |  18 ++--
 shared/{ => idmap}/idmapset_linux_test.go |   2 +-
 shared/idmap/shift_linux.go               | 170 ++++++++++++++++++++++++++++++
 shared/util_linux.go                      | 145 +------------------------
 21 files changed, 254 insertions(+), 212 deletions(-)
 rename shared/{ => idmap}/idmapset_linux.go (97%)
 rename shared/{ => idmap}/idmapset_linux_test.go (99%)
 create mode 100644 shared/idmap/shift_linux.go

diff --git a/fuidshift/main.go b/fuidshift/main.go
index 63eb2ffb1..a9fa1382a 100644
--- a/fuidshift/main.go
+++ b/fuidshift/main.go
@@ -4,7 +4,7 @@ import (
        "fmt"
        "os"
 
-       "github.com/lxc/lxd/shared"
+       "github.com/lxc/lxd/shared/idmap"
 )
 
 func help(me string, status int) {
@@ -35,7 +35,7 @@ func run() error {
        }
 
        directory := os.Args[1]
-       idmap := shared.IdmapSet{}
+       idmapSet := idmap.IdmapSet{}
        testmode := false
        reverse := false
 
@@ -48,14 +48,14 @@ func run() error {
                        testmode = true
                default:
                        var err error
-                       idmap, err = idmap.Append(os.Args[pos])
+                       idmapSet, err = idmapSet.Append(os.Args[pos])
                        if err != nil {
                                return err
                        }
                }
        }
 
-       if idmap.Len() == 0 {
+       if idmapSet.Len() == 0 {
                fmt.Printf("No idmaps given\n")
                help(os.Args[0], 1)
        }
@@ -66,7 +66,7 @@ func run() error {
        }
 
        if reverse {
-               return idmap.UidshiftFromContainer(directory, testmode)
+               return idmapSet.UidshiftFromContainer(directory, testmode)
        }
-       return idmap.UidshiftIntoContainer(directory, testmode)
+       return idmapSet.UidshiftIntoContainer(directory, testmode)
 }
diff --git a/lxd/container.go b/lxd/container.go
index 1be7f95a1..bde60418a 100644
--- a/lxd/container.go
+++ b/lxd/container.go
@@ -18,6 +18,7 @@ import (
        "github.com/lxc/lxd/lxd/types"
        "github.com/lxc/lxd/shared"
        "github.com/lxc/lxd/shared/api"
+       "github.com/lxc/lxd/shared/idmap"
        "github.com/lxc/lxd/shared/osarch"
 )
 
@@ -494,8 +495,8 @@ type container interface {
        StorageStart() (bool, error)
        StorageStop() (bool, error)
        Storage() storage
-       IdmapSet() (*shared.IdmapSet, error)
-       LastIdmapSet() (*shared.IdmapSet, error)
+       IdmapSet() (*idmap.IdmapSet, error)
+       LastIdmapSet() (*idmap.IdmapSet, error)
        TemplateApply(trigger string) error
        StateObject() *state.State
 }
diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index d2628583c..eba02ad72 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -30,6 +30,7 @@ import (
        "github.com/lxc/lxd/lxd/util"
        "github.com/lxc/lxd/shared"
        "github.com/lxc/lxd/shared/api"
+       "github.com/lxc/lxd/shared/idmap"
        "github.com/lxc/lxd/shared/logger"
        "github.com/lxc/lxd/shared/osarch"
 
@@ -331,7 +332,7 @@ func containerLXCCreate(s *state.State, args 
db.ContainerArgs) (container, error
        c.storage = cStorage
 
        // Setup initial idmap config
-       var idmap *shared.IdmapSet
+       var idmap *idmap.IdmapSet
        base := int64(0)
        if !c.IsPrivileged() {
                idmap, base, err = findIdmap(
@@ -457,7 +458,7 @@ type containerLXC struct {
        // Cache
        c        *lxc.Container
        state    *state.State
-       idmapset *shared.IdmapSet
+       idmapset *idmap.IdmapSet
 
        // Storage
        storage storage
@@ -544,7 +545,7 @@ func idmapSize(state *state.State, isolatedStr string, size 
string) (int64, erro
 
 var idmapLock sync.Mutex
 
-func parseRawIdmap(value string) ([]shared.IdmapEntry, error) {
+func parseRawIdmap(value string) ([]idmap.IdmapEntry, error) {
        getRange := func(r string) (int64, int64, error) {
                entries := strings.Split(r, "-")
                if len(entries) > 2 {
@@ -570,7 +571,7 @@ func parseRawIdmap(value string) ([]shared.IdmapEntry, 
error) {
                return base, size, nil
        }
 
-       ret := shared.IdmapSet{}
+       ret := idmap.IdmapSet{}
 
        for _, line := range strings.Split(value, "\n") {
                if line == "" {
@@ -596,7 +597,7 @@ func parseRawIdmap(value string) ([]shared.IdmapEntry, 
error) {
                        return nil, fmt.Errorf("idmap ranges of different sizes 
%s", line)
                }
 
-               entry := shared.IdmapEntry{
+               entry := idmap.IdmapEntry{
                        Hostid:   outsideBase,
                        Nsid:     insideBase,
                        Maprange: insideSize,
@@ -630,7 +631,7 @@ func parseRawIdmap(value string) ([]shared.IdmapEntry, 
error) {
        return ret.Idmap, nil
 }
 
-func findIdmap(state *state.State, cName string, isolatedStr string, 
configBase string, configSize string, rawIdmap string) (*shared.IdmapSet, 
int64, error) {
+func findIdmap(state *state.State, cName string, isolatedStr string, 
configBase string, configSize string, rawIdmap string) (*idmap.IdmapSet, int64, 
error) {
        isolated := false
        if shared.IsTrue(isolatedStr) {
                isolated = true
@@ -642,7 +643,7 @@ func findIdmap(state *state.State, cName string, 
isolatedStr string, configBase
        }
 
        if !isolated {
-               newIdmapset := shared.IdmapSet{Idmap: make([]shared.IdmapEntry, 
len(state.OS.IdmapSet.Idmap))}
+               newIdmapset := idmap.IdmapSet{Idmap: make([]idmap.IdmapEntry, 
len(state.OS.IdmapSet.Idmap))}
                copy(newIdmapset.Idmap, state.OS.IdmapSet.Idmap)
 
                for _, ent := range rawMaps {
@@ -657,8 +658,8 @@ func findIdmap(state *state.State, cName string, 
isolatedStr string, configBase
                return nil, 0, err
        }
 
-       mkIdmap := func(offset int64, size int64) *shared.IdmapSet {
-               set := &shared.IdmapSet{Idmap: []shared.IdmapEntry{
+       mkIdmap := func(offset int64, size int64) *idmap.IdmapSet {
+               set := &idmap.IdmapSet{Idmap: []idmap.IdmapEntry{
                        {Isuid: true, Nsid: 0, Hostid: offset, Maprange: size},
                        {Isgid: true, Nsid: 0, Hostid: offset, Maprange: size},
                }}
@@ -689,7 +690,7 @@ func findIdmap(state *state.State, cName string, 
isolatedStr string, configBase
 
        offset := state.OS.IdmapSet.Idmap[0].Hostid + 65536
 
-       mapentries := shared.ByHostid{}
+       mapentries := idmap.ByHostid{}
        for _, name := range cs {
                /* Don't change our map Just Because. */
                if name == cName {
@@ -722,7 +723,7 @@ func findIdmap(state *state.State, cName string, 
isolatedStr string, configBase
                        return nil, 0, err
                }
 
-               mapentries = append(mapentries, &shared.IdmapEntry{Hostid: 
int64(cBase), Maprange: cSize})
+               mapentries = append(mapentries, &idmap.IdmapEntry{Hostid: 
int64(cBase), Maprange: cSize})
        }
 
        sort.Sort(mapentries)
@@ -3368,7 +3369,7 @@ func (c *containerLXC) Update(args db.ContainerArgs, 
userRequested bool) error {
        }
 
        if shared.StringInSlice("security.idmap.isolated", changedConfig) || 
shared.StringInSlice("security.idmap.base", changedConfig) || 
shared.StringInSlice("security.idmap.size", changedConfig) || 
shared.StringInSlice("raw.idmap", changedConfig) || 
shared.StringInSlice("security.privileged", changedConfig) {
-               var idmap *shared.IdmapSet
+               var idmap *idmap.IdmapSet
                base := int64(0)
                if !c.IsPrivileged() {
                        // update the idmap
@@ -6859,7 +6860,7 @@ func (c *containerLXC) Id() int {
        return c.id
 }
 
-func (c *containerLXC) IdmapSet() (*shared.IdmapSet, error) {
+func (c *containerLXC) IdmapSet() (*idmap.IdmapSet, error) {
        var err error
 
        if c.idmapset != nil {
@@ -6896,7 +6897,7 @@ func (c *containerLXC) LocalDevices() types.Devices {
        return c.localDevices
 }
 
-func (c *containerLXC) idmapsetFromConfig(k string) (*shared.IdmapSet, error) {
+func (c *containerLXC) idmapsetFromConfig(k string) (*idmap.IdmapSet, error) {
        lastJsonIdmap := c.LocalConfig()[k]
 
        if lastJsonIdmap == "" {
@@ -6906,7 +6907,7 @@ func (c *containerLXC) idmapsetFromConfig(k string) 
(*shared.IdmapSet, error) {
        return idmapsetFromString(lastJsonIdmap)
 }
 
-func (c *containerLXC) NextIdmapSet() (*shared.IdmapSet, error) {
+func (c *containerLXC) NextIdmapSet() (*idmap.IdmapSet, error) {
        if c.localConfig["volatile.idmap.next"] != "" {
                return c.idmapsetFromConfig("volatile.idmap.next")
        } else if c.IsPrivileged() {
@@ -6918,7 +6919,7 @@ func (c *containerLXC) NextIdmapSet() (*shared.IdmapSet, 
error) {
        return nil, fmt.Errorf("Unable to determine the idmap")
 }
 
-func (c *containerLXC) LastIdmapSet() (*shared.IdmapSet, error) {
+func (c *containerLXC) LastIdmapSet() (*idmap.IdmapSet, error) {
        return c.idmapsetFromConfig("volatile.last_state.idmap")
 }
 
diff --git a/lxd/container_lxc_utils.go b/lxd/container_lxc_utils.go
index e4c288fc2..9da660f39 100644
--- a/lxd/container_lxc_utils.go
+++ b/lxd/container_lxc_utils.go
@@ -3,12 +3,12 @@ package main
 import (
        "encoding/json"
 
-       "github.com/lxc/lxd/shared"
+       "github.com/lxc/lxd/shared/idmap"
 )
 
-func idmapsetFromString(idmap string) (*shared.IdmapSet, error) {
-       lastIdmap := new(shared.IdmapSet)
-       err := json.Unmarshal([]byte(idmap), &lastIdmap.Idmap)
+func idmapsetFromString(idmapString string) (*idmap.IdmapSet, error) {
+       lastIdmap := new(idmap.IdmapSet)
+       err := json.Unmarshal([]byte(idmapString), &lastIdmap.Idmap)
        if err != nil {
                return nil, err
        }
@@ -20,8 +20,8 @@ func idmapsetFromString(idmap string) (*shared.IdmapSet, 
error) {
        return lastIdmap, nil
 }
 
-func idmapsetToJSON(idmap *shared.IdmapSet) (string, error) {
-       idmapBytes, err := json.Marshal(idmap.Idmap)
+func idmapsetToJSON(idmapSet *idmap.IdmapSet) (string, error) {
+       idmapBytes, err := json.Marshal(idmapSet.Idmap)
        if err != nil {
                return "", err
        }
diff --git a/lxd/main_activateifneeded.go b/lxd/main_activateifneeded.go
index 592e04a30..0a277b07c 100644
--- a/lxd/main_activateifneeded.go
+++ b/lxd/main_activateifneeded.go
@@ -7,6 +7,7 @@ import (
        "github.com/lxc/lxd/client"
        "github.com/lxc/lxd/lxd/db"
        "github.com/lxc/lxd/shared"
+       "github.com/lxc/lxd/shared/idmap"
        "github.com/lxc/lxd/shared/logger"
 )
 
@@ -45,7 +46,7 @@ func cmdActivateIfNeeded(args *Args) error {
        }
 
        // Load the idmap for unprivileged containers
-       d.os.IdmapSet, err = shared.DefaultIdmapSet()
+       d.os.IdmapSet, err = idmap.DefaultIdmapSet()
        if err != nil {
                return err
        }
diff --git a/lxd/main_init.go b/lxd/main_init.go
index 009ea41f5..b09724fae 100644
--- a/lxd/main_init.go
+++ b/lxd/main_init.go
@@ -16,6 +16,7 @@ import (
        "github.com/lxc/lxd/shared"
        "github.com/lxc/lxd/shared/api"
        "github.com/lxc/lxd/shared/cmd"
+       "github.com/lxc/lxd/shared/idmap"
        "github.com/lxc/lxd/shared/logger"
 )
 
@@ -810,7 +811,7 @@ func (cmd *CmdInit) askDefaultPrivileged() int {
        // Detect lack of uid/gid
        defaultPrivileged := -1
        needPrivileged := false
-       idmapset, err := shared.DefaultIdmapSet()
+       idmapset, err := idmap.DefaultIdmapSet()
        if err != nil || len(idmapset.Idmap) == 0 || idmapset.Usable() != nil {
                needPrivileged = true
        }
diff --git a/lxd/migrate.go b/lxd/migrate.go
index 16bcc6fa3..59fa03faa 100644
--- a/lxd/migrate.go
+++ b/lxd/migrate.go
@@ -24,6 +24,7 @@ import (
 
        "github.com/lxc/lxd/shared"
        "github.com/lxc/lxd/shared/api"
+       "github.com/lxc/lxd/shared/idmap"
        "github.com/lxc/lxd/shared/logger"
 )
 
@@ -854,16 +855,16 @@ func (c *migrationSink) Do(migrateOp *operation) error {
        restore := make(chan error)
        go func(c *migrationSink) {
                imagesDir := ""
-               srcIdmap := new(shared.IdmapSet)
-
-               for _, idmap := range header.Idmap {
-                       e := shared.IdmapEntry{
-                               Isuid:    *idmap.Isuid,
-                               Isgid:    *idmap.Isgid,
-                               Nsid:     int64(*idmap.Nsid),
-                               Hostid:   int64(*idmap.Hostid),
-                               Maprange: int64(*idmap.Maprange)}
-                       srcIdmap.Idmap = shared.Extend(srcIdmap.Idmap, e)
+               srcIdmap := new(idmap.IdmapSet)
+
+               for _, idmapSet := range header.Idmap {
+                       e := idmap.IdmapEntry{
+                               Isuid:    *idmapSet.Isuid,
+                               Isgid:    *idmapSet.Isgid,
+                               Nsid:     int64(*idmapSet.Nsid),
+                               Hostid:   int64(*idmapSet.Hostid),
+                               Maprange: int64(*idmapSet.Maprange)}
+                       srcIdmap.Idmap = idmap.Extend(srcIdmap.Idmap, e)
                }
 
                /* We do the fs receive in parallel so we don't have to reason
diff --git a/lxd/storage.go b/lxd/storage.go
index ddc680c20..355553261 100644
--- a/lxd/storage.go
+++ b/lxd/storage.go
@@ -15,6 +15,7 @@ import (
        "github.com/lxc/lxd/lxd/state"
        "github.com/lxc/lxd/shared"
        "github.com/lxc/lxd/shared/api"
+       "github.com/lxc/lxd/shared/idmap"
        "github.com/lxc/lxd/shared/ioprogress"
        "github.com/lxc/lxd/shared/logger"
 )
@@ -220,7 +221,7 @@ type storage interface {
                c container,
                objects []*Snapshot,
                conn *websocket.Conn,
-               srcIdmap *shared.IdmapSet,
+               srcIdmap *idmap.IdmapSet,
                op *operation,
                containerOnly bool) error
 }
@@ -392,7 +393,7 @@ func storagePoolVolumeAttachInit(s *state.State, poolName 
string, volumeName str
        poolVolumePut := st.GetStoragePoolVolumeWritable()
 
        // get last idmapset
-       var lastIdmap *shared.IdmapSet
+       var lastIdmap *idmap.IdmapSet
        if poolVolumePut.Config["volatile.idmap.last"] != "" {
                lastIdmap, err = 
idmapsetFromString(poolVolumePut.Config["volatile.idmap.last"])
                if err != nil {
@@ -709,14 +710,14 @@ func deleteSnapshotMountpoint(snapshotMountpoint string, 
snapshotsSymlinkTarget
 
 // ShiftIfNecessary sets the volatile.last_state.idmap key to the idmap last
 // used by the container.
-func ShiftIfNecessary(container container, srcIdmap *shared.IdmapSet) error {
+func ShiftIfNecessary(container container, srcIdmap *idmap.IdmapSet) error {
        dstIdmap, err := container.IdmapSet()
        if err != nil {
                return err
        }
 
        if dstIdmap == nil {
-               dstIdmap = new(shared.IdmapSet)
+               dstIdmap = new(idmap.IdmapSet)
        }
 
        if !reflect.DeepEqual(srcIdmap, dstIdmap) {
diff --git a/lxd/storage_btrfs.go b/lxd/storage_btrfs.go
index 8c46f174d..0b58dd135 100644
--- a/lxd/storage_btrfs.go
+++ b/lxd/storage_btrfs.go
@@ -19,6 +19,7 @@ import (
        "github.com/lxc/lxd/lxd/util"
        "github.com/lxc/lxd/shared"
        "github.com/lxc/lxd/shared/api"
+       "github.com/lxc/lxd/shared/idmap"
        "github.com/lxc/lxd/shared/logger"
 )
 
@@ -1938,7 +1939,7 @@ func (s *storageBtrfs) MigrationSource(c container, 
containerOnly bool) (Migrati
        return driver, nil
 }
 
-func (s *storageBtrfs) MigrationSink(live bool, container container, snapshots 
[]*Snapshot, conn *websocket.Conn, srcIdmap *shared.IdmapSet, op *operation, 
containerOnly bool) error {
+func (s *storageBtrfs) MigrationSink(live bool, container container, snapshots 
[]*Snapshot, conn *websocket.Conn, srcIdmap *idmap.IdmapSet, op *operation, 
containerOnly bool) error {
        if runningInUserns {
                return rsyncMigrationSink(live, container, snapshots, conn, 
srcIdmap, op, containerOnly)
        }
diff --git a/lxd/storage_ceph_migration.go b/lxd/storage_ceph_migration.go
index f42b706a1..24179fd6e 100644
--- a/lxd/storage_ceph_migration.go
+++ b/lxd/storage_ceph_migration.go
@@ -9,6 +9,7 @@ import (
 
        "github.com/lxc/lxd/lxd/db"
        "github.com/lxc/lxd/shared"
+       "github.com/lxc/lxd/shared/idmap"
        "github.com/lxc/lxd/shared/logger"
 )
 
@@ -191,7 +192,7 @@ func (s *storageCeph) MigrationSource(c container, 
containerOnly bool) (Migratio
        return &driver, nil
 }
 
-func (s *storageCeph) MigrationSink(live bool, c container, snapshots 
[]*Snapshot, conn *websocket.Conn, srcIdmap *shared.IdmapSet, op *operation, 
containerOnly bool) error {
+func (s *storageCeph) MigrationSink(live bool, c container, snapshots 
[]*Snapshot, conn *websocket.Conn, srcIdmap *idmap.IdmapSet, op *operation, 
containerOnly bool) error {
        // Check that we received a valid root disk device with a pool property
        // set.
        parentStoragePool := ""
diff --git a/lxd/storage_dir.go b/lxd/storage_dir.go
index 681cbfb31..acdbca417 100644
--- a/lxd/storage_dir.go
+++ b/lxd/storage_dir.go
@@ -12,6 +12,7 @@ import (
        "github.com/lxc/lxd/lxd/db"
        "github.com/lxc/lxd/shared"
        "github.com/lxc/lxd/shared/api"
+       "github.com/lxc/lxd/shared/idmap"
        "github.com/lxc/lxd/shared/logger"
 )
 
@@ -910,7 +911,7 @@ func (s *storageDir) MigrationSource(container container, 
containerOnly bool) (M
        return rsyncMigrationSource(container, containerOnly)
 }
 
-func (s *storageDir) MigrationSink(live bool, container container, snapshots 
[]*Snapshot, conn *websocket.Conn, srcIdmap *shared.IdmapSet, op *operation, 
containerOnly bool) error {
+func (s *storageDir) MigrationSink(live bool, container container, snapshots 
[]*Snapshot, conn *websocket.Conn, srcIdmap *idmap.IdmapSet, op *operation, 
containerOnly bool) error {
        return rsyncMigrationSink(live, container, snapshots, conn, srcIdmap, 
op, containerOnly)
 }
 
diff --git a/lxd/storage_lvm.go b/lxd/storage_lvm.go
index ce0107c7b..ece80e331 100644
--- a/lxd/storage_lvm.go
+++ b/lxd/storage_lvm.go
@@ -11,6 +11,7 @@ import (
        "github.com/lxc/lxd/lxd/db"
        "github.com/lxc/lxd/shared"
        "github.com/lxc/lxd/shared/api"
+       "github.com/lxc/lxd/shared/idmap"
        "github.com/lxc/lxd/shared/logger"
 )
 
@@ -1651,7 +1652,7 @@ func (s *storageLvm) MigrationSource(container container, 
containerOnly bool) (M
        return rsyncMigrationSource(container, containerOnly)
 }
 
-func (s *storageLvm) MigrationSink(live bool, container container, snapshots 
[]*Snapshot, conn *websocket.Conn, srcIdmap *shared.IdmapSet, op *operation, 
containerOnly bool) error {
+func (s *storageLvm) MigrationSink(live bool, container container, snapshots 
[]*Snapshot, conn *websocket.Conn, srcIdmap *idmap.IdmapSet, op *operation, 
containerOnly bool) error {
        return rsyncMigrationSink(live, container, snapshots, conn, srcIdmap, 
op, containerOnly)
 }
 
diff --git a/lxd/storage_migration.go b/lxd/storage_migration.go
index 80dfb2c14..faf7c4f02 100644
--- a/lxd/storage_migration.go
+++ b/lxd/storage_migration.go
@@ -8,6 +8,7 @@ import (
        "github.com/lxc/lxd/lxd/db"
        "github.com/lxc/lxd/lxd/types"
        "github.com/lxc/lxd/shared"
+       "github.com/lxc/lxd/shared/idmap"
 )
 
 // MigrationStorageSourceDriver defines the functions needed to implement a
@@ -122,7 +123,7 @@ func snapshotProtobufToContainerArgs(containerName string, 
snap *Snapshot) db.Co
        }
 }
 
-func rsyncMigrationSink(live bool, container container, snapshots []*Snapshot, 
conn *websocket.Conn, srcIdmap *shared.IdmapSet, op *operation, containerOnly 
bool) error {
+func rsyncMigrationSink(live bool, container container, snapshots []*Snapshot, 
conn *websocket.Conn, srcIdmap *idmap.IdmapSet, op *operation, containerOnly 
bool) error {
        ourStart, err := container.StorageStart()
        if err != nil {
                return err
diff --git a/lxd/storage_mock.go b/lxd/storage_mock.go
index b8b7e9656..03b390824 100644
--- a/lxd/storage_mock.go
+++ b/lxd/storage_mock.go
@@ -5,8 +5,8 @@ import (
 
        "github.com/gorilla/websocket"
 
-       "github.com/lxc/lxd/shared"
        "github.com/lxc/lxd/shared/api"
+       "github.com/lxc/lxd/shared/idmap"
        "github.com/lxc/lxd/shared/logger"
 )
 
@@ -211,7 +211,7 @@ func (s *storageMock) PreservesInodes() bool {
 func (s *storageMock) MigrationSource(container container, containerOnly bool) 
(MigrationStorageSourceDriver, error) {
        return nil, fmt.Errorf("not implemented")
 }
-func (s *storageMock) MigrationSink(live bool, container container, snapshots 
[]*Snapshot, conn *websocket.Conn, srcIdmap *shared.IdmapSet, op *operation, 
containerOnly bool) error {
+func (s *storageMock) MigrationSink(live bool, container container, snapshots 
[]*Snapshot, conn *websocket.Conn, srcIdmap *idmap.IdmapSet, op *operation, 
containerOnly bool) error {
        return nil
 }
 
diff --git a/lxd/storage_zfs.go b/lxd/storage_zfs.go
index d2e85cb1e..594d0f2ad 100644
--- a/lxd/storage_zfs.go
+++ b/lxd/storage_zfs.go
@@ -17,6 +17,7 @@ import (
        "github.com/lxc/lxd/lxd/util"
        "github.com/lxc/lxd/shared"
        "github.com/lxc/lxd/shared/api"
+       "github.com/lxc/lxd/shared/idmap"
        "github.com/lxc/lxd/shared/logger"
 
        "github.com/pborman/uuid"
@@ -2114,7 +2115,7 @@ func (s *storageZfs) MigrationSource(ct container, 
containerOnly bool) (Migratio
        return &driver, nil
 }
 
-func (s *storageZfs) MigrationSink(live bool, container container, snapshots 
[]*Snapshot, conn *websocket.Conn, srcIdmap *shared.IdmapSet, op *operation, 
containerOnly bool) error {
+func (s *storageZfs) MigrationSink(live bool, container container, snapshots 
[]*Snapshot, conn *websocket.Conn, srcIdmap *idmap.IdmapSet, op *operation, 
containerOnly bool) error {
        poolName := s.getOnDiskPoolName()
        zfsRecv := func(zfsName string, writeWrapper func(io.WriteCloser) 
io.WriteCloser) error {
                zfsFsName := fmt.Sprintf("%s/%s", poolName, zfsName)
diff --git a/lxd/sys/os.go b/lxd/sys/os.go
index d699ad878..420b6e277 100644
--- a/lxd/sys/os.go
+++ b/lxd/sys/os.go
@@ -5,6 +5,7 @@ import (
 
        "github.com/lxc/lxd/lxd/util"
        "github.com/lxc/lxd/shared"
+       "github.com/lxc/lxd/shared/idmap"
        "github.com/lxc/lxd/shared/logger"
 )
 
@@ -16,7 +17,7 @@ type OS struct {
        Architectures []int  // Cache of detected system architectures
        LxcPath       string // Path to the $LXD_DIR/containers directory
        BackingFS     string // Backing filesystem of $LXD_DIR/containers
-       IdmapSet      *shared.IdmapSet
+       IdmapSet      *idmap.IdmapSet
 
        MockMode bool // If true some APIs will be mocked (for testing)
 }
diff --git a/lxd/util/sys.go b/lxd/util/sys.go
index 005a8554a..fa46a5f2b 100644
--- a/lxd/util/sys.go
+++ b/lxd/util/sys.go
@@ -5,7 +5,7 @@ import (
 
        log "gopkg.in/inconshreveable/log15.v2"
 
-       "github.com/lxc/lxd/shared"
+       "github.com/lxc/lxd/shared/idmap"
        "github.com/lxc/lxd/shared/logger"
        "github.com/lxc/lxd/shared/osarch"
 )
@@ -36,14 +36,14 @@ func GetArchitectures() ([]int, error) {
 }
 
 // GetIdmapSet reads the uid/gid allocation.
-func GetIdmapSet() *shared.IdmapSet {
-       idmapSet, err := shared.DefaultIdmapSet()
+func GetIdmapSet() *idmap.IdmapSet {
+       idmapSet, err := idmap.DefaultIdmapSet()
        if err != nil {
                logger.Warn("Error reading default uid/gid map", log.Ctx{"err": 
err.Error()})
                logger.Warnf("Only privileged containers will be able to run")
                idmapSet = nil
        } else {
-               kernelIdmapSet, err := shared.CurrentIdmapSet()
+               kernelIdmapSet, err := idmap.CurrentIdmapSet()
                if err == nil {
                        logger.Infof("Kernel uid/gid map:")
                        for _, lxcmap := range kernelIdmapSet.ToLxcString() {
diff --git a/shared/idmapset_linux.go b/shared/idmap/idmapset_linux.go
similarity index 97%
rename from shared/idmapset_linux.go
rename to shared/idmap/idmapset_linux.go
index da1c59e7e..aa9241c1e 100644
--- a/shared/idmapset_linux.go
+++ b/shared/idmap/idmapset_linux.go
@@ -1,4 +1,4 @@
-package shared
+package idmap
 
 import (
        "bufio"
@@ -11,6 +11,8 @@ import (
        "sort"
        "strconv"
        "strings"
+
+       "github.com/lxc/lxd/shared"
 )
 
 type IdRange struct {
@@ -307,7 +309,7 @@ func (m IdmapSet) ValidRanges() ([]*IdRange, error) {
 
        // Sort the map
        idmap := IdmapSet{}
-       err := DeepCopy(&m, &idmap)
+       err := shared.DeepCopy(&m, &idmap)
        if err != nil {
                return nil, err
        }
@@ -397,7 +399,7 @@ func (m IdmapSet) ToLxcString() []string {
        var lines []string
        for _, e := range m.Idmap {
                for _, l := range e.ToLxcString() {
-                       if !StringInSlice(l+"\n", lines) {
+                       if !shared.StringInSlice(l+"\n", lines) {
                                lines = append(lines, l+"\n")
                        }
                }
@@ -478,7 +480,7 @@ func (set *IdmapSet) doUidshiftIntoContainer(dir string, 
testmode bool, how stri
                        return err
                }
 
-               intUid, intGid, _, _, _, _, err := GetFileStat(path)
+               intUid, intGid, _, _, _, _, err := shared.GetFileStat(path)
                if err != nil {
                        return err
                }
@@ -510,7 +512,7 @@ func (set *IdmapSet) doUidshiftIntoContainer(dir string, 
testmode bool, how stri
                return nil
        }
 
-       if !PathExists(dir) {
+       if !shared.PathExists(dir) {
                return fmt.Errorf("No such file or directory: %q", dir)
        }
 
@@ -650,7 +652,7 @@ func DefaultIdmapSet() (*IdmapSet, error) {
        // Check if shadow's uidmap tools are installed
        newuidmap, _ := exec.LookPath("newuidmap")
        newgidmap, _ := exec.LookPath("newgidmap")
-       if newuidmap != "" && newgidmap != "" && PathExists("/etc/subuid") && 
PathExists("/etc/subgid") {
+       if newuidmap != "" && newgidmap != "" && 
shared.PathExists("/etc/subuid") && shared.PathExists("/etc/subgid") {
                // Parse the shadow uidmap
                entries, err := getFromShadow("/etc/subuid", "root")
                if err != nil {
@@ -788,7 +790,7 @@ func DefaultIdmapSet() (*IdmapSet, error) {
 func CurrentIdmapSet() (*IdmapSet, error) {
        idmapset := new(IdmapSet)
 
-       if PathExists("/proc/self/uid_map") {
+       if shared.PathExists("/proc/self/uid_map") {
                // Parse the uidmap
                entries, err := getFromProc("/proc/self/uid_map")
                if err != nil {
@@ -805,7 +807,7 @@ func CurrentIdmapSet() (*IdmapSet, error) {
                idmapset.Idmap = Extend(idmapset.Idmap, e)
        }
 
-       if PathExists("/proc/self/gid_map") {
+       if shared.PathExists("/proc/self/gid_map") {
                // Parse the gidmap
                entries, err := getFromProc("/proc/self/gid_map")
                if err != nil {
diff --git a/shared/idmapset_linux_test.go b/shared/idmap/idmapset_linux_test.go
similarity index 99%
rename from shared/idmapset_linux_test.go
rename to shared/idmap/idmapset_linux_test.go
index d8582c8d9..9fe466caa 100644
--- a/shared/idmapset_linux_test.go
+++ b/shared/idmap/idmapset_linux_test.go
@@ -1,4 +1,4 @@
-package shared
+package idmap
 
 import (
        "fmt"
diff --git a/shared/idmap/shift_linux.go b/shared/idmap/shift_linux.go
new file mode 100644
index 000000000..b470da4fb
--- /dev/null
+++ b/shared/idmap/shift_linux.go
@@ -0,0 +1,170 @@
+// +build linux
+// +build cgo
+
+package idmap
+
+import (
+       "fmt"
+       "os"
+       "unsafe"
+)
+
+// #cgo LDFLAGS: -lacl
+/*
+#define _GNU_SOURCE
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/acl.h>
+
+int shiftowner(char *basepath, char *path, int uid, int gid) {
+       struct stat sb;
+       int fd, r;
+       char fdpath[PATH_MAX];
+       char realpath[PATH_MAX];
+
+       fd = open(path, O_PATH|O_NOFOLLOW);
+       if (fd < 0 ) {
+               perror("Failed open");
+               return 1;
+       }
+
+       r = sprintf(fdpath, "/proc/self/fd/%d", fd);
+       if (r < 0) {
+               perror("Failed sprintf");
+               close(fd);
+               return 1;
+       }
+
+       r = readlink(fdpath, realpath, PATH_MAX);
+       if (r < 0) {
+               perror("Failed readlink");
+               close(fd);
+               return 1;
+       }
+
+       if (strlen(realpath) < strlen(basepath)) {
+               printf("Invalid path, source (%s) is outside of basepath 
(%s).\n", realpath, basepath);
+               close(fd);
+               return 1;
+       }
+
+       if (strncmp(realpath, basepath, strlen(basepath))) {
+               printf("Invalid path, source (%s) is outside of basepath 
(%s).\n", realpath, basepath);
+               close(fd);
+               return 1;
+       }
+
+       r = fstat(fd, &sb);
+       if (r < 0) {
+               perror("Failed fstat");
+               close(fd);
+               return 1;
+       }
+
+       r = fchownat(fd, "", uid, gid, AT_EMPTY_PATH|AT_SYMLINK_NOFOLLOW);
+       if (r < 0) {
+               perror("Failed chown");
+               close(fd);
+               return 1;
+       }
+
+       if (!S_ISLNK(sb.st_mode)) {
+               r = chmod(fdpath, sb.st_mode);
+               if (r < 0) {
+                       perror("Failed chmod");
+                       close(fd);
+                       return 1;
+               }
+       }
+
+       close(fd);
+       return 0;
+}
+*/
+import "C"
+
+// ShiftOwner updates uid and gid for a file when entering/exiting a namespace
+func ShiftOwner(basepath string, path string, uid int, gid int) error {
+       cbasepath := C.CString(basepath)
+       defer C.free(unsafe.Pointer(cbasepath))
+
+       cpath := C.CString(path)
+       defer C.free(unsafe.Pointer(cpath))
+
+       r := C.shiftowner(cbasepath, cpath, C.int(uid), C.int(gid))
+       if r != 0 {
+               return fmt.Errorf("Failed to change ownership of: %s", path)
+       }
+       return nil
+}
+
+// ShiftACL updates uid and gid for file ACLs when entering/exiting a namespace
+func ShiftACL(path string, shiftIds func(uid int64, gid int64) (int64, int64)) 
error {
+       finfo, err := os.Lstat(path)
+       if err != nil {
+               return err
+       }
+       if finfo.Mode()&os.ModeSymlink != 0 {
+               return nil
+       }
+
+       cpath := C.CString(path)
+       defer C.free(unsafe.Pointer(cpath))
+
+       acl := C.acl_get_file(cpath, C.ACL_TYPE_ACCESS)
+       if acl == nil {
+               return nil
+       }
+       defer C.acl_free(unsafe.Pointer(acl))
+
+       for entryId := C.ACL_FIRST_ENTRY; ; entryId = C.ACL_NEXT_ENTRY {
+               var ent C.acl_entry_t
+               var tag C.acl_tag_t
+               updateACL := false
+
+               ret := C.acl_get_entry(acl, C.int(entryId), &ent)
+               if ret != 1 {
+                       break
+               }
+
+               ret = C.acl_get_tag_type(ent, &tag)
+               if ret == -1 {
+                       return fmt.Errorf("Failed to change ACLs on %s", path)
+               }
+
+               idp := (*C.id_t)(C.acl_get_qualifier(ent))
+               if idp == nil {
+                       continue
+               }
+
+               var newId int64
+               switch tag {
+               case C.ACL_USER:
+                       newId, _ = shiftIds((int64)(*idp), -1)
+                       updateACL = true
+
+               case C.ACL_GROUP:
+                       _, newId = shiftIds(-1, (int64)(*idp))
+                       updateACL = true
+               }
+
+               if updateACL {
+                       ret = C.acl_set_qualifier(ent, unsafe.Pointer(&newId))
+                       if ret == -1 {
+                               return fmt.Errorf("Failed to change ACLs on 
%s", path)
+                       }
+                       ret = C.acl_set_file(cpath, C.ACL_TYPE_ACCESS, acl)
+                       if ret == -1 {
+                               return fmt.Errorf("Failed to change ACLs on 
%s", path)
+                       }
+               }
+       }
+       return nil
+}
diff --git a/shared/util_linux.go b/shared/util_linux.go
index 26389c7ee..77daf1051 100644
--- a/shared/util_linux.go
+++ b/shared/util_linux.go
@@ -19,7 +19,7 @@ import (
        "github.com/lxc/lxd/shared/logger"
 )
 
-// #cgo LDFLAGS: -lutil -lpthread -lacl
+// #cgo LDFLAGS: -lutil -lpthread
 /*
 #define _GNU_SOURCE
 #include <errno.h>
@@ -36,7 +36,6 @@ import (
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/un.h>
-#include <sys/acl.h>
 
 #ifndef AT_SYMLINK_FOLLOW
 #define AT_SYMLINK_FOLLOW    0x400
@@ -129,71 +128,6 @@ void create_pipe(int *master, int *slave) {
        *slave = pipefd[1];
 }
 
-int shiftowner(char *basepath, char *path, int uid, int gid) {
-       struct stat sb;
-       int fd, r;
-       char fdpath[PATH_MAX];
-       char realpath[PATH_MAX];
-
-       fd = open(path, O_PATH|O_NOFOLLOW);
-       if (fd < 0 ) {
-               perror("Failed open");
-               return 1;
-       }
-
-       r = sprintf(fdpath, "/proc/self/fd/%d", fd);
-       if (r < 0) {
-               perror("Failed sprintf");
-               close(fd);
-               return 1;
-       }
-
-       r = readlink(fdpath, realpath, PATH_MAX);
-       if (r < 0) {
-               perror("Failed readlink");
-               close(fd);
-               return 1;
-       }
-
-       if (strlen(realpath) < strlen(basepath)) {
-               printf("Invalid path, source (%s) is outside of basepath 
(%s).\n", realpath, basepath);
-               close(fd);
-               return 1;
-       }
-
-       if (strncmp(realpath, basepath, strlen(basepath))) {
-               printf("Invalid path, source (%s) is outside of basepath 
(%s).\n", realpath, basepath);
-               close(fd);
-               return 1;
-       }
-
-       r = fstat(fd, &sb);
-       if (r < 0) {
-               perror("Failed fstat");
-               close(fd);
-               return 1;
-       }
-
-       r = fchownat(fd, "", uid, gid, AT_EMPTY_PATH|AT_SYMLINK_NOFOLLOW);
-       if (r < 0) {
-               perror("Failed chown");
-               close(fd);
-               return 1;
-       }
-
-       if (!S_ISLNK(sb.st_mode)) {
-               r = chmod(fdpath, sb.st_mode);
-               if (r < 0) {
-                       perror("Failed chmod");
-                       close(fd);
-                       return 1;
-               }
-       }
-
-       close(fd);
-       return 0;
-}
-
 int get_poll_revents(int lfd, int timeout, int flags, int *revents, int 
*saved_errno)
 {
        int ret;
@@ -239,83 +173,6 @@ func GetPollRevents(fd int, timeout int, flags int) (int, 
int, error) {
        return int(ret), int(revents), err
 }
 
-func ShiftOwner(basepath string, path string, uid int, gid int) error {
-       cbasepath := C.CString(basepath)
-       defer C.free(unsafe.Pointer(cbasepath))
-
-       cpath := C.CString(path)
-       defer C.free(unsafe.Pointer(cpath))
-
-       r := C.shiftowner(cbasepath, cpath, C.int(uid), C.int(gid))
-       if r != 0 {
-               return fmt.Errorf("Failed to change ownership of: %s", path)
-       }
-       return nil
-}
-
-func ShiftACL(path string, shiftIds func(uid int64, gid int64) (int64, int64)) 
error {
-       finfo, err := os.Lstat(path)
-       if err != nil {
-               return err
-       }
-       if finfo.Mode()&os.ModeSymlink != 0 {
-               return nil
-       }
-
-       cpath := C.CString(path)
-       defer C.free(unsafe.Pointer(cpath))
-
-       acl := C.acl_get_file(cpath, C.ACL_TYPE_ACCESS)
-       if acl == nil {
-               return nil
-       }
-       defer C.acl_free(unsafe.Pointer(acl))
-
-       for entryId := C.ACL_FIRST_ENTRY; ; entryId = C.ACL_NEXT_ENTRY {
-               var ent C.acl_entry_t
-               var tag C.acl_tag_t
-               updateACL := false
-
-               ret := C.acl_get_entry(acl, C.int(entryId), &ent)
-               if ret != 1 {
-                       break
-               }
-
-               ret = C.acl_get_tag_type(ent, &tag)
-               if ret == -1 {
-                       return fmt.Errorf("Failed to change ACLs on %s", path)
-               }
-
-               idp := (*C.id_t)(C.acl_get_qualifier(ent))
-               if idp == nil {
-                       continue
-               }
-
-               var newId int64
-               switch tag {
-               case C.ACL_USER:
-                       newId, _ = shiftIds((int64)(*idp), -1)
-                       updateACL = true
-
-               case C.ACL_GROUP:
-                       _, newId = shiftIds(-1, (int64)(*idp))
-                       updateACL = true
-               }
-
-               if updateACL {
-                       ret = C.acl_set_qualifier(ent, unsafe.Pointer(&newId))
-                       if ret == -1 {
-                               return fmt.Errorf("Failed to change ACLs on 
%s", path)
-                       }
-                       ret = C.acl_set_file(cpath, C.ACL_TYPE_ACCESS, acl)
-                       if ret == -1 {
-                               return fmt.Errorf("Failed to change ACLs on 
%s", path)
-                       }
-               }
-       }
-       return nil
-}
-
 func OpenPty(uid, gid int64) (master *os.File, slave *os.File, err error) {
        fd_master := C.int(-1)
        fd_slave := C.int(-1)
_______________________________________________
lxc-devel mailing list
[email protected]
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to