comparison lib/filenamecat.c @ 5907:c47674a83a78

Sync from coreutils. Use "file name" when talking about file names, instead of "filename" or "path", as per the GNU coding standards. * MODULES.html.sh: mkdir-p renamed from makepath. filenamecat renamed from path-concat. * modules/filenamecat: Renamed from modules/path-concat. (Files): filenamecat.h and filenamecat.c renamed from path-concat.h and path-concat.c. (configure.ac): gl_FILE_NAME_CONCAT, not gl_PATH_CONCAT. (Include): filenamecat.h, not path-concat.h. * modules/mkdir-p: Renamed from modules/makepath. (Files): mkdir-p.h and mkdir-p.c renamed from makepath.h and makepath.c. (configure.ac): gl_MKDIR_PARENTS, not gl_MAKEPATH. (Include): mkdir-p.h, not makepath.h. * lib/mkdir-p.c: Renamed from makepath.c. (make_dir_parents): Renamed from make_path. All callers changed. * lib/mkdir-p.h: Likewise. All includers changed. * lib/filenamecat.c: Renamed from path-concat.c. (file_name_concat): Renamed from path_concat. All callers changed. [TEST_FILE_NAME_CONCAT]: Renamed from TEST_PATH_CONCAT. * lib/filenamecat.h: Likewise. All includers changed. * lib/acl.c: Don't use "path" or "filename" to mean "file name" in comments or local variable names. * lib/basename.c: Likewise. * lib/canonicalize.c, canonicalize.h: Likewise. * lib/dirname.c, dirname.h: Likewise. * lib/euidaccess.c: Likewise. * lib/exclude.c: Likewise * lib/fnmatch_.h, fnmatch_loop.c: Likewise. * lib/fsusage.c, fsuage.h: Likewise. * lib/fts.c, fts_.h: Likewise. * lib/getcwd.c: Likewise. * lib/getloadavg.c: Likewise. * lib/mkstemp.c: Likewise. * lib/mountlist.c, mountlist.h: Likewise. * lib/openat.c, openat.h: Likewise. * lib/readlink-stub.c: Likewise. * lib/readutmp.c, readutmp.h: Likewise. * lib/rename.c: Likewise. * lib/rmdir.c: Likewise. * lib/same.c: Likewise. * lib/savedir.c: Likewise. * lib/stripslash.c: Likewise. * lib/tempname.c: Likewise. * lib/xreadlink.c: Likewise. * lib/exclude.c (excluded_file_name): Renamed from excluded_filename. All uses changed. * lib/exclude.h: Likewise. * m4/mkdir-p.m4: Renamed from makepath.m4. (gl_MKDIR_PARENTS): Renamed from gl_MAKEPATH. All uses changed. Rename files from makepath.c to mkdir-p.c, and from makepath.h to mkdir-p.h. * m4/filenamecat.m4: Renamed from path-concat.m4. (gl_FILE_NAME_CONCAT): Renamed from gl_PATH_CONCAT. All uses changed. Rename files from path-concat.c to filenamecat.c, and from path-concat.h to filenamecat.h. * m4/getcwd-path-max.m4: Don't use "path" or "filename" to mean "file name" in local variables or comments. * rename.m4: Likewise. * lib/euidaccess.c (getuid, getgid, getuid, getegid) [!defined _POSIX_VERSION]: Remove decls; not needed these days. * lib/idcache.c (getpwuid, getpwnam, getgrgid, getgrnam) [!defined _POSIX_VERSION]: Remove decls; not needed these days. * lib/pathmax.h: Include <limits.h> unconditionally, since other files have been getting away with it for years (MORE/BSD 4.3 is extinct now). * lib/userspec.c (getpwnam, getgrnam, getgrgid) [!defined _POSIX_VERSION]: Remove decls; not needed these days. * lib/pathmax.h (_POSIX_PATH_MAX) [!defined _POSIX_PATH_MAX]: Define to 256, not 255, as per modern POSIX.
author Paul Eggert <eggert@cs.ucla.edu>
date Thu, 02 Jun 2005 20:41:04 +0000
parents
children 96c32553b4c6
comparison
equal deleted inserted replaced
5906:247f8fcff982 5907:c47674a83a78
1 /* Concatenate two arbitrary file names.
2
3 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free
4 Software Foundation, Inc.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software Foundation,
18 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19
20 /* Written by Jim Meyering. */
21
22 #if HAVE_CONFIG_H
23 # include <config.h>
24 #endif
25
26 /* Specification. */
27 #include "filenamecat.h"
28
29 #include <string.h>
30
31 #include "dirname.h"
32 #include "xalloc.h"
33
34 #if ! HAVE_MEMPCPY && ! defined mempcpy
35 # define mempcpy(D, S, N) ((void *) ((char *) memcpy (D, S, N) + (N)))
36 #endif
37
38 /* Return the longest suffix of F that is a relative file name.
39 If it has no such suffix, return the empty string. */
40
41 static char const *
42 longest_relative_suffix (char const *f)
43 {
44 for (f += FILE_SYSTEM_PREFIX_LEN (f); ISSLASH (*f); f++)
45 continue;
46 return f;
47 }
48
49 /* Concatenate two file name components, DIR and ABASE, in
50 newly-allocated storage and return the result.
51 The resulting file name F is such that the commands "ls F" and "(cd
52 DIR; ls BASE)" refer to the same file, where BASE is ABASE with any
53 file system prefixes and leading separators removed.
54 Arrange for a directory separator if necessary between DIR and BASE
55 in the result, removing any redundant separators.
56 In any case, if BASE_IN_RESULT is non-NULL, set
57 *BASE_IN_RESULT to point to the copy of ABASE in the returned
58 concatenation. However, if ABASE begins with more than one slash,
59 set *BASE_IN_RESULT to point to the sole corresponding slash that
60 is copied into the result buffer.
61
62 Report an error if memory is exhausted. */
63
64 char *
65 file_name_concat (char const *dir, char const *abase, char **base_in_result)
66 {
67 char const *dirbase = base_name (dir);
68 size_t dirbaselen = base_len (dirbase);
69 size_t dirlen = dirbase - dir + dirbaselen;
70 size_t needs_separator = (dirbaselen && ! ISSLASH (dirbase[dirbaselen - 1]));
71
72 char const *base = longest_relative_suffix (abase);
73 size_t baselen = strlen (base);
74
75 char *p_concat = xmalloc (dirlen + needs_separator + baselen + 1);
76 char *p;
77
78 p = mempcpy (p_concat, dir, dirlen);
79 *p = DIRECTORY_SEPARATOR;
80 p += needs_separator;
81
82 if (base_in_result)
83 *base_in_result = p - IS_ABSOLUTE_FILE_NAME (abase);
84
85 p = mempcpy (p, base, baselen);
86 *p = '\0';
87
88 return p_concat;
89 }
90
91 #ifdef TEST_FILE_NAME_CONCAT
92 # include <stdlib.h>
93 # include <stdio.h>
94 int
95 main ()
96 {
97 static char const *const tests[][3] =
98 {
99 {"a", "b", "a/b"},
100 {"a/", "b", "a/b"},
101 {"a/", "/b", "a/b"},
102 {"a", "/b", "a/b"},
103
104 {"/", "b", "/b"},
105 {"/", "/b", "/b"},
106 {"/", "/", "/"},
107 {"a", "/", "a/"}, /* this might deserve a diagnostic */
108 {"/a", "/", "/a/"}, /* this might deserve a diagnostic */
109 {"a", "//b", "a/b"},
110 };
111 size_t i;
112 bool fail = false;
113 for (i = 0; i < sizeof tests / sizeof tests[0]; i++)
114 {
115 char *base_in_result;
116 char const *const *t = tests[i];
117 char *res = file_name_concat (t[0], t[1], &base_in_result);
118 if (strcmp (res, t[2]) != 0)
119 {
120 printf ("got %s, expected %s\n", res, t[2]);
121 fail = true;
122 }
123 }
124 exit (fail ? EXIT_FAILURE : EXIT_SUCCESS);
125 }
126 #endif