openat: don’t close (-1)
[gnulib.git] / lib / basename.c
blobc5a6bdc9d5d1274664f0a90d8043b063a7d216d8
1 /* basename.c -- return the last element in a file name
3 Copyright (C) 1990, 1998-2001, 2003-2006, 2009-2024 Free Software
4 Foundation, Inc.
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 3 of the License, or
9 (at your option) any later version.
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.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <https://www.gnu.org/licenses/>. */
19 #include <config.h>
21 #include "dirname.h"
23 #include <string.h>
24 #include "xalloc.h"
26 char *
27 base_name (char const *name)
29 char const *base = last_component (name);
30 idx_t length;
31 int dotslash_len;
32 if (*base)
34 length = base_len (base);
36 /* Collapse a sequence of trailing slashes into one. */
37 length += ISSLASH (base[length]);
39 /* On systems with drive letters, "a/b:c" must return "./b:c" rather
40 than "b:c" to avoid confusion with a drive letter. On systems
41 with pure POSIX semantics, this is not an issue. */
42 dotslash_len = FILE_SYSTEM_PREFIX_LEN (base) != 0 ? 2 : 0;
44 else
46 /* There is no last component, so NAME is a file system root or
47 the empty string. */
48 base = name;
49 length = base_len (base);
50 dotslash_len = 0;
53 char *p = ximalloc (dotslash_len + length + 1);
54 if (dotslash_len)
56 p[0] = '.';
57 p[1] = '/';
60 /* Finally, copy the basename. */
61 memcpy (p + dotslash_len, base, length);
62 p[dotslash_len + length] = '\0';
63 return p;