
1: /* dirname.c -- return all but the last element in a file name 2: 3: Copyright (C) 1990, 1998, 2000, 2001, 2003, 2004, 2005, 2006 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: #include <config.h> 21: 22: #include "dirname.h" 23: 24: #include <string.h> 25: #include "xalloc.h" 26: 27: /* Return the length of the prefix of FILE that will be used by 28: dir_name. If FILE is in the working directory, this returns zero 29: even though `dir_name (FILE)' will return ".". Works properly even 30: if there are trailing slashes (by effectively ignoring them). */ 31: 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: /* Advance prefix_length beyond important leading slashes. */ 39: prefix_length += (prefix_length != 0 40: ? (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 41: && ISSLASH (file[prefix_length])) 42: : (ISSLASH (file[0]) 43: ? ((DOUBLE_SLASH_IS_DISTINCT_ROOT 44: && ISSLASH (file[1]) && ! ISSLASH (file[2]) 45: ? 2 : 1)) 46: : 0)); 47: 48: /* Strip the basename and any redundant slashes before it. */ 49: for (length = last_component (file) - file; 50: prefix_length < length; length--) 51: if (! ISSLASH (file[length - 1])) 52: break; 53: return length; 54: } 55: 56: 57: /* In general, we can't use the builtin `dirname' function if available, 58: since it has different meanings in different environments. 59: In some environments the builtin `dirname' modifies its argument. 60: 61: Return the leading directories part of FILE, allocated with xmalloc. 62: Works properly even if there are trailing slashes (by effectively 63: ignoring them). Unlike POSIX dirname(), FILE cannot be NULL. 64: 65: If lstat (FILE) would succeed, then { chdir (dir_name (FILE)); 66: lstat (base_name (FILE)); } will access the same file. Likewise, 67: if the sequence { chdir (dir_name (FILE)); 68: rename (base_name (FILE), "foo"); } succeeds, you have renamed FILE 69: to "foo" in the same directory FILE was in. */ 70: 71: char * 72: dir_name (char const *file) 73: { 74: size_t length = dir_len (file); 75: bool append_dot = (length == 0 76: || (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 77: && length == FILE_SYSTEM_PREFIX_LEN (file) 78: && file[2] != '\0' && ! ISSLASH (file[2]))); 79: char *dir = xmalloc (length + append_dot + 1); 80: memcpy (dir, file, length); 81: if (append_dot) 82: dir[length++] = '.'; 83: dir[length] = '\0'; 84: return dir; 85: }