Pathfns is a small C library which supports some common operations on path names. In general they reimplement more-or-less well known existing functions, with the variation that none of them depend on fixed-size or static buffers.
It is a logical companion to Stringfns.
Programs that use any of the Pathfns functions should use
#include <pathfns.h>
in source files and -lpathfns when linking.
The following functions are implemented:
char *agetcwd(void); |
Determine current working directory (if there is one) |
char *adirname(const char *path); |
Determine the directory name part of PATH. |
char *abasename(const char *path); |
Determine the base name part of PATH. |
int pathsplit(const char *path, char **basenamep, char **dirnamep); |
Both of adirname() and abasename(), wrapped up in a single call. Returns 0 on success. Either or both of the return pointers may be a null pointer. |
char *arealpath(const char *path); |
Determine the canonical form of PATH. |
char *areadlink(const char *path); |
Read the target of symbolic link PATH. |
In all cases, returned strings are allocated with malloc and include a null terminator. On error, all the functions return a null pointer (except pathsplit which returns -1) and set errno.
Follow the links above to the man pages, or consult the versions included in the distribution, for full details.
I've tested this package under Debian GNU/Linux "woody" and FreeBSD 4.4. It is intended to work on a wide range of UNIX-like platforms.
The latest version is pathfns-0.1.5.tar.gz. If you have any earlier version, please upgrade now.
You can also look at the CVS repository at http://www.chiark.greenend.org.uk/ucgi/~richardk/cvsweb/pathfns/.
All the functions in Pathfns implement the same operation as a function existing in at least some implementations of libc. So why are new versions required? In each case the pre-existing version has some flaw which makes it unsuitable for use in many contexts.
getcwd(3) is a POSIX function, but requires the caller to guess in advance how much space will be required for the answer. Some versions provide a workaround for this, but not all, so you have to do something beyond just using getcwd.
readlink(2) is another standard function, but it has an even more inconvenient interface: not only does the caller have to guess how big a buffer to supply, but it doesn't add a null terminator either.
dirname(3) and basename(3) are defined in SUSv2. They have two flaws: they might modify the argument string (which is inconvenient), and they might use static data to store the result (which is broken in threaded programs, and inconvenient if you want to have several directory or base names around at once).
Finally realpath(3), also from SUSv2, instead of requiring the caller to guess how big a buffer to allocate insists that it be PATH_MAX. But PATH_MAX might not even be defined, so it is impossible to rely on this function in a portable program. The Linux man page for realpath(3) suggests calling pathconf(path, _PC_PATH_MAX) to determine the size of buffer to allocate, if PATH_MAX is undefined. This is inconvenient and doesn't work anyway.
(If you don't care about some of these issues, or find the memory management associated with the Pathfns functions more onerous than the hoops that you might have to jump through to use the standard versions, then perhaps Pathfns is not for you.)
Pathfns is Copyright © 2002, 2006 Richard Kettlewell
This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA