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