1 /* $OpenBSD: basename.c,v 1.14 2005/08/08 08:05:33 espie Exp $ */ 2 3 /* 4 * Copyright (c) 1997, 2004 Todd C. Miller <Todd.Miller@courtesan.com> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/cdefs.h> 20 __FBSDID("$FreeBSD$"); 21 22 #include <errno.h> 23 #include <libgen.h> 24 #include <stdlib.h> 25 #include <string.h> 26 #include <sys/param.h> 27 28 char * 29 __freebsd11_basename_r(const char *path, char *bname) 30 { 31 const char *endp, *startp; 32 size_t len; 33 34 /* Empty or NULL string gets treated as "." */ 35 if (path == NULL || *path == '\0') { 36 bname[0] = '.'; 37 bname[1] = '\0'; 38 return (bname); 39 } 40 41 /* Strip any trailing slashes */ 42 endp = path + strlen(path) - 1; 43 while (endp > path && *endp == '/') 44 endp--; 45 46 /* All slashes becomes "/" */ 47 if (endp == path && *endp == '/') { 48 bname[0] = '/'; 49 bname[1] = '\0'; 50 return (bname); 51 } 52 53 /* Find the start of the base */ 54 startp = endp; 55 while (startp > path && *(startp - 1) != '/') 56 startp--; 57 58 len = endp - startp + 1; 59 if (len >= MAXPATHLEN) { 60 errno = ENAMETOOLONG; 61 return (NULL); 62 } 63 memcpy(bname, startp, len); 64 bname[len] = '\0'; 65 return (bname); 66 } 67 68 char * 69 __freebsd11_basename(char *path) 70 { 71 static char *bname = NULL; 72 73 if (bname == NULL) { 74 bname = (char *)malloc(MAXPATHLEN); 75 if (bname == NULL) 76 return (NULL); 77 } 78 return (__freebsd11_basename_r(path, bname)); 79 } 80 81 __sym_compat(basename_r, __freebsd11_basename_r, FBSD_1.2); 82 __sym_compat(basename, __freebsd11_basename, FBSD_1.0); 83