github.com/portworx/docker@v1.12.1/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  }