1/* dirname.c -- return all but the last element in a path 2 Copyright 1990, 1998, 2000, 2001 Free Software Foundation, Inc. 3 4 This program is free software; you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by 6 the Free Software Foundation; either version 2, or (at your option) 7 any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with this program; if not, write to the Free Software Foundation, 16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 17 18#if HAVE_CONFIG_H 19# include <config.h> 20#endif 21 22#if STDC_HEADERS || HAVE_STRING_H 23# include <string.h> 24#endif 25 26#include "dirname.h" 27#include "xalloc.h" 28 29/* Return the length of `dirname (PATH)', or zero if PATH is 30 in the working directory. Works properly even if 31 there are trailing slashes (by effectively ignoring them). */ 32size_t 33dir_len (char const *path) 34{ 35 size_t prefix_length = FILESYSTEM_PREFIX_LEN (path); 36 size_t length; 37 38 /* Strip the basename and any redundant slashes before it. */ 39 for (length = base_name (path) - path; prefix_length < length; length--) 40 if (! ISSLASH (path[length - 1])) 41 return length; 42 43 /* But don't strip the only slash from "/". */ 44 return prefix_length + ISSLASH (path[prefix_length]); 45} 46 47/* Return the leading directories part of PATH, 48 allocated with xmalloc. 49 Works properly even if there are trailing slashes 50 (by effectively ignoring them). */ 51 52char * 53dir_name (char const *path) 54{ 55 size_t length = dir_len (path); 56 int append_dot = (length == FILESYSTEM_PREFIX_LEN (path)); 57 char *newpath = xmalloc (length + append_dot + 1); 58 memcpy (newpath, path, length); 59 if (append_dot) 60 newpath[length++] = '.'; 61 newpath[length] = 0; 62 return newpath; 63} 64 65#ifdef TEST_DIRNAME 66/* 67 68Run the test like this (expect no output): 69 gcc -DHAVE_CONFIG_H -DTEST_DIRNAME -I.. -O -Wall \ 70 basename.c dirname.c xmalloc.c 71 sed -n '/^BEGIN-DATA$/,/^END-DATA$/p' dirname.c|grep -v DATA|./a.out 72 73BEGIN-DATA 74foo//// . 75bar/foo//// bar 76foo/ . 77/ / 78. . 79a . 80END-DATA 81 82*/ 83 84# define MAX_BUFF_LEN 1024 85# include <stdio.h> 86 87int 88main () 89{ 90 char buff[MAX_BUFF_LEN + 1]; 91 92 buff[MAX_BUFF_LEN] = 0; 93 while (fgets (buff, MAX_BUFF_LEN, stdin) && buff[0]) 94 { 95 char path[MAX_BUFF_LEN]; 96 char expected_result[MAX_BUFF_LEN]; 97 char const *result; 98 sscanf (buff, "%s %s", path, expected_result); 99 result = dir_name (path); 100 if (strcmp (result, expected_result)) 101 printf ("%s: got %s, expected %s\n", path, result, expected_result); 102 } 103 return 0; 104} 105#endif 106