git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH 2/2] git: continue alias lookup on EACCES errors

From
Jeff King <peff@peff.net>
Date
Mar 28, 2012, 21:04 UTC
Message-ID
<20120328210407.GC10174@sigill.intra.peff.net>
In-Reply-To
<7vzkb0tq10.fsf@alter.siamese.dyndns.org>
On Wed, Mar 28, 2012 at 01:43:39PM -0700, Junio C Hamano wrote:
Show 10 quoted lines
> > +	while (1) {
> > +		const char *end = strchrnul(p, ':');
> > +		const char *path;
> > +		struct stat st;
> > +
> > +		path = mkpath("%.*s/%s", (int)(end - p), p, file);
> 
> Given PATH=":/usr/bin:/bin" and file "frotz" (please call it "cmd" or
> something, by the way), end points at the first colon and path becomes
> "/frotz".  Oops?

Ugh, yeah. This is what I meant when I said "checking afterwards basically means re-implementing execvp". :)

Regarding the name, I pulled it from the linux-manpages execvp(3), since this is supposed to be compatible. POSIX uses the even worse "path" as the first element. But there is no reason we have to follow those naming conventions.

Show 9 quoted lines
> > +int sane_execvp(const char *file, char * const argv[])
> > +{
> > +	int ret = execvp(file, argv);
> > +	if (ret < 0 && errno == EACCES && !file_in_path_is_nonexecutable(file))
> > +		errno = ENOENT;
> > +	return ret;
> 
> Double negation makes my head hurt, but unfortunately, we cannot rename it
> to "executable_exists_on_path()" and negate its return value.

Right, technically it could exist in two places, and we care about finding the first one.

In practice, I think we can just do exists_on_path() and not even worry about the executable bit. If it exists, execvp did not run it, and we got EACCES, then it is not executable. Any other error would trump EACCES (i.e., execvp would have returned immediately; with EACCES it waits until it has processed all entries before returning EACCES).

I actually think this would be easier to read if we simply re-implemented execvp.

Show 10 quoted lines
> Anyway, the logic is to set errno to ENOENT when
> 
>  - We tried to exec, and got EACCES; and
>  - There is a file on the PATH that lacks executable bit.
> 
> In such a case, the error from execvp() is not about the file it tried to
> execute lacked executable bit, but there was nothing that match the name,
> but it couldn't be certain because some directories were not readable.
> 
> OK.  I think I can follow that logic.

I think you are backwards. There is _no_ file on the PATH that lacks the executable bit, and therefore the error is about an inaccessible directory.

You could also search for an inaccessible directory, but that is not quite right. If you have an inaccessible directory _and_ a matching file with no executable bit, then you would make the wrong assumption.

Show 22 quoted lines
> If there are more than one entry on PATH, and a system call made during
> first round of the loop fails but a later round finds a non-executable
> file, i.e.
> 
> 	$ PATH=/nosuch:/home/peff/bin; export PATH
>         $ >/home/peff/bin/frotz; chmod -x /home/peff/bin/frotz
>         git frotz
> 
> we would get EACCES from execvp(), the first round runs stat("/nosuch/frotz")
> and sets errno to ENOTDIR, and the second round runs stat() and access()
> on "/home/peff/bin/frotz" and returns 1 to say "Yeah, there is a plain
> file frotz that cannot be executed".
> 
> And sane_execvp() will return ENOTDIR?
>
> So sane_execvp() would probably need to do a bit more (but not that much).
> 
> 	if (ret < 0 && errno == EACCES)
> 		errno = file_in_path_is_nonexecutable(file) ? EACCES : ENOENT;
> 	return ret;
> 
> or something.

Good point. We definitely need to save the EACCES errno across the second round lookup.

-Peff
Previous: Junio C HamanoNext: Junio C Hamano
Message 29 of 47 in “Bug? Bad permissions in $PATH breaks Git aliases”
  1. James PickensMar 26, 2012
  2. Jeff KingMar 27, 2012
  3. James PickensMar 27, 2012
  4. Junio C HamanoMar 27, 2012
  5. Jeff KingMar 27, 2012
  6. 1/2 run-command: propagate EACCES errors to parentJeff King, Mar 27, 2012
  7. Junio C HamanoMar 27, 2012
  8. Jeff KingMar 27, 2012
  9. 2/2 git: continue alias lookup on EACCES errorsJeff King, Mar 27, 2012
  10. Junio C HamanoMar 27, 2012
  11. Jeff KingMar 28, 2012
  12. Junio C HamanoMar 28, 2012
  13. Jeff KingMar 28, 2012
  14. Jonathan NiederMar 28, 2012
  15. Junio C HamanoMar 28, 2012
  16. Jonathan NiederMar 28, 2012
  17. Jeff KingMar 28, 2012
  18. Jonathan NiederMar 28, 2012
  19. Jeff KingMar 28, 2012
  20. Jeff KingMar 28, 2012
  21. Jonathan NiederMar 28, 2012
  22. Jeff KingMar 28, 2012
  23. Jonathan NiederMar 28, 2012
  24. Jeff KingMar 28, 2012
  25. Jonathan NiederMar 28, 2012
  26. Jeff KingMar 28, 2012
  27. Frans KlaverMar 28, 2012
  28. Junio C HamanoMar 28, 2012
  29. Jeff KingMar 28, 2012
  30. Junio C HamanoMar 28, 2012
  31. Jeff KingMar 28, 2012
  32. Jeff KingMar 28, 2012
  33. Junio C HamanoMar 28, 2012
  34. Frans KlaverMar 29, 2012
  35. Jeff KingMar 29, 2012
  36. Frans KlaverMar 29, 2012
  37. Jeff KingMar 28, 2012
  38. Junio C HamanoMar 28, 2012
  39. Jeff KingMar 28, 2012
  40. Frans KlaverMar 29, 2012
  41. Jeff KingMar 29, 2012
  42. Frans KlaverMar 29, 2012
  43. Johannes SixtMar 27, 2012
  44. James PickensMar 27, 2012
  45. Junio C HamanoMar 27, 2012
  46. James PickensMar 27, 2012
  47. Junio C HamanoMar 27, 2012

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.