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