cdirectorygetcwdcwd

Trying to create a code that print absolute path and last modify time of file


WHAT I HAVE TO DO

I have to find, starting from a directory, a file located in one of all directories that have as root the directory passed in input. Something as shell command find.

INPUT/OUTPUT

Having this in input:

./myfind /home/claudio/Scrivania file.txt

I need something as this in output, absolute path and last modify date ecc:

/home/claudio/Scrivania/SistemiOperativi/file.txt   Tue Mar 30 19:51:54 2021

MY CODE It doesn't print anything.

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

#if !defined(NAME_MAX)
#define NAME_MAX 256
#endif

void find(const char* passed_dir_name, const char* passed_file_name) {
    if (chdir(passed_dir_name) == -1) {
        perror("FATAL ERROR CHANGING DIRECTORY");
        exit(EXIT_FAILURE);
    }
    DIR* current_directory;
    if ((current_directory = opendir(".")) == NULL) {
        perror("FATAL ERROR OPENING CURRENT WORKING DIRECTORY");
        exit(EXIT_FAILURE);
    }
    char* buf;
    if ((buf = calloc(NAME_MAX, sizeof(char))) == NULL) {
        perror("FATAL ERROR ALLOCATING MEMORY");
        exit(EXIT_FAILURE);
    }
    struct dirent* dir;
    while ((dir = readdir(current_directory)) != NULL) {
        struct stat statbuf;
        stat(dir->d_name, &statbuf);
        if (S_ISDIR(statbuf.st_mode)) {
            if (strncmp(dir->d_name, ".", 1) != 0 && strncmp(dir->d_name, "..", 2) != 0) {
                find(dir->d_name, passed_file_name);
            }
        } else {
            if (strncmp(dir->d_name, passed_file_name, strlen(passed_file_name) == 0)) {
                if (getcwd(buf, NAME_MAX) == NULL) {
                    perror("FATAL ERROR");
                    exit(EXIT_FAILURE);
                }
            fprintf(stdout, "%s/%s     %s", buf, dir->d_name, ctime(&statbuf.st_mtime));   
            }
        }
    }
    if (closedir(current_directory) == -1) {
        perror("FATAL ERROR CLOSING CURRENT WORKING DIRECTORY");
        exit(EXIT_FAILURE);
    }  
    chdir("..");
    free(buf);
}

int main(int argc, char** argv) {
    if (argc != 3) {
        fprintf(stderr, "ERROR: RUn as ./myfind directory\n");
        exit(EXIT_FAILURE);
    }
    const char* dir = argv[1];
    const char* file = argv[2];
    struct stat statbuf;
    stat(dir, &statbuf);
    if(!S_ISDIR(statbuf.st_mode)) {
        fprintf(stderr, "FATAL ERROR: %s IS NOT A DIRECTORY\n", dir);
        exit(EXIT_FAILURE);
    }
    find(dir, file);
    exit(EXIT_SUCCESS);
}

Solution

  • Your parentheses are wrong in:

    if (strncmp(dir->d_name, passed_file_name, strlen(passed_file_name) == 0))
    

    You need to write:

    if (strncmp(dir->d_name, passed_file_name, strlen(passed_file_name)) == 0)
    

    Since strncmp(x, y, 0) will always return 0, the condition is never being met.

    But note that there's no point in using strncmp here at all. strncmp is only needed if you don't know that one of your entries is a null terminated string. You have a guarante that d_name is null-terminated, and if passed_file_name is not, then strlen is going to be problematic. You might as well just write strcmp(dir->d_name, passed_file_name).