github.com/endophage/docker@v1.4.2-0.20161027011718-242853499895/pkg/idtools/idtools_unix.go (about)

     1  // +build !windows
     2  
     3  package idtools
     4  
     5  import (
     6  	"os"
     7  	"path/filepath"
     8  
     9  	"github.com/docker/docker/pkg/system"
    10  )
    11  
    12  func mkdirAs(path string, mode os.FileMode, ownerUID, ownerGID int, mkAll, chownExisting bool) error {
    13  	// make an array containing the original path asked for, plus (for mkAll == true)
    14  	// all path components leading up to the complete path that don't exist before we MkdirAll
    15  	// so that we can chown all of them properly at the end.  If chownExisting is false, we won't
    16  	// chown the full directory path if it exists
    17  	var paths []string
    18  	if _, err := os.Stat(path); err != nil && os.IsNotExist(err) {
    19  		paths = []string{path}
    20  	} else if err == nil && chownExisting {
    21  		if err := os.Chown(path, ownerUID, ownerGID); err != nil {
    22  			return err
    23  		}
    24  		// short-circuit--we were called with an existing directory and chown was requested
    25  		return nil
    26  	} else if err == nil {
    27  		// nothing to do; directory path fully exists already and chown was NOT requested
    28  		return nil
    29  	}
    30  
    31  	if mkAll {
    32  		// walk back to "/" looking for directories which do not exist
    33  		// and add them to the paths array for chown after creation
    34  		dirPath := path
    35  		for {
    36  			dirPath = filepath.Dir(dirPath)
    37  			if dirPath == "/" {
    38  				break
    39  			}
    40  			if _, err := os.Stat(dirPath); err != nil && os.IsNotExist(err) {
    41  				paths = append(paths, dirPath)
    42  			}
    43  		}
    44  		if err := system.MkdirAll(path, mode); err != nil && !os.IsExist(err) {
    45  			return err
    46  		}
    47  	} else {
    48  		if err := os.Mkdir(path, mode); err != nil && !os.IsExist(err) {
    49  			return err
    50  		}
    51  	}
    52  	// even if it existed, we will chown the requested path + any subpaths that
    53  	// didn't exist when we called MkdirAll
    54  	for _, pathComponent := range paths {
    55  		if err := os.Chown(pathComponent, ownerUID, ownerGID); err != nil {
    56  			return err
    57  		}
    58  	}
    59  	return nil
    60  }
    61  
    62  // CanAccess takes a valid (existing) directory and a uid, gid pair and determines
    63  // if that uid, gid pair has access (execute bit) to the directory
    64  func CanAccess(path string, uid, gid int) bool {
    65  	statInfo, err := system.Stat(path)
    66  	if err != nil {
    67  		return false
    68  	}
    69  	fileMode := os.FileMode(statInfo.Mode())
    70  	permBits := fileMode.Perm()
    71  	return accessible(statInfo.UID() == uint32(uid),
    72  		statInfo.GID() == uint32(gid), permBits)
    73  }
    74  
    75  func accessible(isOwner, isGroup bool, perms os.FileMode) bool {
    76  	if isOwner && (perms&0100 == 0100) {
    77  		return true
    78  	}
    79  	if isGroup && (perms&0010 == 0010) {
    80  		return true
    81  	}
    82  	if perms&0001 == 0001 {
    83  		return true
    84  	}
    85  	return false
    86  }