Skip to content

Commit 824682a

Browse files
dschogitster
authored andcommitted
compat/basename.c: provide a dirname() compatibility function
When there is no `libgen.h` to our disposal, we miss the `dirname()` function. Earlier we added basename() compatibility function for the same reason at e1c0688 (compat: add a basename() compatibility function, 2009-05-31). So far, we only had one user of that function: credential-cache--daemon (which was only compiled when Unix sockets are available, anyway). But now we also have `builtin/am.c` as user, so we need it. Since `dirname()` is a sibling of `basename()`, we simply put our very own `gitdirname()` implementation next to `gitbasename()` and use it if `NO_LIBGEN_H` has been set. Signed-off-by: Johannes Schindelin <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 61725be commit 824682a

File tree

2 files changed

+46
-0
lines changed

2 files changed

+46
-0
lines changed

compat/basename.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "../git-compat-util.h"
2+
#include "../strbuf.h"
23

34
/* Adapted from libiberty's basename.c. */
45
char *gitbasename (char *path)
@@ -25,3 +26,46 @@ char *gitbasename (char *path)
2526
}
2627
return (char *)base;
2728
}
29+
30+
char *gitdirname(char *path)
31+
{
32+
static struct strbuf buf = STRBUF_INIT;
33+
char *p = path, *slash = NULL, c;
34+
int dos_drive_prefix;
35+
36+
if (!p)
37+
return ".";
38+
39+
if ((dos_drive_prefix = skip_dos_drive_prefix(&p)) && !*p)
40+
goto dot;
41+
42+
/*
43+
* POSIX.1-2001 says dirname("/") should return "/", and dirname("//")
44+
* should return "//", but dirname("///") should return "/" again.
45+
*/
46+
if (is_dir_sep(*p)) {
47+
if (!p[1] || (is_dir_sep(p[1]) && !p[2]))
48+
return path;
49+
slash = ++p;
50+
}
51+
while ((c = *(p++)))
52+
if (is_dir_sep(c)) {
53+
char *tentative = p - 1;
54+
55+
/* POSIX.1-2001 says to ignore trailing slashes */
56+
while (is_dir_sep(*p))
57+
p++;
58+
if (*p)
59+
slash = tentative;
60+
}
61+
62+
if (slash) {
63+
*slash = '\0';
64+
return path;
65+
}
66+
67+
dot:
68+
strbuf_reset(&buf);
69+
strbuf_addf(&buf, "%.*s.", dos_drive_prefix, path);
70+
return buf.buf;
71+
}

git-compat-util.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,8 @@ struct itimerval {
253253
#else
254254
#define basename gitbasename
255255
extern char *gitbasename(char *);
256+
#define dirname gitdirname
257+
extern char *gitdirname(char *);
256258
#endif
257259

258260
#ifndef NO_ICONV

0 commit comments

Comments
 (0)