Wednesday, February 6, 2008

C Program For Linux Or Unix To Unravel Symlinks

Good morning/afternoon/evening :)

Today, I put together a quick C program (Tested to compile with gcc on Linux and Unix - Note that your "include" files might need to be slightly modified depending on where they are and what flavor of Unix or Linux you're using) to make it easier to solve a common issue.

Depending upon how things are setup where you work and/or play, this c program may be immensely helpful for you. The opposite, of course, may be true ;)

This program makes use of the c "realpath" function, which (put simply) will give you the "actual" absolute path or location of any file or directory name that you feed it. This is only highly useful, again, if you work somewhere were people go nuts using symlinks all over the place on your hosts' filesystems; leaving you with tons of relative path file locations.

You can compile this code simply with gcc, by just putting the contents into a file (I'll call it realpath.c) and running a simple compile command, like so:

host # gcc -o realpath realpath.c

this will output a binary called "realpath" that you can use like this (We'll show, below, the two ways feeding this program an existing file can turn out):

host # ./realpath /usr/local/bin/program
/usr/local/bin/program is the real pathname.

host # ./realpath /usr/local/bin/otherprogram
/usr/local/bin/program is a linked pathname for /apps/local/ops/sbin/otherprogram


using this simple program can save you considerable heartburn under the right circumstances. Here's to your not having to find yourself in the "right circumstances" too often ;)

Best Wishes,


Creative Commons License


This work is licensed under a
Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License

# include <errno.h>
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <sys/param.h>
# include <sys/stat.h>
# include <sys/types.h>

/* realpath - weed out those symlinks

2008 - Mike Golvach - eggi@comcast.net

Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License
*/

main(int argc, char **argv)
{

char *real;
const char bone[1024];
int diff, bob;
struct stat ruthere;

if ( argc != 2 ) {
printf("Usage: %s [pathname in question]\n", argv[0]);
exit(1);
}

if ((realpath(argv[1], real)) < 0) {
printf("%s : File Not Found\n", argv[1]);
exit(1);
}

if ((stat(argv[1], &ruthere)) < 0 ) {
bob = errno;
if ( bob == 2 ) {
printf("%s : File Not Found\n", argv[1]);
exit(1);
} else if ( bob == 13 || bob == 20 ) {
printf("\n");
printf("You can't access this file!\n");
printf("Results may be incorrect...\n");
}
}

if ((diff = strcmp(argv[1], real)) == 0) {
printf("\n");
printf("%s is the real pathname.\n", argv[1]);
} else {
printf("\n");
printf("%s is a linked pathname for %s\n", argv[1], real);
}

}


, Mike