-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fileutils: Use ModeType as the mask for mode checks #3
Conversation
11f4828
to
e48df7f
Compare
Hang on, I'm going to drop some of these |
POSIX provides S_IS*(m) macros to portably interpret the mode type, but does not define values for each type [1]. Alban pointed out that st_mode is not a bitfield on Linux [2]. For example, Linux defines [3]: S_IFBLK 060000 S_IFDIR 040000 S_IFCHR 020000 So 'm&S_IFCHR == S_IFCHR', for example, would succeed for both character and block devices. Go translates the system values to a platform-agnostic bitfield [4], so the previous approach works on Go. But it may be confusing for people used to the native non-bitfield mode, so this commit moves us to an approach that does not rely on Go's using a bitfield. I've also dropped the 07000 portion of the previous 07777 mask in favor of the cross-platform ModePerm mask. This avoids an internal magic number, and the sticky, suid, and sgid bits don't make sense for device nodes. And I'm using some contants from os instead of their syscall analogs. We can't drop the syscall dependency, because we're still using syscall to construct the Mknod arguments, but with this commit we're no longer using it to inspect the source file type. [1]: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_stat.h.html [2]: opencontainers/runtime-tools#308 (comment) [3]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/stat.h?h=v4.16#n9 [4]: https://github.com/golang/go/blob/b0d437f866eb8987cde7e6550cacd77876f36d4b/src/os/types.go#L45
e48df7f
to
8bad3ca
Compare
Ok, I've pushed that along a bit with e48df7f → 8bad3ca. Let me know if you like that as it stands, or if you'd like me to restore some of the |
@mrunalp PTAL |
LGTM |
Thanks! Do you think it's worth considering tagging a |
In case there are no users except runc, I'd rather merge this one to runc. Easier to maintain that way. |
@kolyshkin this might help checking who uses it; https://grep.app/search?q=%22github.com/mrunalp/fileutils%22&filter[lang][0]=Go |
This subtle bug keeps lurking in because error checking for `Mkdir()` and `MkdirAll()` is slightly different wrt `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. This commit removes ignoring the IsExist error, as it should not be 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 mrunalp#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 mrunalp#1, IsExist check after MkdirAll is not needed. Because of mrunalp#2 and mrunalp#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>
POSIX provides
S_IS*(m)
macros to portably interpret the mode type, but does not define values for each type. @alban pointed out thatst_mode
is not a bitfield on Linux 1. For example, Linux defines:So
m&S_IFCHR == S_IFCHR
, for example, would succeed for both character and block devices. Go translates the system values to a platform-agnostic bitfield, so the previous approach works on Go. But it may be confusing for people used to the native non-bitfield mode, so this pull request moves us to an approach that does not rely on Go's using a bitfield.