2018-02-05 21:05:59 +00:00
|
|
|
package idtools // import "github.com/docker/docker/pkg/idtools"
|
2015-10-14 18:35:48 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"os"
|
|
|
|
|
|
|
|
"github.com/docker/docker/pkg/system"
|
|
|
|
)
|
|
|
|
|
2017-11-16 06:20:33 +00:00
|
|
|
// This is currently a wrapper around MkdirAll, however, since currently
|
|
|
|
// permissions aren't set through this path, the identity isn't utilized.
|
|
|
|
// Ownership is handled elsewhere, but in the future could be support here
|
|
|
|
// too.
|
|
|
|
func mkdirAs(path string, mode os.FileMode, owner Identity, mkAll, chownExisting bool) error {
|
Simplify/fix MkdirAll usage
This subtle bug keeps lurking in because error checking for `Mkdir()`
and `MkdirAll()` is slightly different wrt to `EEXIST`/`IsExist`:
- for `Mkdir()`, `IsExist` error should (usually) be ignored
(unless you want to make sure directory was not there before)
as it means "the destination directory was already there"
- for `MkdirAll()`, `IsExist` error should NEVER be ignored.
Mostly, this commit just removes ignoring the IsExist error, as it
should not be ignored.
Also, there are a couple of cases then IsExist is handled as
"directory already exist" which is wrong. As a result, some code
that never worked as intended is now removed.
NOTE that `idtools.MkdirAndChown()` behaves like `os.MkdirAll()`
rather than `os.Mkdir()` -- so its description is amended accordingly,
and its usage is handled as such (i.e. IsExist error is not ignored).
For more details, a quote from my runc commit 6f82d4b (July 2015):
TL;DR: check for IsExist(err) after a failed MkdirAll() is both
redundant and wrong -- so two reasons to remove it.
Quoting MkdirAll documentation:
> MkdirAll creates a directory named path, along with any necessary
> parents, and returns nil, or else returns an error. If path
> is already a directory, MkdirAll does nothing and returns nil.
This means two things:
1. If a directory to be created already exists, no error is
returned.
2. If the error returned is IsExist (EEXIST), it means there exists
a non-directory with the same name as MkdirAll need to use for
directory. Example: we want to MkdirAll("a/b"), but file "a"
(or "a/b") already exists, so MkdirAll fails.
The above is a theory, based on quoted documentation and my UNIX
knowledge.
3. In practice, though, current MkdirAll implementation [1] returns
ENOTDIR in most of cases described in #2, with the exception when
there is a race between MkdirAll and someone else creating the
last component of MkdirAll argument as a file. In this very case
MkdirAll() will indeed return EEXIST.
Because of #1, IsExist check after MkdirAll is not needed.
Because of #2 and #3, ignoring IsExist error is just plain wrong,
as directory we require is not created. It's cleaner to report
the error now.
Note this error is all over the tree, I guess due to copy-paste,
or trying to follow the same usage pattern as for Mkdir(),
or some not quite correct examples on the Internet.
[1] https://github.com/golang/go/blob/f9ed2f75/src/os/path.go
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2017-09-25 19:39:36 +00:00
|
|
|
if err := system.MkdirAll(path, mode, ""); err != nil {
|
2015-10-14 18:35:48 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
2016-08-23 16:49:13 +00:00
|
|
|
|
|
|
|
// CanAccess takes a valid (existing) directory and a uid, gid pair and determines
|
|
|
|
// if that uid, gid pair has access (execute bit) to the directory
|
|
|
|
// Windows does not require/support this function, so always return true
|
2017-11-16 06:20:33 +00:00
|
|
|
func CanAccess(path string, identity Identity) bool {
|
2016-08-23 16:49:13 +00:00
|
|
|
return true
|
|
|
|
}
|