Index: head/include/libgen.h =================================================================== --- head/include/libgen.h +++ head/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: head/lib/libc/gen/Makefile.inc =================================================================== --- head/lib/libc/gen/Makefile.inc +++ head/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: head/lib/libc/gen/Symbol.map =================================================================== --- head/lib/libc/gen/Symbol.map +++ head/lib/libc/gen/Symbol.map @@ -68,7 +68,6 @@ arc4random_addrandom; arc4random_stir; __assert; - basename; check_utility_compat; clock; closedir; @@ -414,6 +413,7 @@ }; FBSD_1.5 { + basename; dirname; }; Index: head/lib/libc/gen/basename.3 =================================================================== --- head/lib/libc/gen/basename.3 +++ head/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 -.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 +This implementation 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 . -.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. +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 Nuxi, the Netherlands Index: head/lib/libc/gen/basename.c =================================================================== --- head/lib/libc/gen/basename.c +++ head/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) -{ - const char *endp, *startp; - size_t len; - - /* Empty or NULL string gets treated as "." */ - if (path == NULL || *path == '\0') { - bname[0] = '.'; - bname[1] = '\0'; - return (bname); - } - - /* Strip any trailing slashes */ - endp = path + strlen(path) - 1; - while (endp > path && *endp == '/') - endp--; - - /* 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); -} char * -basename(char *path) +(basename)(char *path) { - static char *bname = NULL; + char *ptr; - if (bname == NULL) { - bname = (char *)malloc(MAXPATHLEN); - if (bname == NULL) - return (NULL); - } - return (basename_r(path, 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 *, ".")); + + /* Find end of last pathname component and null terminate it. */ + ptr = path + strlen(path); + while (ptr > path + 1 && *(ptr - 1) == '/') + --ptr; + *ptr-- = '\0'; + + /* Find beginning of last pathname component. */ + while (ptr > path && *(ptr - 1) != '/') + --ptr; + return (ptr); } Index: head/lib/libc/gen/basename_compat.c =================================================================== --- head/lib/libc/gen/basename_compat.c +++ head/lib/libc/gen/basename_compat.c @@ -0,0 +1,81 @@ +/* $OpenBSD: basename.c,v 1.14 2005/08/08 08:05:33 espie Exp $ */ + +/* + * Copyright (c) 1997, 2004 Todd C. Miller + * + * 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. + * + * 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include + +char * +basename_r(const char *path, char *bname) +{ + const char *endp, *startp; + size_t len; + + /* Empty or NULL string gets treated as "." */ + if (path == NULL || *path == '\0') { + bname[0] = '.'; + bname[1] = '\0'; + return (bname); + } + + /* Strip any trailing slashes */ + endp = path + strlen(path) - 1; + while (endp > path && *endp == '/') + endp--; + + /* 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); +} + +char * +__freebsd11_basename(char *path) +{ + static char *bname = NULL; + + if (bname == NULL) { + bname = (char *)malloc(MAXPATHLEN); + if (bname == NULL) + return (NULL); + } + return (basename_r(path, bname)); +} + +__sym_compat(basename, __freebsd11_basename, FBSD_1.0);