'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 |
