(linenum→info "unix/slp.c:2238")

coreutils/6.9/lib/dirname.c

    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: }
Syntax (Markdown)