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?

alk
  • 66,653
  • 10
  • 83
  • 219
user1762571
  • 1,629
  • 4
  • 23
  • 41
  • 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). – Jonathan Leffler Jun 19 '14 at 03:34

3 Answers3

10

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.
Jonathon Reinhart
  • 116,671
  • 27
  • 221
  • 298
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.

Sanket Parmar
  • 1,129
  • 10
  • 9
0

Short answer:

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

bool symlinkExists(const string &path)
{
    struct stat info;
    return lstat(path.c_str(), &info) == 0;
}
Adriel Jr
  • 1,357
  • 12
  • 20