Reputation: 6399
I'm looking for an example of how to use the realpath function in a C program. I can't seem to find one on the web or in any of my C programming books.
Upvotes: 21
Views: 71592
Reputation: 755094
What the realpath()
function does is tell you the absolute pathname of a file when all symbolic links have been resolved.
You may have a 'realpath' program already on your machine. Here's the (non-standard) version I wrote.
/*
@(#)File: $RCSfile: realpath.c,v $
@(#)Version: $Revision: 1.3 $
@(#)Last changed: $Date: 2007/10/23 20:23:44 $
@(#)Purpose: Command to evaluate realpath(3) on given arguments.
@(#)Author: J Leffler
@(#)Copyright: (C) JLSS 2007
@(#)Product: :PRODUCT:
*/
/*TABSTOP=4*/
#if __STDC_VERSION__ >= 199901L
#define _XOPEN_SOURCE 600
#else
#define _XOPEN_SOURCE 500
#endif /* __STDC_VERSION__ */
#include <unistd.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include "stderr.h"
static const char optstr[] = "hlsV";
static const char usestr[] = "[-hslV] given-path [...]";
static const char hlpstr[] =
" -h Print this help message\n"
" -l Long format: print given-path and real-path\n"
" -s Short format: print just real-path\n"
" -V Print version and exit\n"
;
enum { FMT_LONG, FMT_SHORT };
static int format_type = FMT_LONG;
#ifndef lint
/* Prevent over-aggressive optimizers from eliminating ID string */
extern const char jlss_id_realpath_c[];
const char jlss_id_realpath_c[] = "@(#)$Id: realpath.c,v 1.3 2007/10/23 20:23:44 jleffler Exp $";
#endif /* lint */
static int eval_realpath(const char *given)
{
char realname[_POSIX_PATH_MAX];
int rc = 0;
if (realpath(given, realname) == 0)
{
rc = -1;
err_sysrem("failed to resolve real path name for %s\n", given);
}
else if (format_type == FMT_SHORT)
printf("%s\n", realname);
else
printf("%s %s\n", given, realname);
return(rc);
}
int main(int argc, char **argv)
{
int i;
int rc = EXIT_SUCCESS;
int opt;
err_setarg0(argv[0]);
while ((opt = getopt(argc, argv, optstr)) != -1)
{
switch (opt)
{
case 'V':
err_version("REALPATH", &"@(#)$Revision: 1.3 $ ($Date: 2007/10/23 20:23:44 $)"[4]);
break;
case 'h':
err_help(usestr, hlpstr);
break;
case 'l':
format_type = FMT_LONG;
break;
case 's':
format_type = FMT_SHORT;
break;
default:
err_usage(usestr);
break;
}
}
for (i = optind; i < argc; i++)
{
if (eval_realpath(argv[i]) != 0)
rc = EXIT_FAILURE;
}
return(rc);
}
I needed it to test some software that was evaluating the security of a path, and needed to be sure my code was evaluating the given path to the same resolved location as realpath()
does. It would probably be sensible to extend it with a '-a' option to ensure names are mapped to absolute names (by prefixing the result of getcwd()
to relative pathnames).
(The extra source code is available in my SOQ (Stack Overflow Questions) repository on GitHub as files stderr.c
, stderr.h
and errhelp.c
in the src/libsoq sub-directory.)
Upvotes: 4
Reputation: 108986
Note
realpath()
function is not described in the C Standard
Sample Code
#include <limits.h> /* PATH_MAX */
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char buf[PATH_MAX]; /* PATH_MAX incudes the \0 so +1 is not required */
char *res = realpath("this_source.c", buf);
if (res) { // or: if (res != NULL)
printf("This source is at %s.\n", buf);
} else {
char* errStr = strerror(errno);
printf("error string: %s\n", errStr);
perror("realpath");
exit(EXIT_FAILURE);
}
return 0;
}
Upvotes: 32
Reputation: 54701
Minimalist but it does the job!
Build
gcc -o realpath -x c - <<< $'#include<stdlib.h>\n#include<stdio.h>\nint main(int c,char**v){puts(realpath(v[1],0));}'
Test
$> ./realpath ~/../../../usr/./bin/./awk
/bin/gawk
$> readlink -f ~/../../../usr/./bin/./awk
/bin/gawk
Requirements
Crash
My minimalist one-line command line builds an executable realpath
that produces a Segmentation fault
when the path does not exist. Instead of writing if
/else
blocs to handle that issue within my answer, I have added below some links to let you have a look on the Busybox implementation of realpath
and readlink
.
For a more complete source code, have a look on this simple implementation.
Official Git repository
GitHub mirror repository
Upvotes: 5