1//========================================================================
2//
3// gbasename.cc
4//
5// Wrapper for libgen's basename() call which returns a std::string.
6// This is a convenience method working around questionable behavior
7// in the copy of basename() provided by libgen.h.
8//
9// According to man 3 basename:
10//
11// Both dirname() and basename() may modify the contents of path, so it
12// may be desirable to pass a copy when calling one of these functions.
13//
14// ...
15//
16// These functions may return pointers to statically allocated memory
17// which may be overwritten by subsequent calls. Alternatively, they
18// may return a pointer to some part of path, so that the string
19// referred to by path should not be modified or freed until the pointer
20// returned by the function is no longer required.
21//
22// Because basename can modify filename (for some reason), we have to
23// duplicate our input into a mutable buffer before we can call it.
24// The return value might be part of this mutable temporary, but not
25// generally the front, so 'char *' cannot be used as our return value.
26// The return value might also be a statically allocated string,
27// rendering basename (and thus gbasename) non-thread-safe. Because
28// we don't know how basename()'s return value is lifecycled, we need
29// to duplicate it again into something whose lifecycle we can predict.
30//
31// This is how a method that should amount to finding the last slash
32// in a string ends up requiring two memory allocations while managing
33// not to be thread-safe. In a way, it's kind of impressive.
34//
35// This file is licensed under the GPLv2 or later
36//
37// Copyright (C) 2018, 2019 Greg Knight <lyngvi@gmail.com>
38// Copyright (C) 2019 Albert Astals Cid <aacid@kde.org>
39//
40//========================================================================
41
42#include "gbasename.h"
43#ifndef _MSC_VER
44# include <libgen.h>
45#endif
46#include <cstdlib>
47#include <cstring>
48
49std::string gbasename(const char *filename)
50{
51#ifdef _MSC_VER
52 char fname[_MAX_FNAME] = {}, fext[_MAX_EXT] = {};
53 errno_t z = _splitpath_s(filename, NULL, 0, NULL, 0, fname, _countof(fname), fext, _countof(fext));
54 return std::string(fname) + std::string(fext);
55#else
56 char *mutabl = strdup(s: filename);
57 std::string retu = basename(path: mutabl);
58 free(ptr: mutabl);
59 return retu;
60#endif
61}
62

source code of poppler/goo/gbasename.cc