File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libiconv / srclib / dirname-lgpl.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 13:38:46 2021 UTC (4 years ago) by misho
Branches: libiconv, MAIN
CVS tags: v1_16p0, HEAD
libiconv 1.16

    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>