dirname.c revision 184578
1184578Sdelphij/* $OpenBSD: dirname.c,v 1.13 2005/08/08 08:05:33 espie Exp $ */ 2184578Sdelphij 365294Sdes/* 4184578Sdelphij * Copyright (c) 1997, 2004 Todd C. Miller <Todd.Miller@courtesan.com> 565294Sdes * 6184578Sdelphij * Permission to use, copy, modify, and distribute this software for any 7184578Sdelphij * purpose with or without fee is hereby granted, provided that the above 8184578Sdelphij * copyright notice and this permission notice appear in all copies. 965294Sdes * 10184578Sdelphij * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11184578Sdelphij * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12184578Sdelphij * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13184578Sdelphij * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14184578Sdelphij * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15184578Sdelphij * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16184578Sdelphij * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1765294Sdes */ 1865294Sdes 1990016Sbde#include <sys/cdefs.h> 2089999Sobrien__FBSDID("$FreeBSD: head/lib/libc/gen/dirname.c 184578 2008-11-03 05:19:45Z delphij $"); 2165294Sdes 2265294Sdes#include <errno.h> 2365294Sdes#include <libgen.h> 24108419Smarcel#include <stdlib.h> 2565294Sdes#include <string.h> 2665294Sdes#include <sys/param.h> 2765294Sdes 2865294Sdeschar * 29184578Sdelphijdirname(const char *path) 3065294Sdes{ 31184578Sdelphij static char *dname = NULL; 32184578Sdelphij size_t len; 3390041Sobrien const char *endp; 3465294Sdes 35184578Sdelphij if (dname == NULL) { 36184578Sdelphij dname = (char *)malloc(MAXPATHLEN); 37184578Sdelphij if (dname == NULL) 38108152Sbbraun return(NULL); 39108152Sbbraun } 40108152Sbbraun 4165294Sdes /* Empty or NULL string gets treated as "." */ 4265294Sdes if (path == NULL || *path == '\0') { 43184578Sdelphij dname[0] = '.'; 44184578Sdelphij dname[1] = '\0'; 45184578Sdelphij return (dname); 4665294Sdes } 4765294Sdes 48184578Sdelphij /* Strip any trailing slashes */ 4965294Sdes endp = path + strlen(path) - 1; 5065294Sdes while (endp > path && *endp == '/') 5165294Sdes endp--; 5265294Sdes 5365294Sdes /* Find the start of the dir */ 5465294Sdes while (endp > path && *endp != '/') 5565294Sdes endp--; 5665294Sdes 5765294Sdes /* Either the dir is "/" or there are no slashes */ 5865294Sdes if (endp == path) { 59184578Sdelphij dname[0] = *endp == '/' ? '/' : '.'; 60184578Sdelphij dname[1] = '\0'; 61184578Sdelphij return (dname); 6265294Sdes } else { 63184578Sdelphij /* Move forward past the separating slashes */ 6465294Sdes do { 6565294Sdes endp--; 6665294Sdes } while (endp > path && *endp == '/'); 6765294Sdes } 6865294Sdes 69184578Sdelphij len = endp - path + 1; 70184578Sdelphij if (len >= MAXPATHLEN) { 7165294Sdes errno = ENAMETOOLONG; 72184578Sdelphij return (NULL); 7365294Sdes } 74184578Sdelphij memcpy(dname, path, len); 75184578Sdelphij dname[len] = '\0'; 76184578Sdelphij return (dname); 7765294Sdes} 78