xref: /openbsd-src/lib/libc/gen/dirname.c (revision cf6da2c267aa357925acfdbab7adba6129c97978)
1*cf6da2c2Snaddy /*	$OpenBSD: dirname.c,v 1.17 2020/10/20 19:30:14 naddy Exp $	*/
22baf3e42Smillert 
32baf3e42Smillert /*
4bf198cc6Smillert  * Copyright (c) 1997, 2004 Todd C. Miller <millert@openbsd.org>
52baf3e42Smillert  *
606f01696Smillert  * Permission to use, copy, modify, and distribute this software for any
706f01696Smillert  * purpose with or without fee is hereby granted, provided that the above
806f01696Smillert  * copyright notice and this permission notice appear in all copies.
92baf3e42Smillert  *
10328f1f07Smillert  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11328f1f07Smillert  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12328f1f07Smillert  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13328f1f07Smillert  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14328f1f07Smillert  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15328f1f07Smillert  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16328f1f07Smillert  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
172baf3e42Smillert  */
182baf3e42Smillert 
192baf3e42Smillert #include <errno.h>
202baf3e42Smillert #include <libgen.h>
2169245ebdSmillert #include <limits.h>
222baf3e42Smillert #include <string.h>
232baf3e42Smillert 
24585a69dbSkurt /* A slightly modified copy of this file exists in libexec/ld.so */
25585a69dbSkurt 
262baf3e42Smillert char *
dirname(char * path)27*cf6da2c2Snaddy dirname(char *path)
282baf3e42Smillert {
2969245ebdSmillert 	static char dname[PATH_MAX];
306c39c219Smillert 	size_t len;
316c39c219Smillert 	const char *endp;
322baf3e42Smillert 
332baf3e42Smillert 	/* Empty or NULL string gets treated as "." */
342baf3e42Smillert 	if (path == NULL || *path == '\0') {
356c39c219Smillert 		dname[0] = '.';
366c39c219Smillert 		dname[1] = '\0';
376c39c219Smillert 		return (dname);
382baf3e42Smillert 	}
392baf3e42Smillert 
406c39c219Smillert 	/* Strip any trailing slashes */
412baf3e42Smillert 	endp = path + strlen(path) - 1;
422baf3e42Smillert 	while (endp > path && *endp == '/')
432baf3e42Smillert 		endp--;
442baf3e42Smillert 
452baf3e42Smillert 	/* Find the start of the dir */
462baf3e42Smillert 	while (endp > path && *endp != '/')
472baf3e42Smillert 		endp--;
482baf3e42Smillert 
492baf3e42Smillert 	/* Either the dir is "/" or there are no slashes */
502baf3e42Smillert 	if (endp == path) {
516c39c219Smillert 		dname[0] = *endp == '/' ? '/' : '.';
526c39c219Smillert 		dname[1] = '\0';
536c39c219Smillert 		return (dname);
542baf3e42Smillert 	} else {
556c39c219Smillert 		/* Move forward past the separating slashes */
562baf3e42Smillert 		do {
572baf3e42Smillert 			endp--;
582baf3e42Smillert 		} while (endp > path && *endp == '/');
592baf3e42Smillert 	}
602baf3e42Smillert 
616c39c219Smillert 	len = endp - path + 1;
626c39c219Smillert 	if (len >= sizeof(dname)) {
632baf3e42Smillert 		errno = ENAMETOOLONG;
642baf3e42Smillert 		return (NULL);
652baf3e42Smillert 	}
666c39c219Smillert 	memcpy(dname, path, len);
676c39c219Smillert 	dname[len] = '\0';
686c39c219Smillert 	return (dname);
692baf3e42Smillert }
70