How to check if soft link exists or not
Asked Answered
C

3

5
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?

Crinkle answered 19/6, 2014 at 2:7 Comment(1)
If the symbolic link does not exist, all the mechanisms you tried would report an error. However, they would also report an error if the symbolic link existed but some part of the path it points at causes trouble (does not exist or you don't have permission or isn't a directory when it needs to be one).Gerge
F
12

Use lstat - get symbolic link status:

The lstat() function shall be equivalent to stat(), except when path refers to a symbolic link. In that case lstat() shall return information about the link, while stat() 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.
Fawn answered 19/6, 2014 at 2:8 Comment(2)
Thanks. but it is not working if i remove the destination fileCrinkle
@Jonathon the function symlink_exists in it's current implementation only answers whether path exists, and not whether path is a symbolic link or regular file. When using lstat, If path is a symlink, the buffer will hold data about it and not about the pointed data, as opposed to a mere stat. But you still need to check the file type (will appear in st_mode field in the struct stat buffer supplied). See the example in the man pageGriskin
E
4

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.

Exultation answered 19/6, 2014 at 5:15 Comment(2)
For reference on how to use readlink(): https://mcmap.net/q/1921948/-how-do-you-determine-the-path-of-the-file-that-a-symlink-points-to/694576Oppilate
memory leak: you never free() linknameQuasimodo
C
0

Short answer:

#include <sys/stat.h>
#include <string>

bool symlinkExists(const string &path)
{
    struct stat info;
    return lstat(path.c_str(), &info) == 0;
}
Calchas answered 23/3, 2021 at 18:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.