From owner-svn-src-head@freebsd.org Sun Sep 18 20:47:56 2016 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 6EC86BDFFB3; Sun, 18 Sep 2016 20:47:56 +0000 (UTC) (envelope-from ed@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 491061DB8; Sun, 18 Sep 2016 20:47:56 +0000 (UTC) (envelope-from ed@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u8IKltko096684; Sun, 18 Sep 2016 20:47:55 GMT (envelope-from ed@FreeBSD.org) Received: (from ed@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u8IKlt4J096682; Sun, 18 Sep 2016 20:47:55 GMT (envelope-from ed@FreeBSD.org) Message-Id: <201609182047.u8IKlt4J096682@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: ed set sender to ed@FreeBSD.org using -f From: Ed Schouten Date: Sun, 18 Sep 2016 20:47:55 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r305952 - head/lib/libc/gen X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 18 Sep 2016 20:47:56 -0000 Author: ed Date: Sun Sep 18 20:47:55 2016 New Revision: 305952 URL: https://svnweb.freebsd.org/changeset/base/305952 Log: Replace dirname(3) by a copy that complies to POSIX. It turns out that the path normalization that our brand new copy of dirname(3) does is actually not allowed by the draft version of the upcoming version of POSIX. It has to behave identically to the dirname(1) utility. This change replaces our new dirname(3) implementation by yet another version that doesn't implement the path normalization logic; it merely looks for the end of the directory name and overwrites that with a null byte. More details: See note #3370 at http://austingroupbugs.net/view.php?id=1073 PR: 212193 Reviewed by: emaste, jilles Differential Revision: https://reviews.freebsd.org/D7790 Modified: head/lib/libc/gen/dirname.3 head/lib/libc/gen/dirname.c Modified: head/lib/libc/gen/dirname.3 ============================================================================== --- head/lib/libc/gen/dirname.3 Sun Sep 18 20:23:26 2016 (r305951) +++ head/lib/libc/gen/dirname.3 Sun Sep 18 20:47:55 2016 (r305952) @@ -16,7 +16,7 @@ .\" .\" $FreeBSD$ .\" -.Dd August 12, 2016 +.Dd September 5, 2016 .Dt DIRNAME 3 .Os .Sh NAME @@ -60,11 +60,6 @@ space instead. The advantage of the former approach is that it ensures thread-safety, while also placing no upper limit on the supported length of the pathname. -.Pp -The algorithm used by this implementation also discards redundant -slashes and -.Qq \&. -pathname components from the pathname string. .Sh SEE ALSO .Xr basename 1 , .Xr dirname 1 , Modified: head/lib/libc/gen/dirname.c ============================================================================== --- head/lib/libc/gen/dirname.c Sun Sep 18 20:23:26 2016 (r305951) +++ head/lib/libc/gen/dirname.c Sun Sep 18 20:47:55 2016 (r305952) @@ -27,64 +27,47 @@ __FBSDID("$FreeBSD$"); #include -#include #include char * (dirname)(char *path) { - const char *in, *prev, *begin, *end; - char *out; - size_t prevlen; - bool skipslash; + char *end; /* * If path is a null pointer or points to an empty string, * dirname() shall return a pointer to the string ".". */ if (path == NULL || *path == '\0') - return ((char *)"."); + return (__DECONST(char *, ".")); - /* Retain at least one leading slash character. */ - in = out = *path == '/' ? path + 1 : path; - - skipslash = true; - prev = "."; - prevlen = 1; - for (;;) { - /* Extract the next pathname component. */ - while (*in == '/') - ++in; - begin = in; - while (*in != '/' && *in != '\0') - ++in; - end = in; - if (begin == end) - break; - - /* - * Copy over the previous pathname component, except if - * it's dot. There is no point in retaining those. - */ - if (prevlen != 1 || *prev != '.') { - if (!skipslash) - *out++ = '/'; - skipslash = false; - memmove(out, prev, prevlen); - out += prevlen; - } - - /* Preserve the pathname component for the next iteration. */ - prev = begin; - prevlen = end - begin; - } + /* Find end of last pathname component. */ + end = path + strlen(path); + while (end > path + 1 && *(end - 1) == '/') + --end; + + /* Strip off the last pathname component. */ + while (end > path && *(end - 1) != '/') + --end; /* * If path does not contain a '/', then dirname() shall return a * pointer to the string ".". */ - if (out == path) - *out++ = '.'; - *out = '\0'; + if (end == path) { + path[0] = '.'; + path[1] = '\0'; + return (path); + } + + /* + * Remove trailing slashes from the resulting directory name. Ensure + * that at least one character remains. + */ + while (end > path + 1 && *(end - 1) == '/') + --end; + + /* Null terminate directory name and return it. */ + *end = '\0'; return (path); }