Blame lib/dirname-lgpl.c

Packit 709fb3
/* dirname.c -- return all but the last element in a file name
Packit 709fb3
Packit 709fb3
   Copyright (C) 1990, 1998, 2000-2001, 2003-2006, 2009-2017 Free Software
Packit 709fb3
   Foundation, Inc.
Packit 709fb3
Packit 709fb3
   This program is free software: you can redistribute it and/or modify
Packit 709fb3
   it under the terms of the GNU General Public License as published by
Packit 709fb3
   the Free Software Foundation; either version 3 of the License, or
Packit 709fb3
   (at your option) any later version.
Packit 709fb3
Packit 709fb3
   This program is distributed in the hope that it will be useful,
Packit 709fb3
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 709fb3
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 709fb3
   GNU General Public License for more details.
Packit 709fb3
Packit 709fb3
   You should have received a copy of the GNU General Public License
Packit 709fb3
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
Packit 709fb3
Packit 709fb3
#include <config.h>
Packit 709fb3
Packit 709fb3
#include "dirname.h"
Packit 709fb3
Packit 709fb3
#include <stdlib.h>
Packit 709fb3
#include <string.h>
Packit 709fb3
Packit 709fb3
/* Return the length of the prefix of FILE that will be used by
Packit 709fb3
   dir_name.  If FILE is in the working directory, this returns zero
Packit 709fb3
   even though 'dir_name (FILE)' will return ".".  Works properly even
Packit 709fb3
   if there are trailing slashes (by effectively ignoring them).  */
Packit 709fb3
Packit 709fb3
size_t
Packit 709fb3
dir_len (char const *file)
Packit 709fb3
{
Packit 709fb3
  size_t prefix_length = FILE_SYSTEM_PREFIX_LEN (file);
Packit 709fb3
  size_t length;
Packit 709fb3
Packit 709fb3
  /* Advance prefix_length beyond important leading slashes.  */
Packit 709fb3
  prefix_length += (prefix_length != 0
Packit 709fb3
                    ? (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
Packit 709fb3
                       && ISSLASH (file[prefix_length]))
Packit 709fb3
                    : (ISSLASH (file[0])
Packit 709fb3
                       ? ((DOUBLE_SLASH_IS_DISTINCT_ROOT
Packit 709fb3
                           && ISSLASH (file[1]) && ! ISSLASH (file[2])
Packit 709fb3
                           ? 2 : 1))
Packit 709fb3
                       : 0));
Packit 709fb3
Packit 709fb3
  /* Strip the basename and any redundant slashes before it.  */
Packit 709fb3
  for (length = last_component (file) - file;
Packit 709fb3
       prefix_length < length; length--)
Packit 709fb3
    if (! ISSLASH (file[length - 1]))
Packit 709fb3
      break;
Packit 709fb3
  return length;
Packit 709fb3
}
Packit 709fb3
Packit 709fb3
Packit 709fb3
/* In general, we can't use the builtin 'dirname' function if available,
Packit 709fb3
   since it has different meanings in different environments.
Packit 709fb3
   In some environments the builtin 'dirname' modifies its argument.
Packit 709fb3
Packit 709fb3
   Return the leading directories part of FILE, allocated with malloc.
Packit 709fb3
   Works properly even if there are trailing slashes (by effectively
Packit 709fb3
   ignoring them).  Return NULL on failure.
Packit 709fb3
Packit 709fb3
   If lstat (FILE) would succeed, then { chdir (dir_name (FILE));
Packit 709fb3
   lstat (base_name (FILE)); } will access the same file.  Likewise,
Packit 709fb3
   if the sequence { chdir (dir_name (FILE));
Packit 709fb3
   rename (base_name (FILE), "foo"); } succeeds, you have renamed FILE
Packit 709fb3
   to "foo" in the same directory FILE was in.  */
Packit 709fb3
Packit 709fb3
char *
Packit 709fb3
mdir_name (char const *file)
Packit 709fb3
{
Packit 709fb3
  size_t length = dir_len (file);
Packit 709fb3
  bool append_dot = (length == 0
Packit 709fb3
                     || (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
Packit 709fb3
                         && length == FILE_SYSTEM_PREFIX_LEN (file)
Packit 709fb3
                         && file[2] != '\0' && ! ISSLASH (file[2])));
Packit 709fb3
  char *dir = malloc (length + append_dot + 1);
Packit 709fb3
  if (!dir)
Packit 709fb3
    return NULL;
Packit 709fb3
  memcpy (dir, file, length);
Packit 709fb3
  if (append_dot)
Packit 709fb3
    dir[length++] = '.';
Packit 709fb3
  dir[length] = '\0';
Packit 709fb3
  return dir;
Packit 709fb3
}