user: ls -lt
lrwxrwxrwx 1 user sw-team 9 Jun 18 19:01 new_link -> test/file
I have a soft link like mentioned above. I want to check whether new_link(not the linked file) exists or not. I tried all the below but all are checking only if the final destination file (test/file) exists or not.
access(filename,F_OK)
stat()
open()
fopen()
I want to find it in C language not in shell script.Please tell me how to find if new_link exists before checking the linked file?
Use lstat
- get symbolic link status:
The
lstat()
function shall be equivalent tostat()
, except when path refers to a symbolic link. In that caselstat()
shall return information about the link, whilestat()
shall return information about the file the link references.
(Emphasis mine.)
lstat
will return non-zero, and errno
will be set to ENOENT
if the link (or any other part of the path) does not exist.
Example:
#include <stdio.h>
#include <stdbool.h>
#include <sys/stat.h>
bool symlink_exists(const char* path)
{
struct stat buf;
int result;
result = lstat(path, &buf);
return (result == 0);
}
void test(const char* path)
{
bool exists = symlink_exists(path);
printf("%s does%s exist.\n", path, exists ? "" : " not");
}
int main(int argc, char** argv)
{
test("/bin/sh");
test("/etc/no_such_thing");
return 0;
}
Output:
/bin/sh does exist.
/etc/no_such_thing does not exist.
You need lstat
to get link status and readlink
to read the value of symlink.
I have modified Jonthon's code. Check this:
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <sys/stat.h>
bool symlink_exists(const char* path)
{
struct stat buf;
int ret = 0;
char *linkname;
if (lstat(path, &buf) == 0) {
// TODO: Add error handling
linkname = malloc(buf.st_size + 1);
readlink(path, linkname, buf.st_size + 1);
linkname[buf.st_size] = '\0';
printf("---> '%s' points to '%s'\n", path, linkname);
if (stat(linkname, &buf) == 0)
ret = 1;
}
return ret;
}
void test(const char* path)
{
bool exists = symlink_exists(path);
printf("%s does%s exist.\n", path, exists ? "" : " *not*");
}
int main(int argc, char** argv)
{
test("/bin/sh"); //Normal link using relative path - NOT WORKING
test("/etc/no_such_thing"); //Broken file
test("tmpp"); //Normal link using absolute path - WORKING
test("tmppp"); //Broken link
return 0;
}
Use absolute path to create your links. Otherwise you have to convert it to relative paths.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With