Blame gnulib/lib/dirname-lgpl.c

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