'Unresolved external symbol S_ISDIR in C upon checking if directory exist

I searched the web on how to check if path provided is a file or a directory and came across the stat system call.

I tried to implement as following :

#include <sys/types.h>
#include <sys/stat.h>
int isDirectoryExists(const char *path)
{
    struct stat stats;

    stat(path, &stats);

    // Check for file existence
    if (S_ISDIR(stats.st_mode))
        return 1;

    return 0;
}

but when i try to compile with visual studio on windows i get the following error:

unresolved external symbol S_ISDIR referenced in function 

I read the documentation of stat and it does provide this macro but for some reason my environment is recognizing it...any suggestions?

Alternative solution would be implementing what S_ISDIR is doing:

stat(pathname, &sb);
if ((sb.st_mode & S_IFMT) == S_IFDIR) {
      /* Handle directory */
}


Solution 1:[1]

I've run into problems with Microsoft not providing a POSIX-compliant version of <sys/stat.h>. I have my own header, sysstat.h, that deals with the problem (earliest date 1995, last modified 2013):

#ifndef SYSSTAT_H
#define SYSSTAT_H

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */

#include "posixver.h"           /* Not always quick enough */
#include <sys/types.h>
#include <sys/stat.h>

#ifdef _MSC_VER                 /* MS <sys/stat.h> uses this trigger */
typedef unsigned short mode_t;  /* POSIX defines mode_t in <sys/types.h> */
#endif /* _MSCVER */

#ifndef S_IRWXU

/* POSIX-compliant defines omitted from sys/stat.h. */
/* Assume UNIX Version 7 header, more or less       */

#ifndef S_IREAD
#define S_IREAD     0400
#endif /* S_IREAD */
#ifndef S_IWRITE
#define S_IWRITE    0200
#endif /* S_IWRITE */
#ifndef S_IEXEC
#define S_IEXEC     0100
#endif /* S_IEXEC */

#define S_IRUSR (S_IREAD)
#define S_IWUSR (S_IWRITE)
#define S_IXUSR (S_IEXEC)
#define S_IRGRP (S_IRUSR >> 3)
#define S_IWGRP (S_IWUSR >> 3)
#define S_IXGRP (S_IXUSR >> 3)
#define S_IROTH (S_IRUSR >> 6)
#define S_IWOTH (S_IWUSR >> 6)
#define S_IXOTH (S_IXUSR >> 6)
#define S_IRWXU (S_IRUSR|S_IWUSR|S_IXUSR)
#define S_IRWXG (S_IRGRP|S_IWGRP|S_IXGRP)
#define S_IRWXO (S_IROTH|S_IWOTH|S_IXOTH)

#ifdef _MSC_VER                 /* MS <sys/stat.h> uses this trigger */
/* MS Windows does not support SUID, SGID or sticky bit */
#ifndef S_ISUID
#define S_ISUID 0
#endif
#ifndef S_ISGID
#define S_ISGID 0
#endif
#ifndef S_ISVTX
#define S_ISVTX 0
#endif
#else
#ifndef S_ISUID
#define S_ISUID 04000
#endif
#ifndef S_ISGID
#define S_ISGID 02000
#endif
#ifndef S_ISVTX
#define S_ISVTX 01000
#endif
#endif /* _MSCVER */

#endif /* S_IRWXU */

/*
** Assume the S_IFMT, S_IFDIR, S_IFCHR, S_IFREG are defined, which is OK
** for Windows under MS Visual Studio 2008 Express.  Conditional testing
** not perfect: it assumes pragmatically that S_ISFIFO() is undefined if
** S_IFIFO() is undefined, for example.
*/

/* POSIX file type test macros */
#ifndef S_ISDIR
#define S_ISDIR(m)  (((m) & S_IFMT) == S_IFDIR)
#endif /* S_ISDIR */
#ifndef S_ISCHR
#define S_ISCHR(m)  (((m) & S_IFMT) == S_IFCHR)
#endif /* S_ISCHR */
#ifndef S_ISREG
#define S_ISREG(m)  (((m) & S_IFMT) == S_IFREG)
#endif /* S_ISREG */

/* Not in MS Visual Studio 2008 Express */
#ifdef S_IFBLK
#ifndef S_ISBLK
#define S_ISBLK(m)  (((m) & S_IFMT) == S_IFBLK)
#endif /* S_ISBLK */
#else
#define S_ISBLK(m)  (0)
#endif /* S_IFBLK */

/* Not in Version 7 Unix, but we'll define it anyway */
#ifdef S_IFIFO
#ifndef S_ISFIFO
#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
#endif /* S_ISFIFO */
#else
#define S_ISFIFO(m) (0)
#endif /* S_IFIFO */

/* Not in POSIX 1003.1-1990, but we'll define it anyway */
#ifdef S_IFLNK
#ifndef S_ISLNK
#define S_ISLNK(m)  (((m) & S_IFMT) == S_IFLNK)
#endif /* S_ISLNK */
#else
#define S_ISLNK(m)  (0)
#endif /* S_IFLNK */

/* Not in POSIX 1003.1-1990, but we'll define it anyway */
#ifdef S_IFSOCK
#ifndef S_ISSOCK
#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
#endif /* S_ISSOCK */
#else
#define S_ISSOCK(m) (0)
#endif /* S_IFSOCK */

#endif  /* SYSSTAT_H */

The posixver.h header contains:

#ifndef JLSS_ID_POSIXVER_H
#define JLSS_ID_POSIXVER_H

/*
** Include this file before including system headers.  By default, with
** C99 support from the compiler, it requests POSIX 2008 support.  With
** C89 support only, it requests POSIX 1997 support.  Override the
** default behaviour by setting either _XOPEN_SOURCE or _POSIX_C_SOURCE.
*/

/* _XOPEN_SOURCE 700 is loosely equivalent to _POSIX_C_SOURCE 200809L */
/* _XOPEN_SOURCE 600 is loosely equivalent to _POSIX_C_SOURCE 200112L */
/* _XOPEN_SOURCE 500 is loosely equivalent to _POSIX_C_SOURCE 199506L */

#if !defined(_XOPEN_SOURCE) && !defined(_POSIX_C_SOURCE)
#if defined(__cplusplus)
#define _XOPEN_SOURCE 700   /* SUS v4, POSIX 1003.1 2008/13 (POSIX 2008/13) */
#elif __STDC_VERSION__ >= 199901L
#define _XOPEN_SOURCE 700   /* SUS v4, POSIX 1003.1 2008/13 (POSIX 2008/13) */
#else
#define _XOPEN_SOURCE 500   /* SUS v2, POSIX 1003.1 1997 */
#endif /* __STDC_VERSION__ */
#endif /* !_XOPEN_SOURCE && !_POSIX_C_SOURCE */

#endif /* JLSS_ID_POSIXVER_H */

Just to be explicit: you may use this code however you like, and I do not require attribution.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Jonathan Leffler