如何使用S_ISREG()和S_ISDIR()POSIX宏? [英] How to use S_ISREG() and S_ISDIR() POSIX Macros?

查看:194
本文介绍了如何使用S_ISREG()和S_ISDIR()POSIX宏?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我写的递归导航和输出目录和普通文件的C程序。它编译和运行我的Linux机器上的罚款。但在Solaris中, dit-> d_type == 8 检查和其他类似的不工作,因为没有 d_type 字段。我读过这个问题的答案是使用 S_ISREG() S_ISDIR()宏,但他们在所有我有他们在我的code目前的方式不起作用。我评论,我的Linux机器上运行的线路。

 的#include< SYS / types.h中>
#包括LT&; SYS / stat.h>
#包括LT&;&stdlib.h中GT;
#包括LT&;&dirent.h GT;
#包括LT&;&stdio.h中GT;
#包括LT&;&unistd.h中GT;
#包括LT&;&errno.h中GT;
#包括LT&;&string.h中GT;无效帮手(DIR *,结构的dirent *,结构统计,字符*,INT,CHAR **);
无效dircheck(DIR *,结构的dirent *,结构统计,字符*,INT,CHAR **);INT主(INT ARGC,CHAR *的argv []){  DIR *浸;
  结构的dirent * DIT;
  结构统计statbuf;
  焦炭currentPath [FILENAME_MAX]
  INT深度= 0; / *用于正确输出空间* /  / *打开当前目录* /
  如果((DIP =执行opendir(。))== NULL)
    返回错误号;  / *在currentPath商店当前工作目录* /
  如果((GETCWD(currentPath,FILENAME_MAX))== NULL)
    返回错误号;  / *读取目录中的所有项目* /
  而((DIT = READDIR(DIP))!= NULL){
    / *跳过。和.. * /
    如果(STRCMP(dit->中d_name,)== 0 || STRCMP(dit-> d_name,..)== 0)
      继续;    如果(STAT(currentPath,&安培; statbuf)== -1){
      PERROR(STAT);
      返回错误号;
    }    / *检查,如果目前的产品类型文件(8型),并没有命令行参数
      如果(dit-> d_type == 8安培;&放大器;的argv [1] == NULL)* /
    如果(S_ISREG(statbuf.st_mode)及和放大器;的argv [1] == NULL)
      的printf(%S(%d字节)\\ n,dit-> d_name,(INT)statbuf.st_size);      / *如果一个命令行参数,给出了文件名匹配检查
    如果(dit-> d_type == 8和;&放大器;!的argv [1] = NULL)* /
    如果(S_ISREG(statbuf.st_mode)及&放大器;!的argv [1] = NULL)
      如果(STRCMP(dit-> d_name,ARGV [1])== 0)
        的printf(%S(%d字节)\\ n,dit-> d_name,(INT)statbuf.st_size);      / *检查,如果目前的产品类型目录(类型4)
      如果(dit-> d_type == 4)* /
    如果(S_ISDIR(statbuf.st_mode))
      dircheck(DIP,DIT,statbuf,currentPath,深度的argv);  }
  closedir(DIP);
  返回0;
}/ *递归调用辅助函数* /
无效帮手(DIR *浸,结构的dirent * DIT,结构统计statbuf,
    焦炭currentPath [FILENAME_MAX],INT深度的char * ARGV []){
  INT I = 0;  如果((DIP =执行opendir(currentPath))== NULL)
    的printf(错误:无法打开目录==>%S \\ n,currentPath);  而((DIT = READDIR(DIP))!= NULL){    如果(STRCMP(dit->中d_name,)== 0 || STRCMP(dit-> d_name,..)== 0)
      继续;    STAT(currentPath,&安培; statbuf);    / *如果(dit-> d_type == 8安培;&放大器;的argv [1] == NULL){* /
    如果(S_ISREG(statbuf.st_mode)及和放大器;的argv [1] == NULL){
      对于(i = 0; I<深度;我++)
        的printf();
      的printf(%S(%d字节)\\ n,dit-> d_name,(INT)statbuf.st_size);
    }    / *如果(dit-> d_type == 8安培;&安培;!ARGV [1] = NULL){* /
    如果(S_ISREG(statbuf.st_mode)及&放大器;!的argv [1] = NULL){
      如果(STRCMP(dit-> d_name,ARGV [1])== 0){
    对于(i = 0; I<深度;我++)
      的printf();
    的printf(%S(%d字节)\\ n,dit-> d_name,(INT)statbuf.st_size);
      }
    }    / *如果(dit-> d_type == 4)* /
    如果(S_ISDIR(statbuf.st_mode))
      dircheck(DIP,DIT,statbuf,currentPath,深度的argv);  }
}无效dircheck(DIR *浸,结构的dirent * DIT,结构统计statbuf,
      焦炭currentPath [FILENAME_MAX],INT深度的char * ARGV []){
  INT I = 0;  的strcat(currentPath,/);
  strcat的(currentPath,dit-> d_name);  / *如果在同一水平的路径有两个目录:
    建错误的,需要被校正* /
  如果((CHDIR(currentPath))== -1){
    CHDIR();
    GETCWD(currentPath,FILENAME_MAX);
    的strcat(currentPath,/);
    strcat的(currentPath,dit-> d_name);    对于(i = 0; I<深度;我++)
      的printf();
    的printf(%S(子目录)\\ n,dit-> d_name);
    深入++;
    助手(DIP,DIT,statbuf,currentPath,深度的argv);
  }  其他{
    对于(i = 0; I<深度;我++)
      的printf();
    的printf(%S(子目录)\\ n,dit-> d_name);
    CHDIR(currentPath);
    深入++;
    助手(DIP,DIT,statbuf,currentPath,深度的argv);
  }}


解决方案

您正在使用 S_ISREG() S_ISDIR()正确,你只是用他们在错误的事情。

在你的,而((DIT = READDIR(DIP))!= NULL)的 环主,你再打电话与stat currentPath 一遍又一遍不改变 currentPath

 如果(STAT(currentPath,&安培; statbuf)== -1){
    PERROR(STAT);
    返回错误号;
}

你不是应该附加一个斜线和 dit-> d_name currentPath 来获得完整路径为要统计的文件?依我看到其他统计还需要调用。

这类似的变化

This is a C program I wrote to recursively navigate and output directories and regular files. It compiles and runs fine on my Linux machine. But on Solaris, the dit->d_type == 8 check and the other similar ones don't work because there is no d_type field. An answer I've read to this problem is to use the S_ISREG() and S_ISDIR() macros, but they don't work at all the way I have them in my code currently. I commented out the lines that work on my Linux machine.

#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <dirent.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>

void helper(DIR *, struct dirent *, struct stat, char *, int, char **);
void dircheck(DIR *, struct dirent *, struct stat, char *, int, char **);

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

  DIR *dip;
  struct dirent *dit;
  struct stat statbuf;
  char currentPath[FILENAME_MAX];
  int depth = 0; /*Used to correctly space output*/

  /*Open Current Directory*/
  if((dip = opendir(".")) == NULL)
    return errno;

  /*Store Current Working Directory in currentPath*/
  if((getcwd(currentPath, FILENAME_MAX)) == NULL)
    return errno;

  /*Read all items in directory*/
  while((dit = readdir(dip)) != NULL){
    /*Skips . and ..*/
    if(strcmp(dit->d_name, ".") == 0 || strcmp(dit->d_name, "..") == 0)
      continue;

    if(stat(currentPath, &statbuf) == -1){
      perror("stat");
      return errno;
    }

    /*Checks if current item is of the type file (type 8) and no command line arguments
      if(dit->d_type == 8 && argv[1] == NULL)*/
    if(S_ISREG(statbuf.st_mode) && argv[1] == NULL)
      printf("%s (%d bytes)\n", dit->d_name, (int)statbuf.st_size);

      /*If a command line argument is given, checks for filename match
    if(dit->d_type == 8 && argv[1] != NULL)*/
    if(S_ISREG(statbuf.st_mode) && argv[1] != NULL)
      if(strcmp(dit->d_name, argv[1]) == 0)
        printf("%s (%d bytes)\n", dit->d_name, (int)statbuf.st_size);

      /*Checks if current item is of the type directory (type 4)
      if(dit->d_type == 4)*/
    if(S_ISDIR(statbuf.st_mode))
      dircheck(dip, dit, statbuf, currentPath, depth, argv);

  }
  closedir(dip);
  return 0;
}

/*Recursively called helper function*/
void helper(DIR *dip, struct dirent *dit, struct stat statbuf, 
    char currentPath[FILENAME_MAX], int depth, char *argv[]){
  int i = 0;

  if((dip = opendir(currentPath)) == NULL)
    printf("Error: Failed to open Directory ==> %s\n", currentPath);

  while((dit = readdir(dip)) != NULL){

    if(strcmp(dit->d_name, ".") == 0 || strcmp(dit->d_name, "..") == 0)
      continue;

    stat(currentPath, &statbuf);

    /*if(dit->d_type == 8 && argv[1] == NULL){*/
    if(S_ISREG(statbuf.st_mode) && argv[1] == NULL){
      for(i = 0; i < depth; i++)
        printf("    ");
      printf("%s (%d bytes)\n", dit->d_name, (int)statbuf.st_size);
    }

    /*if(dit->d_type == 8 && argv[1] != NULL){*/
    if(S_ISREG(statbuf.st_mode) && argv[1] != NULL){
      if(strcmp(dit->d_name, argv[1]) == 0){
    for(i = 0; i < depth; i++)
      printf("    ");
    printf("%s (%d bytes)\n", dit->d_name, (int)statbuf.st_size);
      }
    }

    /*if(dit->d_type == 4)*/
    if(S_ISDIR(statbuf.st_mode))
      dircheck(dip, dit, statbuf, currentPath, depth, argv);

  }
}

void dircheck(DIR *dip, struct dirent *dit, struct stat statbuf, 
      char currentPath[FILENAME_MAX], int depth, char *argv[]){
  int i = 0;

  strcat(currentPath, "/");
  strcat(currentPath, dit->d_name);

  /*If two directories exist at the same level the path
    is built wrong and needs to be corrected*/
  if((chdir(currentPath)) == -1){
    chdir("..");
    getcwd(currentPath, FILENAME_MAX);
    strcat(currentPath, "/");
    strcat(currentPath, dit->d_name);

    for(i = 0; i < depth; i++)
      printf ("    ");
    printf("%s (subdirectory)\n", dit->d_name);
    depth++;
    helper(dip, dit, statbuf, currentPath, depth, argv);
  }

  else{
    for(i =0; i < depth; i++)
      printf("    ");
    printf("%s (subdirectory)\n", dit->d_name);
    chdir(currentPath);
    depth++;
    helper(dip, dit, statbuf, currentPath, depth, argv);
  }

}

解决方案

You're using S_ISREG() and S_ISDIR() correctly, you're just using them on the wrong thing.

In your while((dit = readdir(dip)) != NULL) loop in main, you're calling stat on currentPath over and over again without changing currentPath:

if(stat(currentPath, &statbuf) == -1) {
    perror("stat");
    return errno;
}

Shouldn't you be appending a slash and dit->d_name to currentPath to get the full path to the file that you want to stat? Methinks that similar changes to your other stat calls are also needed.

这篇关于如何使用S_ISREG()和S_ISDIR()POSIX宏?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆