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$");
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