Previously:
1. last_error wouldn't be updated with errors from is_dir;
2. We'd always issue a stat(), even for binaries without execute;
3. We used stat() instead of access(), which is cheaper.
This change avoids all of those, by only checking inside X_OK-positive
case whether access() works on the path with an extra slash appended.
Thanks to Lennart for the suggestion.
(cherry picked from commit
33e1a5d8d3f792e1d98377fe439e123231032ec7)
Gbp-Pq: Name path-Improve-PATH-search-directory-case.patch
if (!j)
return -ENOMEM;
- if (is_dir(j, true))
- continue;
-
if (access(j, X_OK) >= 0) {
- /* Found it! */
+ _cleanup_free_ char *with_dash;
- if (ret)
- *ret = path_simplify(TAKE_PTR(j), false);
+ with_dash = strjoin(j, "/");
+ if (!with_dash)
+ return -ENOMEM;
- return 0;
+ /* If this passes, it must be a directory, and so should be skipped. */
+ if (access(with_dash, X_OK) >= 0)
+ continue;
+
+ /**
+ * We can't just `continue` inverting this case, since we need to update last_error.
+ */
+ if (errno == ENOTDIR) {
+ /* Found it! */
+ if (ret)
+ *ret = path_simplify(TAKE_PTR(j), false);
+
+ return 0;
+ }
}
/* PATH entries which we don't have access to are ignored, as per tradition. */