title: How to use S_ISREG() and S_ISDIR() POSIX Macros?
body: <p>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 <code>dit-&gt;d_type == 8</code> check and the other similar ones don't work because there is no <code>d_type</code> field.  An answer I've read to this problem is to use the <code>S_ISREG()</code> and <code>S_ISDIR()</code> 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.</p>
  
  <pre><code>#include &lt;sys/types.h&gt;
  #include &lt;sys/stat.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;dirent.h&gt;
  #include &lt;stdio.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;errno.h&gt;
  #include &lt;string.h&gt;
  
  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-&gt;d_name, ".") == 0 || strcmp(dit-&gt;d_name, "..") == 0)
        continue;
  
      if(stat(currentPath, &amp;statbuf) == -1){
        perror("stat");
        return errno;
      }
  
      /*Checks if current item is of the type file (type 8) and no command line arguments
        if(dit-&gt;d_type == 8 &amp;&amp; argv[1] == NULL)*/
      if(S_ISREG(statbuf.st_mode) &amp;&amp; argv[1] == NULL)
        printf("%s (%d bytes)\n", dit-&gt;d_name, (int)statbuf.st_size);
  
        /*If a command line argument is given, checks for filename match
      if(dit-&gt;d_type == 8 &amp;&amp; argv[1] != NULL)*/
      if(S_ISREG(statbuf.st_mode) &amp;&amp; argv[1] != NULL)
        if(strcmp(dit-&gt;d_name, argv[1]) == 0)
          printf("%s (%d bytes)\n", dit-&gt;d_name, (int)statbuf.st_size);
  
        /*Checks if current item is of the type directory (type 4)
        if(dit-&gt;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 ==&gt; %s\n", currentPath);
  
    while((dit = readdir(dip)) != NULL){
  
      if(strcmp(dit-&gt;d_name, ".") == 0 || strcmp(dit-&gt;d_name, "..") == 0)
        continue;
  
      stat(currentPath, &amp;statbuf);
  
      /*if(dit-&gt;d_type == 8 &amp;&amp; argv[1] == NULL){*/
      if(S_ISREG(statbuf.st_mode) &amp;&amp; argv[1] == NULL){
        for(i = 0; i &lt; depth; i++)
          printf("    ");
        printf("%s (%d bytes)\n", dit-&gt;d_name, (int)statbuf.st_size);
      }
  
      /*if(dit-&gt;d_type == 8 &amp;&amp; argv[1] != NULL){*/
      if(S_ISREG(statbuf.st_mode) &amp;&amp; argv[1] != NULL){
        if(strcmp(dit-&gt;d_name, argv[1]) == 0){
      for(i = 0; i &lt; depth; i++)
        printf("    ");
      printf("%s (%d bytes)\n", dit-&gt;d_name, (int)statbuf.st_size);
        }
      }
  
      /*if(dit-&gt;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-&gt;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-&gt;d_name);
  
      for(i = 0; i &lt; depth; i++)
        printf ("    ");
      printf("%s (subdirectory)\n", dit-&gt;d_name);
      depth++;
      helper(dip, dit, statbuf, currentPath, depth, argv);
    }
  
    else{
      for(i =0; i &lt; depth; i++)
        printf("    ");
      printf("%s (subdirectory)\n", dit-&gt;d_name);
      chdir(currentPath);
      depth++;
      helper(dip, dit, statbuf, currentPath, depth, argv);
    }
  
  }
  </code></pre>