phcaze
phcaze

Reputation: 1777

stat() returns error

I have to know the modification date of some files in a folder. It works, but not with all types of files. For example it works with .c, .txt, but it doesn't work with other types such .mp4, .jpg and .mp3 (the application I'm creating have to work with multimedia files in general). It prints "Cannot display the time.", so I suppose the problem is on stat(). Thanks.

This is the code:

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

char parola[12]="", hash[32]="", esadecimale[1000]="", system3[100]="./md5 ";
int i, len, len2;
int bytes;
char cwd[1024];

int main(void)
{
char t[100] = "";
struct stat b;
DIR *dp;
char destinationFolder[100] = "/Users/mattiazeni/Desktop/Prova/"; //Me la passa da sopra
struct dirent *dir_p;
dp = opendir(destinationFolder);
if ( dp == NULL ) exit(1);

len = strlen(destinationFolder);

for (i=0;i<len;i++) {
    system3[i+6]=destinationFolder[i];
}

while( ( dir_p = readdir(dp) ) != NULL ) {
    if (dir_p -> d_name[0] != '.') {
        //printf("%s\n", dir_p -> d_name);
        len2 = strlen(dir_p -> d_name);
        for (i=0;i<len2;i++) {
            if (dir_p -> d_name[i] == ' '){ //Mi serve per correggere i nomi dei file con spazi
                system3[i+len+6]='\\';   
            }
            else system3[i+len+6]=dir_p -> d_name[i];
        }
        system(system3); //Passa il valore a md5 che calcola l'hash e lo stampa nel file che ci serve insieme al persorso/nome del file

        FILE *fp;
        if((fp=fopen("userDatabase.txt", "ab"))==NULL) {
            printf("Error while opening the file..\n");
            fclose (fp);
        }
        else {
            if (!stat(dir_p -> d_name, &b)) {
            strftime(t, 100, "%d/%m/%Y %H:%M:%S", localtime( &b.st_mtime));         //C'è ancora qualche errore!!
            fprintf(fp, "%s", t);           
            }
            else {
                perror(0);
                fprintf(fp, "error");
            }
            fprintf(fp, " initialized");
            fprintf(fp, "\n");
        }
        fclose (fp);
        for (i=len+6;i<len+6+len2;i++) {
            system3[i]=' ';
        }
    }
}   
closedir(dp);
return 0;
}

Upvotes: 0

Views: 6136

Answers (3)

phcaze
phcaze

Reputation: 1777

This is the final working code in order to scan a directory for files, and print them on a txt output file with the modification date:

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

char system3[6]="./md5 ";

int main(void)
{
char t[100] = "";
char bigbuff[200];
struct stat b;
char destinationFolder[100] = "/Users/mattiazeni/Desktop/Prova"; //Me la passa da sopra
DIR *dp;
struct dirent *dir_p;
dp = opendir(destinationFolder);
if ( dp == NULL ) exit(1);
while( ( dir_p = readdir(dp) ) != NULL ) {
    if (dir_p -> d_name[0] != '.') {
        sprintf( bigbuff, "%s%s/%s",system3, destinationFolder, dir_p->d_name);
        system(bigbuff); 

        FILE *fp;
        if((fp=fopen("userDatabase.txt", "ab"))==NULL) {
            printf("Error while opening the file..\n");
            fclose (fp);
        }
        else {
            sprintf( bigbuff, "%s/%s", destinationFolder, dir_p->d_name);
            if (!stat(bigbuff, &b)) {
            strftime(t, 100, "%d/%m/%Y %H:%M:%S", localtime( &b.st_mtime));         //C'è ancora qualche errore!!
            fprintf(fp, "%s", t);           
            }
            else {
                perror(0);
                fprintf(fp, "error");
            }
            fprintf(fp, "\n");
        }
        fclose (fp);
    }
}   
closedir(dp);
return 0;
}

Thanks all for the help!

Upvotes: 0

Morpfh
Morpfh

Reputation: 4093

Use perror(). Also shouldn't you use st_mtime?

stat:
       On success, zero is returned. 
       On error, -1 is returned, and errno is set appropriately. 

99% sure it is because dir_p -> d_name does not exist, which in turn probably is because of a localization issue.

You could do something like:

fprintf(stderr, 
        "Unable to stat %s\n",
        dir_p->d_name); 
perror(0);

Also; shouldn't it be ->f_name and not ->d_name if you are checking file status? - (Unless you use d_name for file name off course.)

And your fclose(fp) is outside your fp == NULL check. As you do not return or otherwise abort the flow you risk an SIGSEGV if the fopen fail.


Edit: What do you get with something like this?

#include <unistd.h>

char cwd[1024];

...  


} else {
    fprintf(stderr,
            "Unable to stat '%s'\n",
            dir_p->d_name);
    perror(0);

    if (getcwd(cwd, sizeof(cwd)) == NULL) {
        perror("getcwd() error");
    } else {
        fprintf(stderr,
                "in directory  '%s'\n",
                cwd);
    }
} 

Edit2:

First; I said getcwd() != NULL should be ==. Se change. (Bad by me.)

The problem in your code. (There is a few more) but regarding stat - you use d_name from readdir. This is only filename; not dir+filename. Thus; you get i.e.:

stat(dir_p->d_name, ...)

Which becomes i.e.:

stat("file.mp4", ...)

Easiest quick-fix (tho dirty) would be:

/* you need to terminate the system string after your for loop */
system3[i + len + 6] = '\0';

system(system3);

if (!stat(system3 + 6, &b)) {

Upvotes: 3

wildplasser
wildplasser

Reputation: 44220

You should use the complete pathname for stat(). Stat does not know which directory you are interested in.

... 
char  bigbuff[PATH_MAX];

sprintf( bigbuff, "%s/%s", destinationFolder, dir_p->d_name);

rc = stat (bigbuff, &b);
...

Upvotes: 0

Related Questions