diff options
author | Sergey Bugaev <bugaevc@gmail.com> | 2019-10-02 22:40:52 +0300 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-10-03 08:23:54 +0200 |
commit | afdc5688ec90a58591e359e794d07eff18baa0a6 (patch) | |
tree | f2124d54fbbd147e490fecbf51c594e8c2044736 | |
parent | 8fbcfa934afaca709c8ffed3f972e7e0ffb62d0d (diff) | |
download | serenity-afdc5688ec90a58591e359e794d07eff18baa0a6.zip |
LibC: Implement dirname() and basename()
And write section 3 man pages for them.
-rw-r--r-- | Base/usr/share/man/man3/basename.md | 53 | ||||
-rw-r--r-- | Base/usr/share/man/man3/dirname.md | 54 | ||||
-rw-r--r-- | Libraries/LibC/Makefile | 3 | ||||
-rw-r--r-- | Libraries/LibC/libgen.cpp | 58 | ||||
-rw-r--r-- | Libraries/LibC/libgen.h | 10 |
5 files changed, 177 insertions, 1 deletions
diff --git a/Base/usr/share/man/man3/basename.md b/Base/usr/share/man/man3/basename.md new file mode 100644 index 0000000000..716ef8f29e --- /dev/null +++ b/Base/usr/share/man/man3/basename.md @@ -0,0 +1,53 @@ +## Name + +basename - extract file name from a path + +## Synopsis + +```**c++ +#include <libgen.h> + +char* basename(char* path); +``` + +## Description + +Given a file path, `basename()` returns that file's name. `basename()` works +purely lexically, meaning it only manipulates the path as a string, and does +not check if such a file actually exists. + +A call to `basename()` may reuse and modify the passed in `path` buffer. Do not +expect it to have the same value after calling `basename()`. + +## Return value + +`basename()` returns the file name as a string. This string may be allocated +in static memory, or it may point to some part of the original `path` buffer. +Do not `free()` the returned string, and do not `free()` the original `path` +buffer while using the returned string. + +## Examples + +```c++ +#include <AK/LogStream.h> +#include <libgen.h> + +int main() +{ + char path1[] = "/home/anon/ReadMe.md"; + dbg() << basename(path1); // should be "ReadMe.md" + + char path2[] = "foo/bar/"; + dbg() << basename(path2); // should be "bar" + + char path3[] = "foo"; + dbg() << basename(path3); // should be "foo" + + char path4[] = "/"; + dbg() << basename(path4); // should be "/" +} +``` + +## See also + +* [`dirname`(3)](dirname.md) diff --git a/Base/usr/share/man/man3/dirname.md b/Base/usr/share/man/man3/dirname.md new file mode 100644 index 0000000000..6a101d9dbf --- /dev/null +++ b/Base/usr/share/man/man3/dirname.md @@ -0,0 +1,54 @@ +## Name + +dirname - get a file's containing directory path + +## Synopsis + +```**c++ +#include <libgen.h> + +char* dirname(char* path); +``` + +## Description + +Given a file path, `dirname()` returns a path to the directory that contains the +file. `dirname()` works purely lexically, meaning it only manipulates the path +as a string, and does not check if such a file or its containing directory +actually exist. + +A call to `dirname()` may reuse and modify the passed in `path` buffer. Do not +expect it to have the same value after calling `dirname()`. + +## Return value + +`dirname()` returns the directory path as a string. This string may be allocated +in static memory, or it may point to some part of the original `path` buffer. +Do not `free()` the returned string, and do not `free()` the original `path` +buffer while using the returned string. + +## Examples + +```c++ +#include <AK/LogStream.h> +#include <libgen.h> + +int main() +{ + char path1[] = "/home/anon/ReadMe.md"; + dbg() << dirname(path1); // should be "/home/anon" + + char path2[] = "foo/bar/"; + dbg() << dirname(path2); // should be "foo" + + char path3[] = "foo"; + dbg() << dirname(path3); // should be "." + + char path4[] = "/"; + dbg() << dirname(path4); // should be "/" +} +``` + +## See also + +* [`basename`(3)](basename.md) diff --git a/Libraries/LibC/Makefile b/Libraries/LibC/Makefile index af5580266a..7541f10136 100644 --- a/Libraries/LibC/Makefile +++ b/Libraries/LibC/Makefile @@ -51,7 +51,8 @@ LIBC_OBJS = \ arpa/inet.o \ netdb.o \ sched.o \ - dlfcn.o + dlfcn.o \ + libgen.o ASM_OBJS = setjmp.ao crti.ao crtn.ao diff --git a/Libraries/LibC/libgen.cpp b/Libraries/LibC/libgen.cpp new file mode 100644 index 0000000000..04b2e7dac9 --- /dev/null +++ b/Libraries/LibC/libgen.cpp @@ -0,0 +1,58 @@ +#include <AK/Assertions.h> +#include <libgen.h> +#include <string.h> + +static char dot[] = "."; +static char slash[] = "/"; + +char* dirname(char* path) +{ + if (path == nullptr) + return dot; + + int len = strlen(path); + if (len == 0) + return dot; + + while (len > 1 && path[len - 1] == '/') { + path[len - 1] = 0; + len--; + } + + char* last_slash = strrchr(path, '/'); + if (last_slash == nullptr) + return dot; + + if (last_slash == path) + return slash; + + *last_slash = 0; + return path; +} + +char* basename(char* path) +{ + if (path == nullptr) + return dot; + + int len = strlen(path); + if (len == 0) + return dot; + + while (len > 1 && path[len - 1] == '/') { + path[len - 1] = 0; + len--; + } + + char* last_slash = strrchr(path, '/'); + if (last_slash == nullptr) + return path; + + if (len == 1) { + ASSERT(last_slash == path); + ASSERT(path[0] == '/'); + return slash; + } + + return last_slash + 1; +} diff --git a/Libraries/LibC/libgen.h b/Libraries/LibC/libgen.h new file mode 100644 index 0000000000..e8b5af9f0b --- /dev/null +++ b/Libraries/LibC/libgen.h @@ -0,0 +1,10 @@ +#pragma once + +#include <sys/cdefs.h> + +__BEGIN_DECLS + +char* dirname(char* path); +char* basename(char* path); + +__END_DECLS |