1/* dirname.c -- return all but the last element in a file name 2 3 Copyright (C) 1990, 1998, 2000, 2001, 2003, 2004, 2005 Free Software 4 Foundation, Inc. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2, or (at your option) 9 any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software Foundation, 18 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ 19 20#ifdef HAVE_CONFIG_H 21# include <config.h> 22#endif 23 24#include "dirname.h" 25 26#include <string.h> 27#include "xalloc.h" 28 29/* Return the length of `dirname (FILE)', or zero if FILE 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 *file) 34{ 35 size_t prefix_length = FILE_SYSTEM_PREFIX_LEN (file); 36 size_t length; 37 38 /* Strip the basename and any redundant slashes before it. */ 39 for (length = base_name (file) - file; prefix_length < length; length--) 40 if (! ISSLASH (file[length - 1])) 41 return length; 42 43 /* But don't strip the only slash from "/". */ 44 return prefix_length + ISSLASH (file[prefix_length]); 45} 46 47/* Return the leading directories part of FILE, 48 allocated with xmalloc. 49 Works properly even if there are trailing slashes 50 (by effectively ignoring them). */ 51 52char * 53dir_name (char const *file) 54{ 55 size_t length = dir_len (file); 56 bool append_dot = (length == FILE_SYSTEM_PREFIX_LEN (file)); 57 char *dir = xmalloc (length + append_dot + 1); 58 memcpy (dir, file, length); 59 if (append_dot) 60 dir[length++] = '.'; 61 dir[length] = 0; 62 return dir; 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 error.c 71 sed -n '/^BEGIN-DATA$/,/^END-DATA$/p' dirname.c|grep -v DATA|./a.out 72 73If it's been built on a DOS or Windows platforms, run another test like 74this (again, expect no output): 75 sed -n '/^BEGIN-DOS-DATA$/,/^END-DOS-DATA$/p' dirname.c|grep -v DATA|./a.out 76 77BEGIN-DATA 78foo//// . 79bar/foo//// bar 80foo/ . 81/ / 82. . 83a . 84END-DATA 85 86BEGIN-DOS-DATA 87c:///// c:/ 88c:/ c:/ 89c:/. c:/ 90c:foo c:. 91c:foo/bar c:foo 92END-DOS-DATA 93 94*/ 95 96# define MAX_BUFF_LEN 1024 97# include <stdio.h> 98 99char *program_name; 100 101int 102main (int argc, char *argv[]) 103{ 104 char buff[MAX_BUFF_LEN + 1]; 105 106 program_name = argv[0]; 107 108 buff[MAX_BUFF_LEN] = 0; 109 while (fgets (buff, MAX_BUFF_LEN, stdin) && buff[0]) 110 { 111 char file[MAX_BUFF_LEN]; 112 char expected_result[MAX_BUFF_LEN]; 113 char const *result; 114 sscanf (buff, "%s %s", file, expected_result); 115 result = dir_name (file); 116 if (strcmp (result, expected_result)) 117 printf ("%s: got %s, expected %s\n", file, result, expected_result); 118 } 119 return 0; 120} 121#endif 122