From 3ec29ae85ea44c459b342d1439c89a2ab2c992af Mon Sep 17 00:00:00 2001 From: Erik van der Kouwe Date: Mon, 25 Jan 2010 18:12:28 +0000 Subject: [PATCH] Add dirname function --- lib/other/dirname.c | 29 +++++++++++++++++++++ man/man3/dirname.3 | 19 ++++++++++++++ test/test43.c | 61 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 109 insertions(+) create mode 100755 lib/other/dirname.c create mode 100755 man/man3/dirname.3 diff --git a/lib/other/dirname.c b/lib/other/dirname.c new file mode 100755 index 000000000..1a578aed5 --- /dev/null +++ b/lib/other/dirname.c @@ -0,0 +1,29 @@ +#include +#include + +/* based on http://www.opengroup.org/onlinepubs/009695399/functions/dirname.html */ +char *dirname(char *path) +{ + char *pathend; + + /* remove leading slash(es) except root */ + pathend = path + strlen(path) - 1; + while (pathend > path && *pathend == '/') + pathend--; + + /* remove last path component */ + while (pathend >= path && *pathend != '/') + pathend--; + + /* remove slash(es) before last path component except root */ + while (pathend > path && *pathend == '/') + pathend--; + + /* special case: no slashes */ + if (pathend < path) + return "."; + + /* truncate and return string */ + pathend[1] = 0; + return path; +} diff --git a/man/man3/dirname.3 b/man/man3/dirname.3 new file mode 100755 index 000000000..30c9c0a96 --- /dev/null +++ b/man/man3/dirname.3 @@ -0,0 +1,19 @@ +.TH DIRNAME 3 +.SH NAME +dirname \- determine name of containing directory +.SH SYNOPSIS +.nf +.ft B +#include + +char *dirname(char *\fIpath\fP); +.SH DESCRIPTION +The dirname function returns the name of the directory containing \fIpath\fP. +If the path does not contain slashes, the string "." is returned. Trailing +slashes are ignored. +.SH "SEE ALSO" +.BR basename (3). +.SH NOTES +This function may, but need not, overwrite the buffer passed to it. +Although MINIX' implementation of this function is re-entrant, POSIX does not +guarantee this property and portable programs should not rely on it. diff --git a/test/test43.c b/test/test43.c index 8ff3534eb..0e4d509ab 100644 --- a/test/test43.c +++ b/test/test43.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -328,6 +329,36 @@ static void cleanup(const char *path) if (rmdir(path) < 0) ERR; } +static void test_dirname(const char *path, const char *exp) +{ + char buffer[PATH_MAX]; + int i, j; + size_t pathlen = strlen(path); + char *pathout; + + assert(pathlen + 3 < PATH_MAX); + + /* try with no, one or two trailing slashes */ + for (i = 0; i < 3; i++) + { + /* no trailing slashes for empty string */ + if (pathlen < 1 && i > 0) + continue; + + /* prepare buffer */ + strcpy(buffer, path); + for (j = 0; j < i; j++) + buffer[pathlen + j] = '/'; + + buffer[pathlen + i] = 0; + + /* perform test */ + pathout = dirname(buffer); + if (strcmp(pathout, exp) != 0) + ERR; + } +} + int main(int argc, char **argv) { char buffer1[PATH_MAX + 1], buffer2[PATH_MAX + 1]; @@ -358,6 +389,36 @@ int main(int argc, char **argv) /* delete the symlinks */ cleanup(addbasepath(buffer1, PATH_BASE)); + /* also test dirname */ + test_dirname("", "."); + test_dirname(".", "."); + test_dirname("..", "."); + test_dirname("x", "."); + test_dirname("xy", "."); + test_dirname("x/y", "x"); + test_dirname("xy/z", "xy"); + test_dirname("x/yz", "x"); + test_dirname("ab/cd", "ab"); + test_dirname("x//y", "x"); + test_dirname("xy//z", "xy"); + test_dirname("x//yz", "x"); + test_dirname("ab//cd", "ab"); + test_dirname("/", "/"); + test_dirname("/x", "/"); + test_dirname("/xy", "/"); + test_dirname("/x/y", "/x"); + test_dirname("/xy/z", "/xy"); + test_dirname("/x/yz", "/x"); + test_dirname("/ab/cd", "/ab"); + test_dirname("/x//y", "/x"); + test_dirname("/xy//z", "/xy"); + test_dirname("/x//yz", "/x"); + test_dirname("/ab//cd", "/ab"); + test_dirname("/usr/src", "/usr"); + test_dirname("/usr/src/test", "/usr/src"); + test_dirname("usr/src", "usr"); + test_dirname("usr/src/test", "usr/src"); + /* done */ quit(); return(-1); /* impossible */ -- 2.44.0