Skip to content

Instantly share code, notes, and snippets.

@cls cls/lsln.c
Last active Nov 25, 2018

Embed
What would you like to do?
Resolve a symlink step by step, printing each link in the chain
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
static char *getlink(const char *);
static void panic(const char *);
int
main(int argc, char **argv)
{
if (getopt(argc, argv, "") != -1 || optind + 1 != argc) {
fputs("usage: lsln [file]\n", stderr);
exit(2);
}
const char *name = argv[optind];
for (char *link, *path = getlink(name); path; link = getlink(path), free(path), path = link) {
puts(path);
}
}
char *
getlink(const char *path)
{
struct stat st;
if (lstat(path, &st) == -1)
panic(path);
if (!S_ISLNK(st.st_mode))
return NULL;
size_t size = st.st_size + 1;
const char *ptr = strrchr(path, '/');
size_t off = ptr ? ptr + 1 - path : 0;
char *buf = malloc(size + off);
if (!buf)
panic(path);
ssize_t len = readlink(path, buf, size);
if (len == -1)
panic(path);
if (len == size)
return NULL;
buf[len++] = '\0';
if (buf[0] != '/' && off != 0) {
memmove(buf + off, buf, len);
memcpy(buf, path, off);
}
return buf;
}
void
panic(const char *mesg)
{
perror(mesg);
exit(1);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.