Skip to content

Flags builder #44

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

Open
wants to merge 30 commits into
base: master
Choose a base branch
from
Open

Flags builder #44

wants to merge 30 commits into from

Conversation

cehteh
Copy link
Contributor

@cehteh cehteh commented Apr 29, 2021

First part of the flags builder as I sketched in #29, next commit will add a flags-builder for member functions.

cehteh added 26 commits April 17, 2021 21:06
This anticipates the statx() interface I'll add soon.

Breaking change: Adds a 'SimpleType::Unknown' which can be returned when the filetype can't be
determinded. Code matching on SimpleType may add a clause for this when there is no catch-all.
dir.list() consumes the dir and creates a DirIter. The underlying 'dup()' operation now
becomes explicit, one may need to call try_clone() first.

the list_self() and list_dir() using this now but are merely convinience wrappers and may (or
may not) deprecated in future.

Rationale: this simplifies the code a bit (list::open_dir() removed) and is closer to the low
level semantics.
* Forgot to forget the Dir handle, thus it would been dropped.
* On linux O_PATH was passed when Dir descriptors where opened. This is generally a good thing
  but broke the refactored list(). This also shown that O_PATH has different enough semantics
  to be problematic vs. opening handles without (as on other OS'es). Changed this to
  Dir::open() and Dir::sub_dir() default to opening without O_PATH (but O_DIRECTORY see
  remarks).
* added Dir::open_path() and Dir::sub_dir_path() with O_PATH (urgh, better idea
  for naming? open_protected() or something like that?) which offer the O_PATH feature on linux.
'Lite' file descriptors are possibly a better naming of what O_PATH does. This introduces then and
implements them portable. On systems which do not support O_PATH normal file descriptors are
used.
* With FdType/fd_type() one can determine the kind of an underlying file descriptor.
  Lite descriptors are implemented only in Linux (for now).
  When O_DIRECTORY is supported it uses fcntl() in favo over stat()

* clone_dirfd() tries to do 'the right thing' for duplicating FD's

* libc_ok() is a simple wraper for libc calls that return -1 on error, I will refactor the
  code in the next commits to make use of that more.

Please test this! So far it works for me on Linux.
This simplifies the code a bit, in 'release' the same output is generated.
debug builds may not inline the libc_ok() and be slightly larger.
This up/downgrade cloning converts into normal/lite handles which was missing before.

I hope this fixes tailhook#34 finally.
the d_ino field is mandatory in POSIX and clients (me) really need it when passing data
around. Keeping it in the Entry saves an extra stat()/metadata query.
Instead compiling conditionally on the target_os this defines features for every aspect that
can be different. Tested only on linux so far. Eventually the presence/absence of these
features should be determined by a build.rs script.

Meanwhile there are OS specific lists (only linux so far, please contribute more) which can be
activated when building with '--feature osname'.
This should resolve tailhook#27. It does not fix it by adding a expensive stat() check on opening, but by
giving the opportunity to explicitly check a Dir handle. When really required a programmer can
enforce consistency between platforms by using 'is_dir()'. Failing to do so won't cause any
harm because improper handles (on platforms without O_DIRECTORY) would report errors at later
time.

This also removes the test_open_file() test from the testsuite, as it depended on presence of
O_DIRECTORY which makes he testsuite non deterministic testing only where its oblivious that
the OS wouldn't open files as directories.
Allows to build/pass custom flags when opening a 'Dir', see tests/flagsbuilder.rs

Should fix/conclude tailhook#29

Notice: this removes the 'const BASE_OPEN_FLAGS' as it makes flags handling a bit more
elaborate:
 1. DirFlags is created with 'O_CLOEXEC' (I considered O_NOFOLLOW but turned that down)
 2. The user may modify the flags to his liking
 3. The final open() calls will set the required flags (O_DIRECTORY, O_PATH)

All functions that used BASE_OPEN_FLAGS fixed up, but semantics stay the same.
having Dir::new() returning DirFlags and not Dir would be a tpp surprising API
With this it becomes possible to construct and pass open flags to the various member
functions. Also list_self() and list_dir() will use O_SEARCH when supported.

Other than the Dir flags builder, this flags builder for member functions defaults to
O_NOFOLLOW (and O_CLOEXEC) to prevent symlink attacks by default. When this is not desired one
can still clear O_NOFOLLOW.
@cehteh cehteh marked this pull request as ready for review April 30, 2021 14:40
@cehteh
Copy link
Contributor Author

cehteh commented Apr 30, 2021

Thats it! I am finished for now (some improvements are noted and postponed). Otherwise the recent PR's from me should improve the usability and fix some of the open issues (#34, #29, #27). I looking forward for review/comments and getting those merged because I want to use this in my own software and don't want to maintain a fork of 'openat'.

Cheers
Christian

With the flags builder the 'open_lite()' I introduced earlier can be removed. 'Dir::open(),
sub_dir()' defaults to include O_PATH when available as before. The flags builder does NOT include
O_PATH. 'Dir::list_self()' and 'Dir::list_dir()' already clone-upgrade the handle that removes
the O_PATH flag and thus will be not affected.

'Dir::list()' may fail when called with a Dir that is opened with O_PATH and the OS (linux)
does not support listing.
This allows portable access to these flags. When not supported by the OS the value is 0. An
Application can thus just use these definitions with the flags builder as well as doing
runtime checks by comparing them against 0.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant