/* $Id: symlink.c,v 1.7 2026/02/08 01:42:12 kostik Exp kostik $ */ #include #include #include #include #include static void onelink(const char *name) { struct stat st; long plen; ssize_t llen; int fd; fd = open(name, O_PATH | O_NOFOLLOW); if (fd == -1) { warn("open \"%s\"", name); return; } if (fstatat(fd, "", &st, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW) == -1) { warn("fstatat \"%s\"", name); goto ret; } if (!S_ISLNK(st.st_mode)) { warnx("%s: not a symlink", name); goto ret; } #if defined __FreeBSD__ plen = fpathconf(fd, _PC_SYMLINK_MAX); if (plen == -1) { warn("fpathconf \"%s\"", name); goto ret; } #elif defined __linux__ /* On Linux, fpathconf() does not work on O_PATH-fd. */ plen = 2048; #endif { char path[plen + 1]; llen = readlinkat(fd, "", path, plen); if (llen == -1) { warn("readlinkat \"%s\"", name); goto ret; } path[llen] = '\0'; printf("%s => %s\n", name, path); } ret: close(fd); } int main(int argc, char *argv[]) { for (int i = 1; i < argc; i++) onelink(argv[i]); }