On Thu, Mar 12, 2020 at 9:56 AM David Howells <dhowells@xxxxxxxxxx> wrote: > > Any thoughts on which set of flags should override the other? Do we need to care? I don't think we actually have conflicts, because the semantics aren't the same, and they are about independent issues. > If we're making > RESOLVE_* flags the new definitive interface, then I feel they should probably > override the AT_* flags where there's a conflict, ie. RESOLVE_NO_SYMLINKS > should override AT_SYMLINK_FOLLOW for example. That's just for a linkat2() system call? I think the natural semantic is the one that falls out directly: RESOLVE_NO_SYMLINKS will cause it to fail with -ELOOP if it is a symlink. NOTE! This isn't really a "conflict". It's actually two different and independent things: - without AT_SYMLINK_FOLLOW, a linkat() simply won't even try to follow the symlink, and will link to the symlink itself instead. - RESOLVE_NO_SYMLINKS says "never follow symlinks". Note how one does *NOT* override the other, quite the reverse. They are about different things. One is about the _behavior_ when the last component is a symlink, and the other is about permission to follow any symlinks. So all combinations make sense: - no AT_SYMLINK_FOLLOW, no RESOLVE_NO_SYMLINKS: just link to the target, whether it's a symlink or not This is obviously our historical link() behavior. - no AT_SYMLINK_FOLLOW, yes RESOLVE_NO_SYMLINKS: just link to the target, whether it's a symlink or not, but if there's a symlink in the middle, return -ELOOP Note how this case doesn't follow the last one, so RESOLVE_NO_SYMLINKS isn't an issue for the last component, but _is_ an issue for the components in the middle. - AT_SYMLINK_FOLLOW, no RESOLVE_NO_SYMLINKS: just link to the target, following the symlink if it exists This is obviously the historical AT_SYMLINK_FOLLOW behavior - AT_SYMLINK_FOLLOW | RESOLVE_NO_SYMLINKS: just link to the target, return -ELOOP if it's a symlink (of if there's a symlink on the way). This is the natural behavior for "refuse to follow any symlinks anywhere". note how they are all completely sane versions, and in no case does one flag really override the other. If anything, we actually miss a third flag: the "don't allow linking to a final symlink at all" (but allow intermediate symlinks). We've never had that behavior, although I think POSIX makes that case undefined (ie you're not guaranteed to be able to link to a symlink in the first place in POSIX). I guess that third case could be emulated with open(O_PATH) + fstat to check it's not a symlink + linkat(fd,AT_EMPTY_PATH) if it turns somebody would want something like that (and we decided that AT_EMPTY_PATH is ok for linkat()). I doubt anybody cares. Linus