Finding if file is directory or file

Viewed 112

I'm writing a basic program which takes in the name of a directory and opens it. Once I've opened it, I would like to classify files and subdirectories. I found code from a while ago which did something similar - but this is the output I'm getting:

[.] -> [0]
[..] -> [0]
[a.txt] -> [0]
[subDir] -> [0]

Where a.txt is a text fille and subDir is a directory, but both those values are returning 0. Not sure where I'm going wrong.

Full code:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <dirent.h>

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

void handleDirectory(DIR *dir);
int isFile(const char *path);

int main(int argc, char **argv)
{
    if (argc != 2){
        printf("Not enough arguments!\n");
        return 0; 
    }

    DIR *dir = opendir(argv[1]);
    if (dir == NULL){
      return 0;
    }

    handleDirectory(dir);
} // end of main 

void handleDirectory(DIR *dir){
    struct dirent *temp;
    while ((temp = readdir(dir)) != NULL) {
        printf("[%s] -> [%d]\n", temp->d_name, isFile(temp->d_name));
    }
} // end of handle directory method 

int isFile(const char *path)
{
    struct stat path_stat;
    lstat(path, &path_stat);
    return S_ISREG(path_stat.st_mode); 
}
1 Answers

As tadman suggested, stat() (or fstat() or lstat()) are good choices to query file type. st_mode in the returned "stat" struct tells you file type and mode: S_IFREG= "regular file", S_IFDIR= "directory", and so forth.

opendir()/readdir() is certainly a reasonable alternative. "d_type" in the "dirent" struct tells you file type: DT_REG= "regular file", DT_DIR= "directory", etc.

If you got a compile error calling fstat, then you need to 1) show us the code, and 2) copy/paste the exact error text.

The only thing your code is checking for is "st_mode == S_ISREG". At a minimum, I would update the code to check for sb.st_mode & S_IFMT, per this example:

https://man7.org/linux/man-pages/man2/stat.2.html

   #include <sys/types.h>
   #include <sys/stat.h>
   #include <stdint.h>
   #include <time.h>
   #include <stdio.h>
   #include <stdlib.h>
   #include <sys/sysmacros.h>

   int
   main(int argc, char *argv[])
   {
       struct stat sb;

       if (argc != 2) {
           fprintf(stderr, "Usage: %s <pathname>\n", argv[0]);
           exit(EXIT_FAILURE);
       }

       if (lstat(argv[1], &sb) == -1) {
           perror("lstat");
           exit(EXIT_FAILURE);
       }

       printf("ID of containing device:  [%jx,%jx]\n",
               (uintmax_t) major(sb.st_dev),
               (uintmax_t) minor(sb.st_dev));

       printf("File type:                ");

       switch (sb.st_mode & S_IFMT) {
       case S_IFBLK:  printf("block device\n");            break;
       case S_IFCHR:  printf("character device\n");        break;
       case S_IFDIR:  printf("directory\n");               break;
       case S_IFIFO:  printf("FIFO/pipe\n");               break;
       case S_IFLNK:  printf("symlink\n");                 break;
       case S_IFREG:  printf("regular file\n");            break;
       case S_IFSOCK: printf("socket\n");                  break;
       default:       printf("unknown?\n");                break;
       }

       printf("I-node number:            %ju\n", (uintmax_t) sb.st_ino);

       printf("Mode:                     %jo (octal)\n",
               (uintmax_t) sb.st_mode);

       printf("Link count:               %ju\n", (uintmax_t) sb.st_nlink);
       printf("Ownership:                UID=%ju   GID=%ju\n",
               (uintmax_t) sb.st_uid, (uintmax_t) sb.st_gid);

       printf("Preferred I/O block size: %jd bytes\n",
               (intmax_t) sb.st_blksize);
       printf("File size:                %jd bytes\n",
               (intmax_t) sb.st_size);
       printf("Blocks allocated:         %jd\n",
               (intmax_t) sb.st_blocks);

       printf("Last status change:       %s", ctime(&sb.st_ctime));
       printf("Last file access:         %s", ctime(&sb.st_atime));
       printf("Last file modification:   %s", ctime(&sb.st_mtime));

       exit(EXIT_SUCCESS);
   }
Related