1*d794b9b6Skre /* $NetBSD: dirname.c,v 1.14 2018/09/27 00:45:34 kre Exp $ */
28bfc0cefSkleink
38bfc0cefSkleink /*-
4c10a556fSthorpej * Copyright (c) 1997, 2002 The NetBSD Foundation, Inc.
58bfc0cefSkleink * All rights reserved.
68bfc0cefSkleink *
78bfc0cefSkleink * This code is derived from software contributed to The NetBSD Foundation
8c10a556fSthorpej * by Klaus Klein and Jason R. Thorpe.
98bfc0cefSkleink *
108bfc0cefSkleink * Redistribution and use in source and binary forms, with or without
118bfc0cefSkleink * modification, are permitted provided that the following conditions
128bfc0cefSkleink * are met:
138bfc0cefSkleink * 1. Redistributions of source code must retain the above copyright
148bfc0cefSkleink * notice, this list of conditions and the following disclaimer.
158bfc0cefSkleink * 2. Redistributions in binary form must reproduce the above copyright
168bfc0cefSkleink * notice, this list of conditions and the following disclaimer in the
178bfc0cefSkleink * documentation and/or other materials provided with the distribution.
188bfc0cefSkleink *
198bfc0cefSkleink * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
208bfc0cefSkleink * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
218bfc0cefSkleink * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
228bfc0cefSkleink * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
238bfc0cefSkleink * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
248bfc0cefSkleink * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
258bfc0cefSkleink * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
268bfc0cefSkleink * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
278bfc0cefSkleink * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
288bfc0cefSkleink * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
298bfc0cefSkleink * POSSIBILITY OF SUCH DAMAGE.
308bfc0cefSkleink */
318bfc0cefSkleink
328bfc0cefSkleink #include <sys/cdefs.h>
338bfc0cefSkleink #if defined(LIBC_SCCS) && !defined(lint)
34*d794b9b6Skre __RCSID("$NetBSD: dirname.c,v 1.14 2018/09/27 00:45:34 kre Exp $");
358bfc0cefSkleink #endif /* !LIBC_SCCS && !lint */
368bfc0cefSkleink
378bfc0cefSkleink #include "namespace.h"
3859925ff2Schristos #include <sys/param.h>
398bfc0cefSkleink #include <libgen.h>
40c10a556fSthorpej #include <limits.h>
419fbd8888Stv #include <string.h>
428bfc0cefSkleink
438bfc0cefSkleink #ifdef __weak_alias
__weak_alias(dirname,_dirname)4460549036Smycroft __weak_alias(dirname,_dirname)
458bfc0cefSkleink #endif
468bfc0cefSkleink
4759925ff2Schristos static size_t
48db6e70afSchristos xdirname_r(const char *path, char *buf, size_t buflen)
498bfc0cefSkleink {
5059925ff2Schristos const char *endp;
51c10a556fSthorpej size_t len;
528bfc0cefSkleink
538bfc0cefSkleink /*
54c10a556fSthorpej * If `path' is a null pointer or points to an empty string,
55c10a556fSthorpej * return a pointer to the string ".".
568bfc0cefSkleink */
5759925ff2Schristos if (path == NULL || *path == '\0') {
5859925ff2Schristos path = ".";
5959925ff2Schristos len = 1;
6059925ff2Schristos goto out;
61c10a556fSthorpej }
62c10a556fSthorpej
6359925ff2Schristos /* Strip trailing slashes, if any. */
6459925ff2Schristos endp = path + strlen(path) - 1;
6559925ff2Schristos while (endp != path && *endp == '/')
6659925ff2Schristos endp--;
673f8ca7c4Stnozaki
6859925ff2Schristos /* Find the start of the dir */
6959925ff2Schristos while (endp > path && *endp != '/')
7059925ff2Schristos endp--;
7159925ff2Schristos
7259925ff2Schristos if (endp == path) {
7359925ff2Schristos path = *endp == '/' ? "/" : ".";
7459925ff2Schristos len = 1;
7559925ff2Schristos goto out;
7659925ff2Schristos }
7759925ff2Schristos
7859925ff2Schristos do
7959925ff2Schristos endp--;
8059925ff2Schristos while (endp > path && *endp == '/');
8159925ff2Schristos
8259925ff2Schristos len = endp - path + 1;
8359925ff2Schristos out:
8459925ff2Schristos if (buf != NULL && buflen != 0) {
8559925ff2Schristos buflen = MIN(len, buflen - 1);
86*d794b9b6Skre if (buf != path)
8759925ff2Schristos memcpy(buf, path, buflen);
8859925ff2Schristos buf[buflen] = '\0';
8959925ff2Schristos }
9059925ff2Schristos return len;
9159925ff2Schristos }
9259925ff2Schristos
9359925ff2Schristos #if !HAVE_DIRNAME
9459925ff2Schristos char *
dirname(char * path)9559925ff2Schristos dirname(char *path)
9659925ff2Schristos {
9759925ff2Schristos static char result[PATH_MAX];
98db6e70afSchristos (void)xdirname_r(path, result, sizeof(result));
9959925ff2Schristos return result;
1008bfc0cefSkleink }
101c08a2cb7Stv #endif
102