1296637Ssjg/* $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> 38296637Ssjg#include <sys/param.h> 39296637Ssjg#ifdef HAVE_LIBGEN_H 40296637Ssjg#include <libgen.h> 41296637Ssjg#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 51296637Ssjg#ifndef MIN 52296637Ssjg# define MIN(a, b) ((a < b) ? a : b) 53296637Ssjg#endif 54236769Sobrien 55296637Ssjg 56296637Ssjgstatic size_t 57296637Ssjgxdirname_r(const char *path, char *buf, size_t buflen) 58236769Sobrien{ 59296637Ssjg 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 */ 66296637Ssjg if (path == NULL || *path == '\0') { 67296637Ssjg path = "."; 68296637Ssjg len = 1; 69296637Ssjg goto out; 70296637Ssjg } 71236769Sobrien 72236769Sobrien /* Strip trailing slashes, if any. */ 73296637Ssjg endp = path + strlen(path) - 1; 74296637Ssjg while (endp != path && *endp == '/') 75296637Ssjg endp--; 76236769Sobrien 77296637Ssjg /* Find the start of the dir */ 78296637Ssjg while (endp > path && *endp != '/') 79296637Ssjg endp--; 80236769Sobrien 81296637Ssjg if (endp == path) { 82296637Ssjg path = *endp == '/' ? "/" : "."; 83296637Ssjg len = 1; 84296637Ssjg goto out; 85296637Ssjg } 86236769Sobrien 87296637Ssjg do 88296637Ssjg endp--; 89296637Ssjg while (endp > path && *endp == '/'); 90236769Sobrien 91296637Ssjg len = endp - path + 1; 92296637Ssjgout: 93296637Ssjg if (buf != NULL && buflen != 0) { 94296637Ssjg buflen = MIN(len, buflen - 1); 95296637Ssjg memcpy(buf, path, buflen); 96296637Ssjg buf[buflen] = '\0'; 97296637Ssjg } 98296637Ssjg return len; 99296637Ssjg} 100236769Sobrien 101296637Ssjgchar * 102296637Ssjgdirname(char *path) 103296637Ssjg{ 104296637Ssjg static char result[PATH_MAX]; 105296637Ssjg (void)xdirname_r(path, result, sizeof(result)); 106296637Ssjg return result; 107296637Ssjg} 108236769Sobrien 109296637Ssjg#ifdef MAIN 110296637Ssjg#include <stdlib.h> 111296637Ssjg#include <stdio.h> 112296637Ssjg 113296637Ssjgint 114296637Ssjgmain(int argc, char *argv[]) 115296637Ssjg{ 116296637Ssjg printf("%s\n", dirname(argv[1])); 117296637Ssjg exit(0); 118236769Sobrien} 119236769Sobrien#endif 120296637Ssjg#endif 121