Blame lib/dirname-lgpl.c

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