chase: check the result is a directory or regular file only when the resolved path exists

Otherwise, if it is called with CHASE_NONEXISTENT, when we call
stat_verify_directory()/_regular() the struct stat is for one of the
parent directory, rather than for the result path.

With this change, we can safely specify CHASE_MUST_BE_DIRECTORY/REGULAR
with CHASE_NONEXISTENT.

More importantly, chaseat() internally sets CHASE_MUST_BE_DIRECTORY when
the input path ends with "/", "/,", "/..". Hence, without this change,
we cannot specify CHASE_NONEXISTENT safely.

Follow-up for 90b9f7a07e.
This commit is contained in:
Yu Watanabe
2025-07-29 03:37:48 +09:00
parent be876c5933
commit 1cabb6905b
+11 -9
View File
@@ -509,16 +509,18 @@ int chaseat(int dir_fd, const char *path, ChaseFlags flags, char **ret_path, int
close_and_replace(fd, child);
}
if (FLAGS_SET(flags, CHASE_MUST_BE_DIRECTORY)) {
r = stat_verify_directory(&st);
if (r < 0)
return r;
}
if (exists) {
if (FLAGS_SET(flags, CHASE_MUST_BE_DIRECTORY)) {
r = stat_verify_directory(&st);
if (r < 0)
return r;
}
if (FLAGS_SET(flags, CHASE_MUST_BE_REGULAR)) {
r = stat_verify_regular(&st);
if (r < 0)
return r;
if (FLAGS_SET(flags, CHASE_MUST_BE_REGULAR)) {
r = stat_verify_regular(&st);
if (r < 0)
return r;
}
}
if (ret_path) {