aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2014-08-19 14:30:30 -0700
committerElliott Hughes <enh@google.com>2014-08-19 14:30:30 -0700
commit09c39d6df0e952620f8c1751377b559a04e023aa (patch)
tree1ca25e04d3ed7ebea1dde6f4d3baaeee9526c0e5
parentc5d6df6f2fe57fd5aadbd9ebb131023234c30a0c (diff)
downloadandroid_bionic-09c39d6df0e952620f8c1751377b559a04e023aa.tar.gz
android_bionic-09c39d6df0e952620f8c1751377b559a04e023aa.tar.bz2
android_bionic-09c39d6df0e952620f8c1751377b559a04e023aa.zip
Implement the GNU basename(3) in addition to the POSIX one.
Code like perf(1) needs this. Bug: 11860789 Change-Id: I907eb448052a7b165e4012d74303330d32328cb2
-rw-r--r--libc/Android.mk1
-rw-r--r--libc/bionic/__gnu_basename.cpp35
-rw-r--r--libc/include/libgen.h12
-rw-r--r--libc/include/string.h21
-rw-r--r--tests/libgen_test.cpp5
-rw-r--r--tests/string_test.cpp23
6 files changed, 88 insertions, 9 deletions
diff --git a/libc/Android.mk b/libc/Android.mk
index ca22bbcf6..937f741d5 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -122,6 +122,7 @@ libc_bionic_src_files := \
bionic/getpgrp.cpp \
bionic/getpid.cpp \
bionic/gettid.cpp \
+ bionic/__gnu_basename.cpp \
bionic/inotify_init.cpp \
bionic/lchown.cpp \
bionic/lfs64_support.cpp \
diff --git a/libc/bionic/__gnu_basename.cpp b/libc/bionic/__gnu_basename.cpp
new file mode 100644
index 000000000..1eb3f6594
--- /dev/null
+++ b/libc/bionic/__gnu_basename.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#define _GNU_SOURCE 1
+#include <string.h>
+
+extern "C" const char* __gnu_basename(const char* path) {
+ const char* last_slash = strrchr(path, '/');
+ return (last_slash != NULL) ? last_slash + 1 : path;
+}
diff --git a/libc/include/libgen.h b/libc/include/libgen.h
index c5fc76a79..4caf8b9c5 100644
--- a/libc/include/libgen.h
+++ b/libc/include/libgen.h
@@ -25,6 +25,7 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
+
#ifndef _LIBGEN_H
#define _LIBGEN_H
@@ -33,9 +34,18 @@
__BEGIN_DECLS
+#if !defined(__bionic_using_gnu_basename)
+/*
+ * <string.h> gets you the GNU basename.
+ * <libgen.h> the POSIX one.
+ * Note that our "POSIX" one has the wrong argument cv-qualifiers.
+ */
+extern char* basename(const char*);
+#define __bionic_using_posix_basename
+#endif
+
/* our version of dirname/basename don't modify the input path */
extern char* dirname (const char* path);
-extern char* basename(const char* path);
/* special thread-safe Bionic versions
*
diff --git a/libc/include/string.h b/libc/include/string.h
index 643132d67..0a1d653b8 100644
--- a/libc/include/string.h
+++ b/libc/include/string.h
@@ -25,8 +25,9 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
-#ifndef _STRING_H_
-#define _STRING_H_
+
+#ifndef _STRING_H
+#define _STRING_H
#include <sys/cdefs.h>
#include <stddef.h>
@@ -92,6 +93,20 @@ extern size_t strxfrm(char* __restrict, const char* __restrict, size_t);
extern int strcoll_l(const char *, const char *, locale_t) __purefunc;
extern size_t strxfrm_l(char* __restrict, const char* __restrict, size_t, locale_t);
+#if defined(__USE_GNU) && !defined(__bionic_using_posix_basename)
+/*
+ * glibc has a basename in <string.h> that's different to the POSIX one in <libgen.h>.
+ * It doesn't modify its argument, and in C++ it's const-correct.
+ */
+#if defined(__cplusplus)
+extern "C++" char* basename(char*) __RENAME(__gnu_basename) __nonnull((1));
+extern "C++" const char* basename(const char*) __RENAME(__gnu_basename) __nonnull((1));
+#else
+extern char* basename(const char*) __RENAME(__gnu_basename) __nonnull((1));
+#endif
+#define __bionic_using_gnu_basename
+#endif
+
#if defined(__BIONIC_FORTIFY)
__BIONIC_FORTIFY_INLINE
@@ -289,4 +304,4 @@ char* strrchr(const char *s, int c) {
__END_DECLS
-#endif /* _STRING_H_ */
+#endif /* _STRING_H */
diff --git a/tests/libgen_test.cpp b/tests/libgen_test.cpp
index cae646f25..d0402dbf6 100644
--- a/tests/libgen_test.cpp
+++ b/tests/libgen_test.cpp
@@ -14,11 +14,10 @@
* limitations under the License.
*/
-#include <gtest/gtest.h>
-
#include <libgen.h>
#include <errno.h>
+#include <gtest/gtest.h>
static void TestBasename(const char* in, const char* expected_out) {
char* writable_in = (in != NULL) ? strdup(in) : NULL;
@@ -40,7 +39,7 @@ static void TestDirname(const char* in, const char* expected_out) {
// Do not use basename as the test name, it's defined to another value in glibc
// so leads to a differently named test on host versus target architectures.
-TEST(libgen, basename_smoke) {
+TEST(libgen, posix_basename) {
TestBasename(NULL, ".");
TestBasename("", ".");
TestBasename("/usr/lib", "lib");
diff --git a/tests/string_test.cpp b/tests/string_test.cpp
index 73c94c602..a3c6abb7d 100644
--- a/tests/string_test.cpp
+++ b/tests/string_test.cpp
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-#include <gtest/gtest.h>
+#include <string.h>
#include <errno.h>
+#include <gtest/gtest.h>
#include <malloc.h>
#include <math.h>
-#include <string.h>
#include "buffer_tests.h"
@@ -1287,3 +1287,22 @@ TEST(string, strchr_align) {
TEST(string, strchr_overread) {
RunSingleBufferOverreadTest(DoStrchrTest);
}
+
+static void TestBasename(const char* in, const char* expected_out) {
+ errno = 0;
+ const char* out = basename(in);
+ ASSERT_STREQ(expected_out, out) << in;
+ ASSERT_EQ(0, errno) << in;
+}
+
+TEST(string, __gnu_basename) {
+ TestBasename("", "");
+ TestBasename("/usr/lib", "lib");
+ TestBasename("/usr/", "");
+ TestBasename("usr", "usr");
+ TestBasename("/", "");
+ TestBasename(".", ".");
+ TestBasename("..", "..");
+ TestBasename("///", "");
+ TestBasename("//usr//lib//", "");
+}