1321964Ssjg/* $NetBSD: dirname.c,v 1.13 2014/07/16 10:52:26 christos Exp $ */ 2236769Sobrien 3236769Sobrien/*- 4236769Sobrien * Copyright (c) 1997, 2002 The NetBSD Foundation, Inc. 5236769Sobrien * All rights reserved. 6236769Sobrien * 7236769Sobrien * This code is derived from software contributed to The NetBSD Foundation 8236769Sobrien * by Klaus Klein and Jason R. Thorpe. 9236769Sobrien * 10236769Sobrien * Redistribution and use in source and binary forms, with or without 11236769Sobrien * modification, are permitted provided that the following conditions 12236769Sobrien * are met: 13236769Sobrien * 1. Redistributions of source code must retain the above copyright 14236769Sobrien * notice, this list of conditions and the following disclaimer. 15236769Sobrien * 2. Redistributions in binary form must reproduce the above copyright 16236769Sobrien * notice, this list of conditions and the following disclaimer in the 17236769Sobrien * documentation and/or other materials provided with the distribution. 18236769Sobrien * 19236769Sobrien * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20236769Sobrien * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21236769Sobrien * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22236769Sobrien * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23236769Sobrien * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24236769Sobrien * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25236769Sobrien * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26236769Sobrien * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27236769Sobrien * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28236769Sobrien * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29236769Sobrien * POSSIBILITY OF SUCH DAMAGE. 30236769Sobrien */ 31236769Sobrien 32236769Sobrien#ifdef HAVE_CONFIG_H 33236769Sobrien# include <config.h> 34236769Sobrien#endif 35236769Sobrien#ifndef HAVE_DIRNAME 36236769Sobrien 37236769Sobrien#include <sys/cdefs.h> 38321964Ssjg#include <sys/param.h> 39321964Ssjg#ifdef HAVE_LIBGEN_H 40321964Ssjg#include <libgen.h> 41321964Ssjg#endif 42236769Sobrien#ifdef HAVE_LIMITS_H 43236769Sobrien#include <limits.h> 44236769Sobrien#endif 45236769Sobrien#ifdef HAVE_STRING_H 46236769Sobrien#include <string.h> 47236769Sobrien#endif 48236769Sobrien#ifndef PATH_MAX 49236769Sobrien# define PATH_MAX 1024 50236769Sobrien#endif 51321964Ssjg#ifndef MIN 52321964Ssjg# define MIN(a, b) ((a < b) ? a : b) 53321964Ssjg#endif 54236769Sobrien 55321964Ssjg 56321964Ssjgstatic size_t 57321964Ssjgxdirname_r(const char *path, char *buf, size_t buflen) 58236769Sobrien{ 59321964Ssjg const char *endp; 60236769Sobrien size_t len; 61236769Sobrien 62236769Sobrien /* 63236769Sobrien * If `path' is a null pointer or points to an empty string, 64236769Sobrien * return a pointer to the string ".". 65236769Sobrien */ 66321964Ssjg if (path == NULL || *path == '\0') { 67321964Ssjg path = "."; 68321964Ssjg len = 1; 69321964Ssjg goto out; 70321964Ssjg } 71236769Sobrien 72236769Sobrien /* Strip trailing slashes, if any. */ 73321964Ssjg endp = path + strlen(path) - 1; 74321964Ssjg while (endp != path && *endp == '/') 75321964Ssjg endp--; 76236769Sobrien 77321964Ssjg /* Find the start of the dir */ 78321964Ssjg while (endp > path && *endp != '/') 79321964Ssjg endp--; 80236769Sobrien 81321964Ssjg if (endp == path) { 82321964Ssjg path = *endp == '/' ? "/" : "."; 83321964Ssjg len = 1; 84321964Ssjg goto out; 85321964Ssjg } 86236769Sobrien 87321964Ssjg do 88321964Ssjg endp--; 89321964Ssjg while (endp > path && *endp == '/'); 90236769Sobrien 91321964Ssjg len = endp - path + 1; 92321964Ssjgout: 93321964Ssjg if (buf != NULL && buflen != 0) { 94321964Ssjg buflen = MIN(len, buflen - 1); 95321964Ssjg memcpy(buf, path, buflen); 96321964Ssjg buf[buflen] = '\0'; 97321964Ssjg } 98321964Ssjg return len; 99321964Ssjg} 100236769Sobrien 101321964Ssjgchar * 102321964Ssjgdirname(char *path) 103321964Ssjg{ 104321964Ssjg static char result[PATH_MAX]; 105321964Ssjg (void)xdirname_r(path, result, sizeof(result)); 106321964Ssjg return result; 107321964Ssjg} 108236769Sobrien 109321964Ssjg#ifdef MAIN 110321964Ssjg#include <stdlib.h> 111321964Ssjg#include <stdio.h> 112321964Ssjg 113321964Ssjgint 114321964Ssjgmain(int argc, char *argv[]) 115321964Ssjg{ 116321964Ssjg printf("%s\n", dirname(argv[1])); 117321964Ssjg exit(0); 118236769Sobrien} 119236769Sobrien#endif 120321964Ssjg#endif 121