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). */ 32 size_t 33 dir_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 52 char * 53 dir_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 68 Run 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 73 If it's been built on a DOS or Windows platforms, run another test like 74 this (again, expect no output): 75 sed -n '/^BEGIN-DOS-DATA$/,/^END-DOS-DATA$/p' dirname.c|grep -v DATA|./a.out 76 77 BEGIN-DATA 78 foo//// . 79 bar/foo//// bar 80 foo/ . 81 / / 82 . . 83 a . 84 END-DATA 85 86 BEGIN-DOS-DATA 87 c:///// c:/ 88 c:/ c:/ 89 c:/. c:/ 90 c:foo c:. 91 c:foo/bar c:foo 92 END-DOS-DATA 93 94 */ 95 96 # define MAX_BUFF_LEN 1024 97 # include <stdio.h> 98 99 char *program_name; 100 101 int 102 main (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