检查目录是否存在时,在 C 中S_ISDIR未解析的外部符号

Unresolved external symbol S_ISDIR in C upon checking if directory exist

提问人:KaramJaber 提问时间:3/30/2022 最后编辑:KaramJaber 更新时间:3/30/2022 访问量:528

问:

我在网上搜索了如何检查提供的路径是文件还是目录,并遇到了系统调用。stat

我尝试实现如下:

#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;
}

但是当我尝试在 Windows 上使用 Visual Studio 进行编译时,出现以下错误:

unresolved external symbol S_ISDIR referenced in function 

我阅读了 stat 的文档,它确实提供了这个宏,但出于某种原因,我的环境正在识别它......有什么建议吗?

另一种解决方案是实现S_ISDIR正在做的事情:

stat(pathname, &sb);
if ((sb.st_mode & S_IFMT) == S_IFDIR) {
      /* Handle directory */
}
c Windows 统计信息 未解析 - 外部

评论

2赞 Gerhardh 3/30/2022
我阅读了统计的文档。假设是这个。是否包含所需的标头?对于 777 rep,我假设您知道您应该包含一个完整的最小样本,包括所有标头、编译器命令等......
1赞 Gerhardh 3/30/2022
顺便说一句:你没有收到关于隐含声明的警告吗?我认为该符号根本不应该进入链接器。S_ISDIR
3赞 Jonathan Leffler 3/30/2022
这意味着标头不符合 POSIX(假设它已包含在内)。您可能需要提供宏。 / / .冲洗并重复其他类似宏。<sys/stat.h>#ifndef S_ISDIR#define S_ISDIR(s) ((s).st_mode & S_IFDIR)#endif
0赞 Jabberwocky 3/30/2022
顺便说一句:无论如何,你的代码都是错误的,因为你没有检查是否成功。如果由于某种原因失败,检查是没有意义的,因为它的内容将不确定。statstatstats.st_mode
0赞 Andrew Henle 3/30/2022
@JonathanLeffler什么?Windows 不符合可移植操作系统接口标准?!?!!说不是这样!

答:

2赞 Jonathan Leffler 3/30/2022 #1

我遇到了 Microsoft 没有提供符合 POSIX 标准的 版本的问题。我有自己的标题,用于处理该问题(最早的日期为 1995 年,最后修改时间为 2013 年):<sys/stat.h>sysstat.h

#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 */

标头包含:posixver.h

#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 */

明确地说:你可以随心所欲地使用这段代码,我不需要署名。