Matt Fomich Matt Fomich - 3 months ago 9
Linux Question

Linux C, File validation not working

I wanted to make a simple file validation function in C, to verify a file exists before reading it. For some reason, my validation code keeps returning false for a valid file. The file is in the same location as the compiled program. I tried using the full path, and only the file path. Why is my function failing to find the file?

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <stdbool.h>
// #include <linux/string.h>
const char* CONFIG_FILE = "/home/matt/atc_config"; //"/config.ini";

bool path_status (char *s_path);

//bool Validate_File(const char* path);
//bool Read_Config_File(const char* path, char* contents);
//bool Parse_Config_Data(const char* data, MeterParams* mp);

int main(int argc, char** argv)
{
// Get path to config file. This assumes our config file
// is kept in the same folder as this execuable file.

char file[256];
strcpy (file, argv[0]);
strcat (file, CONFIG_FILE);

puts ( file );

// Validate config file is present and we
// can access it.
if ( path_status ( CONFIG_FILE )) // ( file ))
{
puts ("file ok.");
// Read the file's contents.

}
else
{
puts ("file not ok.");
}

return (EXIT_SUCCESS);
}

bool path_status (char *s_path)
{
/* The following mask values are defined for the file type of the
st_mode field:
*
S_IFMT 0170000 bit mask for the file type bit field

S_IFSOCK 0140000 socket
S_IFLNK 0120000 symbolic link
S_IFREG 0100000 regular file
S_IFBLK 0060000 block device
S_IFDIR 0040000 directory
S_IFCHR 0020000 character device
S_IFIFO 0010000 FIFO
* ref: http://man7.org/linux/man-pages/man2/stat.2.html
*/

// 'stat'returns information about file, folder, link or socket.
// It fills a structure, also named 'stat'.
// On success, zero is returned. On error, -1 is returned, and
// errno is set appropriately.

struct stat st;
bool ret = false;
if (stat(s_path , &st) == 0) // // Zero indicates path status successfully obtained.
{
ret = (st.st_mode & S_IFMT == S_IFREG);
}
return ret;
}


Thanks,

Matt

Answer

There's a precedence error here:

ret = (st.st_mode & S_IFMT == S_IFREG);

This parses as

ret = (st.st_mode & (S_IFMT == S_IFREG));

because == binds tighter than & (for silly reasons). S_IFMT == S_IFREG is 0, anything & 0 is 0, so ret is always 0.


Fix:

ret = (st.st_mode & S_IFMT) == S_IFREG;