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