X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fpath-concat.c;h=3a143c7aaa3cd0f80b3eb2dd51dd1903897cfa6d;hb=2bf674b2395b6aff54eff7928d24f2995c37c28e;hp=ce74ed1334ee1a3778ed7fcc281138bfa7c97456;hpb=8ddb64cf1508f8f7d64d1e23285a7ce6f2bbd7fd;p=gnulib.git diff --git a/lib/path-concat.c b/lib/path-concat.c index ce74ed133..3a143c7aa 100644 --- a/lib/path-concat.c +++ b/lib/path-concat.c @@ -1,5 +1,7 @@ /* path-concat.c -- concatenate two arbitrary pathnames - Copyright (C) 1996 Free Software Foundation, Inc. + + Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002 Free + Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,42 +19,111 @@ /* Written by Jim Meyering. */ -#ifdef HAVE_CONFIG_H -#include +#if HAVE_CONFIG_H +# include +#endif + +#ifndef HAVE_MEMPCPY +# define mempcpy(D, S, N) ((void *) ((char *) memcpy (D, S, N) + (N))) #endif +#include + +#if HAVE_STRING_H +# if !STDC_HEADERS && HAVE_MEMORY_H +# include +# endif +# include +#else +# if HAVE_STRINGS_H +# include +# endif +#endif +#if HAVE_STDLIB_H +# include +#endif +#if HAVE_UNISTD_H +# include +#endif + +#ifndef HAVE_DECL_MALLOC +"this configure-time declaration test was not run" +#endif +#if !HAVE_DECL_MALLOC char *malloc (); -char *stpcpy (); +#endif + +#ifndef strdup +char *strdup (); +#endif + +#include "dirname.h" +#include "xalloc.h" +#include "path-concat.h" + +/* Concatenate two pathname components, DIR and BASE, in + newly-allocated storage and return the result. Return 0 if out of + memory. Add a slash between DIR and BASE in the result if neither + would contribute one. If each would contribute at least one, elide + one from the end of DIR. Otherwise, simply concatenate DIR and + BASE. In any case, if BASE_IN_RESULT is non-NULL, set + *BASE_IN_RESULT to point to the copy of BASE in the returned + concatenation. -/* Concatenate two pathname components, DIR and BASE, in newly-allocated - storage and return the result. Return 0 if out of memory. Add a slash - between DIR and BASE in the result if neither would contribute one. - If each would contribute at least one, elide one from the end of DIR. - Otherwise, simply concatenate DIR and BASE. In any case, if - BASE_IN_RESULT is non-NULL, set *BASE_IN_RESULT to point to the copy of - BASE in the returned concatenation. */ + DIR may be NULL, BASE must not be. + + Return NULL if memory is exhausted. */ char * path_concat (const char *dir, const char *base, char **base_in_result) { char *p; char *p_concat; + size_t baselen; + size_t dirlen; + + if (!dir) + { + p_concat = strdup (base); + if (base_in_result) + *base_in_result = p_concat; + return p_concat; + } + + /* DIR is not empty. */ + baselen = base_len (base); + dirlen = strlen (dir); - p_concat = malloc (strlen (dir) + strlen (base) + 2); + p_concat = malloc (dirlen + baselen + 2); if (!p_concat) return 0; - p = stpcpy (p_concat, dir); + p = mempcpy (p_concat, dir, dirlen); - if (*(p - 1) == '/' && *base == '/') - --p; - else if (*(p - 1) != '/' && *base != '/') - p = stpcpy (p, "/"); + if (FILESYSTEM_PREFIX_LEN (dir) < dirlen) + { + if (ISSLASH (*(p - 1)) && ISSLASH (*base)) + --p; + else if (!ISSLASH (*(p - 1)) && !ISSLASH (*base)) + *p++ = DIRECTORY_SEPARATOR; + } if (base_in_result) *base_in_result = p; - stpcpy (p, base); + memcpy (p, base, baselen); + p[baselen] = '\0'; return p_concat; } + +/* Same, but die when memory is exhausted. */ + +char * +xpath_concat (const char *dir, const char *base, char **base_in_result) +{ + char *res = path_concat (dir, base, base_in_result); + if (! res) + xalloc_die (); + return res; +}