Index: include/libgen.h =================================================================== --- include/libgen.h +++ include/libgen.h @@ -40,21 +40,24 @@ __END_DECLS /* - * In FreeBSD 12, the prototype of dirname() was modified to comply to - * POSIX. This function may now modify its input. Unfortunately, our - * copy of xinstall(8) shipped with previous versions of FreeBSD is - * built using the host headers and libc during the bootstrapping phase - * and depends on the old behavior. + * In FreeBSD 12, the prototypes of basename() and dirname() were + * modified to comply to POSIX. These functions may now modify their + * input. Unfortunately, our copy of xinstall(8) shipped with previous + * versions of FreeBSD is built using the host headers and libc during + * the bootstrapping phase and depends on the old behavior. * - * Apply a workaround where we explicitly link against dirname@FBSD_1.0 - * in case this function is called on constant strings, instead of - * making the program crash at runtime. + * Apply a workaround where we explicitly link against basename@FBSD_1.0 + * and dirname@FBSD_1.0 in case these functions are called on constant + * strings, instead of making the program crash at runtime. */ #if defined(__generic) && !defined(__cplusplus) __BEGIN_DECLS +char *__old_basename(char *); char *__old_dirname(char *); __END_DECLS +__sym_compat(basename, __old_basename, FBSD_1.0); __sym_compat(dirname, __old_dirname, FBSD_1.0); +#define basename(x) __generic(x, const char *, __old_basename, basename)(x) #define dirname(x) __generic(x, const char *, __old_dirname, dirname)(x) #endif Index: lib/libc/gen/Makefile.inc =================================================================== --- lib/libc/gen/Makefile.inc +++ lib/libc/gen/Makefile.inc @@ -17,6 +17,7 @@ assert.c \ auxv.c \ basename.c \ + basename_compat.c \ cap_sandboxed.c \ check_utility_compat.c \ clock.c \ Index: lib/libc/gen/Symbol.map =================================================================== --- lib/libc/gen/Symbol.map +++ lib/libc/gen/Symbol.map @@ -68,7 +68,6 @@ arc4random_addrandom; arc4random_stir; __assert; - basename; check_utility_compat; clock; closedir; @@ -418,6 +417,7 @@ }; FBSD_1.5 { + basename; dirname; }; Index: lib/libc/gen/basename.3 =================================================================== --- lib/libc/gen/basename.3 +++ lib/libc/gen/basename.3 @@ -16,7 +16,7 @@ .\" .\" $FreeBSD$ .\" -.Dd July 29, 2016 +.Dd October 29, 2016 .Dt BASENAME 3 .Os .Sh NAME @@ -26,8 +26,6 @@ .In libgen.h .Ft char * .Fn basename "char *path" -.Ft char * -.Fn basename_r "const char *path" "char *bname" .Sh DESCRIPTION The .Fn basename @@ -36,6 +34,7 @@ deleting any trailing .Sq \&/ characters. +.Sh RETURN VALUES If .Fa path consists entirely of @@ -48,48 +47,19 @@ is a null pointer or the empty string, a pointer to the string .Qq \&. is returned. -.Pp -The -.Fn basename_r -variation accepts a buffer of at least -.Dv MAXPATHLEN -bytes in which to store the resulting component. +Otherwise, +it returns a pointer to the last component of +.Fa path . .Sh IMPLEMENTATION NOTES -The +This implementation of .Fn basename -function -returns a pointer to internal storage space allocated on the first call -that will be overwritten -by subsequent calls. -.Pp -Other vendor implementations of -.Fn basename -may store their result in the input buffer, -making it safe to use in multithreaded applications. -Future versions of -.Fx -will follow this approach as well. -.Fn basename_r -will then become obsolete. -.Sh RETURN VALUES -On successful completion, -.Fn basename -and -.Fn basename_r -return pointers to the last component of -.Fa path . -.Pp -If they fail, a null pointer is returned and the global variable -.Va errno -is set to indicate the error. -.Sh ERRORS -The following error codes may be set in -.Va errno : -.Bl -tag -width Er -.It Bq Er ENAMETOOLONG -The path component to be returned was larger than -.Dv MAXPATHLEN . -.El +uses the buffer provided by the caller to store the resulting pathname +component. +Other vendor implementations may return a pointer to internal storage +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. .Sh SEE ALSO .Xr basename 1 , .Xr dirname 1 , @@ -106,16 +76,13 @@ .Ox 2.2 and .Fx 4.2 . +.Pp +In +.Fx 12.0 , +this function was reimplemented to store its result in the provided +input buffer. +There is no longer any need to use the +.Fn basename_r +function. .Sh AUTHORS -.An Todd C. Miller -.Sh CAVEATS -.Fn basename -returns a pointer to internal static storage space that will be overwritten -by subsequent calls. -.Pp -Other vendor implementations of -.Fn basename -may modify the contents of the string passed to -.Fn basename ; -this should be taken into account when writing code which calls this function -if portability is desired. +.An Nuxi, the Netherlands Index: lib/libc/gen/basename.c =================================================================== --- lib/libc/gen/basename.c +++ lib/libc/gen/basename.c @@ -1,79 +1,54 @@ -/* $OpenBSD: basename.c,v 1.14 2005/08/08 08:05:33 espie Exp $ */ - -/* - * Copyright (c) 1997, 2004 Todd C. Miller +/*- + * Copyright (c) 2015-2016 Nuxi, https://nuxi.nl/ * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. */ #include __FBSDID("$FreeBSD$"); -#include #include -#include #include -#include char * -basename_r(const char *path, char *bname) +(basename)(char *path) { - const char *endp, *startp; - size_t len; + char *ptr; - /* Empty or NULL string gets treated as "." */ - if (path == NULL || *path == '\0') { - bname[0] = '.'; - bname[1] = '\0'; - return (bname); - } + /* + * If path is a null pointer or points to an empty string, + * basename() shall return a pointer to the string ".". + */ + if (path == NULL || *path == '\0') + return (__DECONST(char *, ".")); - /* Strip any trailing slashes */ - endp = path + strlen(path) - 1; - while (endp > path && *endp == '/') - endp--; + /* Find end of last pathname component and null terminate it. */ + ptr = path + strlen(path); + while (ptr > path + 1 && *(ptr - 1) == '/') + --ptr; + *ptr-- = '\0'; - /* All slashes becomes "/" */ - if (endp == path && *endp == '/') { - bname[0] = '/'; - bname[1] = '\0'; - return (bname); - } - - /* Find the start of the base */ - startp = endp; - while (startp > path && *(startp - 1) != '/') - startp--; - - len = endp - startp + 1; - if (len >= MAXPATHLEN) { - errno = ENAMETOOLONG; - return (NULL); - } - memcpy(bname, startp, len); - bname[len] = '\0'; - return (bname); + /* Find beginning of last pathname component. */ + while (ptr > path && *(ptr - 1) != '/') + --ptr; + return (ptr); } - -char * -basename(char *path) -{ - static char *bname = NULL; - - if (bname == NULL) { - bname = (char *)malloc(MAXPATHLEN); - if (bname == NULL) - return (NULL); - } - return (basename_r(path, bname)); -} Index: lib/libc/gen/basename_compat.c =================================================================== --- lib/libc/gen/basename_compat.c +++ lib/libc/gen/basename_compat.c @@ -66,7 +66,7 @@ } char * -basename(char *path) +__freebsd11_basename(char *path) { static char *bname = NULL; @@ -77,3 +77,5 @@ } return (basename_r(path, bname)); } + +__sym_compat(basename, __freebsd11_basename, FBSD_1.0);