Blame lib/filenamecat-lgpl.c

Packit Service fdd496
/* Concatenate two arbitrary file names.
Packit Service fdd496
Packit Service fdd496
   Copyright (C) 1996-2007, 2009-2017 Free Software Foundation, Inc.
Packit Service fdd496
Packit Service fdd496
   This program is free software: you can redistribute it and/or modify
Packit Service fdd496
   it under the terms of the GNU General Public License as published by
Packit Service fdd496
   the Free Software Foundation; either version 3 of the License, or
Packit Service fdd496
   (at your option) any later version.
Packit Service fdd496
Packit Service fdd496
   This program is distributed in the hope that it will be useful,
Packit Service fdd496
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service fdd496
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service fdd496
   GNU General Public License for more details.
Packit Service fdd496
Packit Service fdd496
   You should have received a copy of the GNU General Public License
Packit Service fdd496
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
Packit Service fdd496
Packit Service fdd496
/* Written by Jim Meyering.  */
Packit Service fdd496
Packit Service fdd496
#include <config.h>
Packit Service fdd496
Packit Service fdd496
/* Specification.  */
Packit Service fdd496
#include "filenamecat.h"
Packit Service fdd496
Packit Service fdd496
#include <stdlib.h>
Packit Service fdd496
#include <string.h>
Packit Service fdd496
Packit Service fdd496
#include "dirname.h"
Packit Service fdd496
Packit Service fdd496
#if ! HAVE_MEMPCPY && ! defined mempcpy
Packit Service fdd496
# define mempcpy(D, S, N) ((void *) ((char *) memcpy (D, S, N) + (N)))
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
/* Return the longest suffix of F that is a relative file name.
Packit Service fdd496
   If it has no such suffix, return the empty string.  */
Packit Service fdd496
Packit Service fdd496
static char const * _GL_ATTRIBUTE_PURE
Packit Service fdd496
longest_relative_suffix (char const *f)
Packit Service fdd496
{
Packit Service fdd496
  for (f += FILE_SYSTEM_PREFIX_LEN (f); ISSLASH (*f); f++)
Packit Service fdd496
    continue;
Packit Service fdd496
  return f;
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
/* Concatenate two file name components, DIR and ABASE, in
Packit Service fdd496
   newly-allocated storage and return the result.
Packit Service fdd496
   The resulting file name F is such that the commands "ls F" and "(cd
Packit Service fdd496
   DIR; ls BASE)" refer to the same file, where BASE is ABASE with any
Packit Service fdd496
   file system prefixes and leading separators removed.
Packit Service fdd496
   Arrange for a directory separator if necessary between DIR and BASE
Packit Service fdd496
   in the result, removing any redundant separators.
Packit Service fdd496
   In any case, if BASE_IN_RESULT is non-NULL, set
Packit Service fdd496
   *BASE_IN_RESULT to point to the copy of ABASE in the returned
Packit Service fdd496
   concatenation.  However, if ABASE begins with more than one slash,
Packit Service fdd496
   set *BASE_IN_RESULT to point to the sole corresponding slash that
Packit Service fdd496
   is copied into the result buffer.
Packit Service fdd496
Packit Service fdd496
   Return NULL if malloc fails.  */
Packit Service fdd496
Packit Service fdd496
char *
Packit Service fdd496
mfile_name_concat (char const *dir, char const *abase, char **base_in_result)
Packit Service fdd496
{
Packit Service fdd496
  char const *dirbase = last_component (dir);
Packit Service fdd496
  size_t dirbaselen = base_len (dirbase);
Packit Service fdd496
  size_t dirlen = dirbase - dir + dirbaselen;
Packit Service fdd496
  size_t needs_separator = (dirbaselen && ! ISSLASH (dirbase[dirbaselen - 1]));
Packit Service fdd496
Packit Service fdd496
  char const *base = longest_relative_suffix (abase);
Packit Service fdd496
  size_t baselen = strlen (base);
Packit Service fdd496
Packit Service fdd496
  char *p_concat = malloc (dirlen + needs_separator + baselen + 1);
Packit Service fdd496
  char *p;
Packit Service fdd496
Packit Service fdd496
  if (p_concat == NULL)
Packit Service fdd496
    return NULL;
Packit Service fdd496
Packit Service fdd496
  p = mempcpy (p_concat, dir, dirlen);
Packit Service fdd496
  *p = DIRECTORY_SEPARATOR;
Packit Service fdd496
  p += needs_separator;
Packit Service fdd496
Packit Service fdd496
  if (base_in_result)
Packit Service fdd496
    *base_in_result = p - IS_ABSOLUTE_FILE_NAME (abase);
Packit Service fdd496
Packit Service fdd496
  p = mempcpy (p, base, baselen);
Packit Service fdd496
  *p = '\0';
Packit Service fdd496
Packit Service fdd496
  return p_concat;
Packit Service fdd496
}