@@ -401,18 +401,40 @@ static bool bfs_resolve_relative(const struct bfs_resolver *res) {
401401 return false;
402402}
403403
404+ /** Check if the actions include fchdir(). */
405+ static bool bfs_spawn_will_chdir (const struct bfs_spawn * ctx ) {
406+ if (ctx ) {
407+ for_slist (const struct bfs_spawn_action , action , ctx ) {
408+ if (action -> op == BFS_SPAWN_FCHDIR ) {
409+ return true;
410+ }
411+ }
412+ }
413+
414+ return false;
415+ }
416+
417+ /** Check if we can call xfaccessat() before file actions. */
418+ static bool bfs_can_access_early (const struct bfs_resolver * res , const struct bfs_spawn * ctx ) {
419+ if (res -> exe [0 ] == '/' ) {
420+ return true;
421+ }
422+
423+ if (bfs_spawn_will_chdir (ctx )) {
424+ return false;
425+ }
426+
427+ return true;
428+ }
429+
404430/** Check if we can resolve the executable before file actions. */
405431static bool bfs_can_resolve_early (const struct bfs_resolver * res , const struct bfs_spawn * ctx ) {
406432 if (!bfs_resolve_relative (res )) {
407433 return true;
408434 }
409435
410- if (ctx ) {
411- for_slist (const struct bfs_spawn_action , action , ctx ) {
412- if (action -> op == BFS_SPAWN_FCHDIR ) {
413- return false;
414- }
415- }
436+ if (bfs_spawn_will_chdir (ctx )) {
437+ return false;
416438 }
417439
418440 return true;
@@ -442,17 +464,19 @@ static int bfs_resolve_early(struct bfs_resolver *res, const char *exe, const st
442464 };
443465
444466 if (bfs_can_skip_resolve (res , ctx )) {
445- // Do this check eagerly, even though posix_spawn()/execv() also
446- // would, because:
447- //
448- // - faccessat() is faster than fork()/clone() + execv()
449- // - posix_spawn() is not guaranteed to report ENOENT
450- if (xfaccessat (AT_FDCWD , exe , X_OK ) == 0 ) {
451- res -> done = true;
452- return 0 ;
453- } else {
454- return -1 ;
467+ if (bfs_can_access_early (res , ctx )) {
468+ // Do this check eagerly, even though posix_spawn()/execv() also
469+ // would, because:
470+ //
471+ // - faccessat() is faster than fork()/clone() + execv()
472+ // - posix_spawn() is not guaranteed to report ENOENT
473+ if (xfaccessat (AT_FDCWD , exe , X_OK ) != 0 ) {
474+ return -1 ;
475+ }
455476 }
477+
478+ res -> done = true;
479+ return 0 ;
456480 }
457481
458482 res -> path = getenv ("PATH" );
0 commit comments