S_IFMT和S_IFREG未定义,-std = c11或-std = gnu11

时间:2015-02-16 17:43:41

标签: c gcc posix stat c11

这是我第一次使用posix;我包括:

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

我是这个片段。

stat(pathname, &sb);
if ((sb.st_mode & S_IFMT) == S_IFREG) {
    /* Handle regular file */
}

但如果我使用-std = c99或-std = c11或-std = gnu99或-std = gnu11编译,则在Gentoo上使用GCC 4.8.3我收到此错误:

error: ‘S_ISFMT’ undeclared (first use in this function)

如果我省略-std = *我没有错误。但我也希望-std = c99的所有功能(如关键字restrict或for(int i ;;)等...) 我怎么能编译我的代码?

3 个答案:

答案 0 :(得分:5)

现代POSIX兼容系统需要提供S_IFMTS_IFREG值。唯一不需要这个版本的POSIX(事实上,禁止它)是POSIX.1-1990,它似乎是你机器上的标准。

在任何情况下,每个符合POSIX标准的系统都提供macros,允许您检查文件的类型。这些宏等同于掩蔽方法。

因此,在您的情况下,而不是(sb.st_mode & S_IFMT) == S_IFREG,只需撰写S_ISREG(sb.st_mode)

答案 1 :(得分:3)

在源代码中的任意#define _BSD_SOURCE之前放置#define _XOPEN_SOURCE#include 。要了解其工作原理,请查看#define S_IFMT __S_IFMT中的sys/stat.h,然后在feature_test_macros(7)手册页中。

答案 2 :(得分:2)

K&R2提供:

#define S_IFMT 0160000 /* type of file: */
#define S_IFDIR 0040000 /* directory */

在8.6示例列表目录中。

我不鼓励使用此解决方案,此外,我希望一些专家可以教给我们该解决方案是否正确,利弊,替代方案等等。提前谢谢!

MWE示例。

MWE:

/* these defines at beginning to highlight them */
#define S_IFMT 0160000 /* type of file: */
#define S_IFDIR 0040000 /* directory */

/*
   Modify the fsize program to print the other information contained in the inode entry.
   */

#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <dirent.h>
#include <pwd.h>


#define MAX_PATH 1024

#ifndef DIRSIZ
#define DIRSIZ 14
#endif


void dirwalk( char *dir,void (*fcn)(char *)){

    char name[MAX_PATH];
    struct dirent *dp;
    DIR *dfd;

    if((dfd = opendir(dir))==NULL){
        puts("Error: Cannot open Directory");
        return;
    }
    puts(dir);
    // Get each dir entry
    while((dp=readdir(dfd)) != NULL){
        // Skip . and .. is redundant.
        if(strcmp(dp->d_name,".") == 0
            || strcmp(dp->d_name,"..") ==0 )
            continue;
        if(strlen(dir)+strlen(dp->d_name)+2 > sizeof(name))
            puts("Error: Name too long!");
        else{
            sprintf(name,"%s/%s",dir,dp->d_name);
            // Call fsize
            (*fcn)(name);
        }
    }
    closedir(dfd);
}

void fsize(char *name){
    struct stat stbuf;

    if(stat(name,&stbuf) == -1){
        puts("Error: Cannot get file stats!");
        return;
    }

    if((stbuf.st_mode & S_IFMT) == S_IFDIR){
        dirwalk(name,fsize);
    }
    struct passwd *pwd = getpwuid(stbuf.st_uid);
    //print file name,size and owner
    printf("%81d %s Owner: %s\n",(int)stbuf.st_size,name,pwd->pw_name);
}

int main(int argc,char *argv[]){

    if(argc==1)
        fsize(".");
    else 
        while(--argc>0)
            fsize(*++argv);
    return 0;
}