1ca58f742SDaniel Fojt /* $NetBSD: dirname.c,v 1.14 2018/09/27 00:45:34 kre Exp $ */
201e196c8SJohn Marino
301e196c8SJohn Marino /*-
401e196c8SJohn Marino * Copyright (c) 1997, 2002 The NetBSD Foundation, Inc.
501e196c8SJohn Marino * All rights reserved.
601e196c8SJohn Marino *
701e196c8SJohn Marino * This code is derived from software contributed to The NetBSD Foundation
801e196c8SJohn Marino * by Klaus Klein and Jason R. Thorpe.
901e196c8SJohn Marino *
1001e196c8SJohn Marino * Redistribution and use in source and binary forms, with or without
1101e196c8SJohn Marino * modification, are permitted provided that the following conditions
1201e196c8SJohn Marino * are met:
1301e196c8SJohn Marino * 1. Redistributions of source code must retain the above copyright
1401e196c8SJohn Marino * notice, this list of conditions and the following disclaimer.
1501e196c8SJohn Marino * 2. Redistributions in binary form must reproduce the above copyright
1601e196c8SJohn Marino * notice, this list of conditions and the following disclaimer in the
1701e196c8SJohn Marino * documentation and/or other materials provided with the distribution.
1801e196c8SJohn Marino *
1901e196c8SJohn Marino * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2001e196c8SJohn Marino * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2101e196c8SJohn Marino * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2201e196c8SJohn Marino * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2301e196c8SJohn Marino * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2401e196c8SJohn Marino * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2501e196c8SJohn Marino * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2601e196c8SJohn Marino * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2701e196c8SJohn Marino * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2801e196c8SJohn Marino * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2901e196c8SJohn Marino * POSSIBILITY OF SUCH DAMAGE.
3001e196c8SJohn Marino */
3101e196c8SJohn Marino
3201e196c8SJohn Marino #ifdef HAVE_CONFIG_H
3301e196c8SJohn Marino # include <config.h>
3401e196c8SJohn Marino #endif
3501e196c8SJohn Marino #ifndef HAVE_DIRNAME
3601e196c8SJohn Marino
3701e196c8SJohn Marino #include <sys/cdefs.h>
38ca58f742SDaniel Fojt #if defined(LIBC_SCCS) && !defined(lint)
39ca58f742SDaniel Fojt __RCSID("$NetBSD: dirname.c,v 1.14 2018/09/27 00:45:34 kre Exp $");
40ca58f742SDaniel Fojt #endif /* !LIBC_SCCS && !lint */
41ca58f742SDaniel Fojt
42f445c897SJohn Marino #include <sys/param.h>
43f445c897SJohn Marino #ifdef HAVE_LIBGEN_H
44f445c897SJohn Marino #include <libgen.h>
45f445c897SJohn Marino #endif
4601e196c8SJohn Marino #ifdef HAVE_LIMITS_H
4701e196c8SJohn Marino #include <limits.h>
4801e196c8SJohn Marino #endif
4901e196c8SJohn Marino #ifdef HAVE_STRING_H
5001e196c8SJohn Marino #include <string.h>
5101e196c8SJohn Marino #endif
5201e196c8SJohn Marino #ifndef PATH_MAX
5301e196c8SJohn Marino # define PATH_MAX 1024
5401e196c8SJohn Marino #endif
55f445c897SJohn Marino #ifndef MIN
56f445c897SJohn Marino # define MIN(a, b) ((a < b) ? a : b)
57f445c897SJohn Marino #endif
5801e196c8SJohn Marino
59f445c897SJohn Marino
60f445c897SJohn Marino static size_t
xdirname_r(const char * path,char * buf,size_t buflen)61f445c897SJohn Marino xdirname_r(const char *path, char *buf, size_t buflen)
6201e196c8SJohn Marino {
63f445c897SJohn Marino const char *endp;
6401e196c8SJohn Marino size_t len;
6501e196c8SJohn Marino
6601e196c8SJohn Marino /*
6701e196c8SJohn Marino * If `path' is a null pointer or points to an empty string,
6801e196c8SJohn Marino * return a pointer to the string ".".
6901e196c8SJohn Marino */
70f445c897SJohn Marino if (path == NULL || *path == '\0') {
71f445c897SJohn Marino path = ".";
72f445c897SJohn Marino len = 1;
73f445c897SJohn Marino goto out;
74f445c897SJohn Marino }
7501e196c8SJohn Marino
7601e196c8SJohn Marino /* Strip trailing slashes, if any. */
77f445c897SJohn Marino endp = path + strlen(path) - 1;
78f445c897SJohn Marino while (endp != path && *endp == '/')
79f445c897SJohn Marino endp--;
8001e196c8SJohn Marino
81f445c897SJohn Marino /* Find the start of the dir */
82f445c897SJohn Marino while (endp > path && *endp != '/')
83f445c897SJohn Marino endp--;
8401e196c8SJohn Marino
85f445c897SJohn Marino if (endp == path) {
86f445c897SJohn Marino path = *endp == '/' ? "/" : ".";
87f445c897SJohn Marino len = 1;
88f445c897SJohn Marino goto out;
8901e196c8SJohn Marino }
9001e196c8SJohn Marino
91f445c897SJohn Marino do
92f445c897SJohn Marino endp--;
93f445c897SJohn Marino while (endp > path && *endp == '/');
9401e196c8SJohn Marino
95f445c897SJohn Marino len = endp - path + 1;
96f445c897SJohn Marino out:
97f445c897SJohn Marino if (buf != NULL && buflen != 0) {
98f445c897SJohn Marino buflen = MIN(len, buflen - 1);
99ca58f742SDaniel Fojt if (buf != path)
100f445c897SJohn Marino memcpy(buf, path, buflen);
101f445c897SJohn Marino buf[buflen] = '\0';
10201e196c8SJohn Marino }
103f445c897SJohn Marino return len;
104f445c897SJohn Marino }
105f445c897SJohn Marino
106f445c897SJohn Marino char *
dirname(char * path)107f445c897SJohn Marino dirname(char *path)
108f445c897SJohn Marino {
109f445c897SJohn Marino static char result[PATH_MAX];
110f445c897SJohn Marino (void)xdirname_r(path, result, sizeof(result));
111f445c897SJohn Marino return result;
112f445c897SJohn Marino }
113f445c897SJohn Marino
114f445c897SJohn Marino #ifdef MAIN
115f445c897SJohn Marino #include <stdlib.h>
116f445c897SJohn Marino #include <stdio.h>
117f445c897SJohn Marino
118f445c897SJohn Marino int
main(int argc,char * argv[])119f445c897SJohn Marino main(int argc, char *argv[])
120f445c897SJohn Marino {
121f445c897SJohn Marino printf("%s\n", dirname(argv[1]));
122f445c897SJohn Marino exit(0);
123f445c897SJohn Marino }
124f445c897SJohn Marino #endif
12501e196c8SJohn Marino #endif
126