diff mbox

[v2] uclibc:fix basename modify the input path

Message ID 1411526830-3108-1-git-send-email-wangyufen@huawei.com
State Rejected
Headers show

Commit Message

Wang Yufen Sept. 24, 2014, 2:47 a.m. UTC
From: Wang Yufen <wangyufen@huawei.com>

I tested basename(path), path is "///", the basename(path) returned "/",
but the input path also be modified to "/". It because in basename impl, 
"last[1] = 0;" modified the input path, I think that isn't correct. 

This patch fix this problem. 

Signed-off-by: Wang Yufen <wangyufen@huawei.com>
---
 libc/string/__xpg_basename.c |   54 +++++++++++++++++++++++++++--------------
 1 files changed, 35 insertions(+), 19 deletions(-)

Comments

Bernhard Reutner-Fischer Jan. 20, 2015, 1:42 p.m. UTC | #1
On 24 September 2014 at 04:47, Wangyufen <wangyufen@huawei.com> wrote:
> From: Wang Yufen <wangyufen@huawei.com>
>
> I tested basename(path), path is "///", the basename(path) returned "/",
> but the input path also be modified to "/". It because in basename impl,
> "last[1] = 0;" modified the input path, I think that isn't correct.

This is perfectly legal.
See http://pubs.opengroup.org/onlinepubs/9699919799/functions/basename.html

   text   data    bss    dec    hex filename
    165      0      0    165     a5 libc/string/__xpg_basename.os
    113      0      0    113     71 libc/string/__xpg_basename.os.orig

Since the current behaviour is in accordance to the standard and your version
is way bigger i prefer to keep it as is.

Thanks anyway!
diff mbox

Patch

diff --git a/libc/string/__xpg_basename.c b/libc/string/__xpg_basename.c
index 2e7ade9..4d5a984 100644
--- a/libc/string/__xpg_basename.c
+++ b/libc/string/__xpg_basename.c
@@ -6,33 +6,49 @@ 
  */
 
 #include <libgen.h>
-
-char *__xpg_basename(register char *path)
+#include <string.h>
+char *__xpg_basename (char *path)
 {
-	static const char null_or_empty[] = ".";
-	char *first;
-	register char *last;
-
-	first = (char *) null_or_empty;
+	char *p;
 
-	if (path && *path) {
-		first = path;
-		last = path - 1;
+	if (path == NULL || path[0] == '\0')
+		/* We return a pointer to a static string containing ".".  */
+		p = (char *) ".";
+	else {
+		p = strrchr (path, '/');
 
-		do {
-			if ((*path != '/') && (path > ++last)) {
-				last = first = path;
-			}
-		} while (*++path);
+		if (p == NULL)
+			/* There is no slash in the filename.  Return the whole string.  */
+			p = path;
+		else {
+			if (p[1] == '\0') {
+				/* We must remove trailing '/'.  */
+				while (p > path && p[-1] == '/')
+					--p;
 
-		if (*first == '/') {
-			last = first;
+				/* Now we can be in two situations:
+				   a) the string only contains '/' characters, so we return
+				   '/'
+				   b) p points past the last component, but we have to remove
+				   the trailing slash.  */
+				if (p > path) {
+					*p-- = '\0';
+					while (p > path && p[-1] != '/')
+						--p;
+				} else
+					/* The last slash we already found is the right position
+					   to return.  */
+					while (p[1] != '\0')
+						++p;
+			} else
+				/* Go to the first character of the name.  */
+				++p;
 		}
-		last[1] = 0;
 	}
 
-	return first;
+	return p;
 }
+
 #ifndef __USE_GNU
 # undef basename
 weak_alias(__xpg_basename,basename)