github.com/hooklift/nomad@v0.5.7-0.20170407200202-db11e7dd7b55/client/allocdir/fs_unix.go (about)

     1  // +build darwin dragonfly freebsd linux netbsd openbsd solaris
     2  
     3  package allocdir
     4  
     5  import (
     6  	"fmt"
     7  	"os"
     8  	"os/user"
     9  	"path/filepath"
    10  	"strconv"
    11  
    12  	"golang.org/x/sys/unix"
    13  )
    14  
    15  var (
    16  	// SharedAllocContainerPath is the path inside container for mounted
    17  	// directory shared across tasks in a task group.
    18  	SharedAllocContainerPath = filepath.Join("/", SharedAllocName)
    19  
    20  	// TaskLocalContainer is the path inside a container for mounted directory
    21  	// for local storage.
    22  	TaskLocalContainerPath = filepath.Join("/", TaskLocal)
    23  
    24  	// TaskSecretsContainerPath is the path inside a container for mounted
    25  	// secrets directory
    26  	TaskSecretsContainerPath = filepath.Join("/", TaskSecrets)
    27  )
    28  
    29  // dropDirPermissions gives full access to a directory to all users and sets
    30  // the owner to nobody.
    31  func dropDirPermissions(path string) error {
    32  	if err := os.Chmod(path, 0777); err != nil {
    33  		return fmt.Errorf("Chmod(%v) failed: %v", path, err)
    34  	}
    35  
    36  	// Can't change owner if not root.
    37  	if unix.Geteuid() != 0 {
    38  		return nil
    39  	}
    40  
    41  	u, err := user.Lookup("nobody")
    42  	if err != nil {
    43  		return err
    44  	}
    45  
    46  	uid, err := getUid(u)
    47  	if err != nil {
    48  		return err
    49  	}
    50  
    51  	gid, err := getGid(u)
    52  	if err != nil {
    53  		return err
    54  	}
    55  
    56  	if err := os.Chown(path, uid, gid); err != nil {
    57  		return fmt.Errorf("Couldn't change owner/group of %v to (uid: %v, gid: %v): %v", path, uid, gid, err)
    58  	}
    59  
    60  	return nil
    61  }
    62  
    63  // getUid for a user
    64  func getUid(u *user.User) (int, error) {
    65  	uid, err := strconv.Atoi(u.Uid)
    66  	if err != nil {
    67  		return 0, fmt.Errorf("Unable to convert Uid to an int: %v", err)
    68  	}
    69  
    70  	return uid, nil
    71  }
    72  
    73  // getGid for a user
    74  func getGid(u *user.User) (int, error) {
    75  	gid, err := strconv.Atoi(u.Gid)
    76  	if err != nil {
    77  		return 0, fmt.Errorf("Unable to convert Gid to an int: %v", err)
    78  	}
    79  
    80  	return gid, nil
    81  }
    82  
    83  // linkOrCopy attempts to hardlink dst to src and fallsback to copying if the
    84  // hardlink fails.
    85  func linkOrCopy(src, dst string, perm os.FileMode) error {
    86  	// Avoid link/copy if the file already exists in the chroot
    87  	// TODO 0.6 clean this up. This was needed because chroot creation fails
    88  	// when a process restarts.
    89  	if fileInfo, _ := os.Stat(dst); fileInfo != nil {
    90  		return nil
    91  	}
    92  	// Attempt to hardlink.
    93  	if err := os.Link(src, dst); err == nil {
    94  		return nil
    95  	}
    96  
    97  	return fileCopy(src, dst, perm)
    98  }