Blame lib/dirname-lgpl.c

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