Blame lib/dirname-lgpl.c

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