7
\$\begingroup\$

I wrote a program that checks if two files (with a different path / name) match or not. The hard and symbolic links between the files are followed to determine it.

I know this is not the best implementation, so I would like some suggestions for improvement, possible problems. What you should change?

code:

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

void printUsage()
{
    printf("Use: ./leg <name_file1> <name_file2>.\n");
}

int createStat(const char* file, struct stat* fileStat)
{
    if(stat(file,fileStat) < 0)
    {
        fprintf(stderr,"Error! File %s does not exist.\n",file);
        return 0;
    }
    return 1;
}

int main(int argc, char **argv)
{
    if(argc < 3)
    {    
        printf("Insufficient number of parameters.\n");
        printUsage();
        return -1;
    }

    struct stat fileStat1;
    struct stat fileStat2;
    if(createStat(argv[1],&fileStat1) == 0)
    {
        return -1;
    }
    if(createStat(argv[2],&fileStat2) == 0)
    {
        return -1;
    }
    if(S_ISREG(fileStat1.st_mode) && S_ISREG(fileStat2.st_mode)){
        if((fileStat1.st_dev == fileStat2.st_dev) && (fileStat1.st_ino == fileStat2.st_ino)){
            printf("Files'%s' and '%s' coincide.\n", argv[1], argv[2]);
        }
        else
            printf("Files '%s' and '%s' do not match.\n", argv[1], argv[2]);
    }
    else
        fprintf(stderr,"'%s' and '%s' there are no files.\n",argv[1],argv[2]);

    return 0;
}
\$\endgroup\$

1 Answer 1

4
\$\begingroup\$
if(createStat(argv[1],&fileStat1) == 0)
{
    return -1;
}

It's a good idea to output a diagnostic there:

if(createStat(argv[1], &fileStat1) == 0)
{
    perror(argv[1]);
    return EXIT_FAILURE;
}

The S_ISREG test seems at best unnecessary, and at worst harmful - what if the files you want to compare are device files? Or directories? Both of those seem valid uses.


Please be consistent with the use of braces. Some conditionals have them only for the if block and not the else. Code is easier to read correctly if you're consistent; I recommend using braces even for single statements.


The program would be more useful if it returned 0 only if the pathnames refer to the same file, so that scripts can easily use it (although test -ef already exists for that purpose, so perhaps unnecessary).


if(argc < 3)
{    
    printf("Insufficient number of parameters.\n");
    printUsage();
    return -1;
}

We should probably at least warn if too many arguments are supplied, and the error message ought to go to the standard error stream.

if (argc != 3)
{    
    fputs("Incorrect number of arguments.\n", stderr);
    printUsage(stderr);
    return EXIT_FAILURE;
}

if(stat(file,fileStat) < 0)
{
    fprintf(stderr,"Error! File %s does not exist.\n",file);

Misleading error message - the file might exist, but have insufficient permissions for us to access. Or any of the other reasons listed in the man page (though mostly they prevent the file existing).

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.