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

Re: [PATCH] Provide a dirname() function when NO_LIBGEN_H=YesPlease

From
Junio C Hamano <gitster@pobox.com>
Date
Sep 30, 2015, 18:24 UTC
Message-ID
<xmqq8u7n934i.fsf@gitster.mtv.corp.google.com>
In-Reply-To
<25a2598e756959f55f06ae6b4dc6f448e3b6b127.1443624188.git.johannes.schindelin@gmx.de>
Johannes Schindelin <johannes.schindelin@gmx.de> writes:
Show 5 quoted lines
> 	I stumbled over the compile warning when upgrading Git for Windows
> 	to 2.6.0. There was a left-over NO_LIBGEN_H=YesPlease (which we
> 	no longer need in Git for Windows 2.x), but it did point to the
> 	fact that we use `dirname()` in builtin/am.c now, so we better
> 	have a fall-back implementation for platforms without libgen.h.
Thanks for being careful.
Show 24 quoted lines
>
> 	I tested this implementation a bit, but I still would appreciate
> 	a few eye-balls to go over it.
>
>  compat/basename.c | 26 ++++++++++++++++++++++++++
>  git-compat-util.h |  2 ++
>  2 files changed, 28 insertions(+)
>
> diff --git a/compat/basename.c b/compat/basename.c
> index d8f8a3c..10dba38 100644
> --- a/compat/basename.c
> +++ b/compat/basename.c
> @@ -13,3 +13,29 @@ char *gitbasename (char *path)
>  	}
>  	return (char *)base;
>  }
> +
> +char *gitdirname(char *path)
> +{
> +	char *p = path, *slash, c;
> +
> +	/* Skip over the disk name in MSDOS pathnames. */
> +	if (has_dos_drive_prefix(p))
> +		p += 2;

Not a new problem, but many callers of has_dos_drive_prefix() hardcodes that "2" in various forms. I wonder if this is something we should relieve callers of by tweaking the semantics of it, e.g. by returning 2 (or howmanyever bytes should be skipped) from the function, changing it to skip_dos_drive_prefix(&p), etc.

> +	/* POSIX.1-2001 says dirname("/") should return "/" */
> +	slash = is_dir_sep(*p) ? ++p : NULL;
> +	while ((c = *(p++)))

I am confused by this. What is the invariant on 'p' at the beginning of the body of this while loop in each iteration?

Inside the body, p skips over dir-sep characters, so p must point at the byte past the last run of slashes?

If that is the invariant, upon entry, shouldn't the initialization of "slash" be skipping over all slashes, not just the first one, when the input is "///foo", for example? Instead the above skips '/' and sets slash to the byte past the first '/' (which is OK because you want to NUL-terminate to remove "//foo" from the input) but does not move p to 'f', so the invariant is not "p must point at the byte past the last run of slashes".

Show 9 quoted lines
> +		if (is_dir_sep(c)) {
> +			char *tentative = p - 1;
> +
> +			/* POSIX.1-2001 says to ignore trailing slashes */
> +			while (is_dir_sep(*p))
> +				p++;
> +			if (*p)
> +				slash = tentative;
> +		}
I would have expected the function to scan from the end/right/tail.
Show 18 quoted lines
> +	if (!slash)
> +		return ".";
> +	*slash = '\0';
> +	return path;
> +}
> diff --git a/git-compat-util.h b/git-compat-util.h
> index f649e81..8b01aa5 100644
> --- a/git-compat-util.h
> +++ b/git-compat-util.h
> @@ -253,6 +253,8 @@ struct itimerval {
>  #else
>  #define basename gitbasename
>  extern char *gitbasename(char *);
> +#define dirname gitdirname
> +extern char *gitdirname(char *);
>  #endif
>  
>  #ifndef NO_ICONV
Previous: Johannes SchindelinNext: Johannes Schindelin
Message 2 of 63 in “Provide a dirname() function when NO_LIBGEN_H=YesPlease”
  1. Provide a dirname() function when NO_LIBGEN_H=YesPleaseJohannes Schindelin, Sep 30, 2015
  2. Junio C HamanoSep 30, 2015
  3. Johannes SchindelinJan 8, 2016
  4. Ramsay JonesSep 30, 2015
  5. Johannes SchindelinJan 8, 2016
  6. 0/4 Ensure that we can build without libgen.hJohannes Schindelin, Jan 8, 2016
  7. 1/4 Refactor skipping DOS drive prefixesJohannes Schindelin, Jan 8, 2016
  8. Eric SunshineJan 8, 2016
  9. Junio C HamanoJan 8, 2016
  10. Johannes SchindelinJan 11, 2016
  11. Junio C HamanoJan 11, 2016
  12. 2/4 compat/basename: make basename() conform to POSIXJohannes Schindelin, Jan 8, 2016
  13. Junio C HamanoJan 8, 2016
  14. Johannes SchindelinJan 9, 2016
  15. Junio C HamanoJan 11, 2016
  16. 3/4 Provide a dirname() function when NO_LIBGEN_H=YesPleaseJohannes Schindelin, Jan 8, 2016
  17. Junio C HamanoJan 8, 2016
  18. 4/4 t0060: verify that basename() and dirname() work as expectedJohannes Schindelin, Jan 8, 2016
  19. Eric SunshineJan 10, 2016
  20. Johannes SchindelinJan 11, 2016
  21. Michael BlumeJan 13, 2016
  22. Junio C HamanoJan 13, 2016
  23. Johannes SchindelinJan 14, 2016
  24. 0/4 Ensure that we can build without libgen.hJohannes Schindelin, Jan 11, 2016
  25. 1/4 Refactor skipping DOS drive prefixesJohannes Schindelin, Jan 11, 2016
  26. 2/4 compat/basename: make basename() conform to POSIXJohannes Schindelin, Jan 11, 2016
  27. 3/4 Provide a dirname() function when NO_LIBGEN_H=YesPleaseJohannes Schindelin, Jan 11, 2016
  28. Eric SunshineJan 11, 2016
  29. Junio C HamanoJan 11, 2016
  30. Johannes SchindelinJan 12, 2016
  31. 4/4 t0060: verify that basename() and dirname() work as expectedJohannes Schindelin, Jan 11, 2016
  32. Junio C HamanoJan 11, 2016
  33. 0/4 Ensure that we can build without libgen.hJohannes Schindelin, Jan 12, 2016
  34. 1/4 Refactor skipping DOS drive prefixesJohannes Schindelin, Jan 12, 2016
  35. Johannes SixtJan 22, 2016
  36. Junio C HamanoJan 22, 2016
  37. Johannes SchindelinJan 23, 2016
  38. Johannes SixtJan 23, 2016
  39. Johannes SchindelinJan 24, 2016
  40. Johannes SixtJan 24, 2016
  41. Junio C HamanoJan 24, 2016
  42. mingw: avoid linking to the C library's isalpha()Johannes Sixt, Jan 25, 2016
  43. Junio C HamanoJan 25, 2016
  44. 2/4 compat/basename: make basename() conform to POSIXJohannes Schindelin, Jan 12, 2016
  45. Ramsay JonesJan 13, 2016
  46. Johannes SchindelinJan 13, 2016
  47. 3/4 Provide a dirname() function when NO_LIBGEN_H=YesPleaseJohannes Schindelin, Jan 12, 2016
  48. Ramsay JonesJan 13, 2016
  49. Johannes SchindelinJan 13, 2016
  50. Ramsay JonesJan 13, 2016
  51. 4/4 t0060: verify that basename() and dirname() work as expectedJohannes Schindelin, Jan 12, 2016
  52. Ramsay JonesJan 13, 2016
  53. Johannes SchindelinJan 13, 2016
  54. Ramsay JonesJan 13, 2016
  55. Junio C HamanoJan 13, 2016
  56. Torsten BögershausenJan 13, 2016
  57. Johannes SchindelinJan 13, 2016
  58. Johannes SchindelinJan 13, 2016
  59. Johannes SchindelinJan 13, 2016
  60. Ramsay JonesJan 13, 2016
  61. Ramsay JonesJan 13, 2016
  62. Junio C HamanoJan 13, 2016
  63. Johannes SchindelinJan 13, 2016

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.