help with opening files and reading them in C

In C, given a name or path to a file, how do I check if the path is valid, and how can I check its permisions will let me read from it, and how do i check if its an empty file?

#include <unistd.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
// questions 1 & 2:
// access validates access to a file  F_OK == path is okay and file exists  
//  R_OK == F_OK + I can read it, so use R_OK
// Q3:
// this is a general function to get the size of an opened file
size_t filesize(int fd)
{
    struct stat st;
    if(fstat(fd, &st)== -1)
    {
          perror("Cannot stat file");
          exit(1);
    }
    return st.st_size;
}
int main(int argc, char **argv)
{
    FILE *in=NULL; 
    
    if(access(argv[1], R_OK)==0)
    {
           printf("file %s, access is okay\n", argv[1]);
    }
    in=fopen(argv[1],"r");
    printf("file size = %u\n", filesize(fileno(in));
    fclose(in);
    return 0;
}

when doing the access command i am getting this error

:108: error: �R_OK� undeclared (first use in this function)
108: error: (Each undeclared identifier is reported only once
108: error: for each function it appears in.)

Vave you included unistd.h? What operating system are you on?

Also note that

   printf("file size = %u\n", filesize(fileno(in));

should be

   printf("file size = %u\n", filesize(fileno(in)) );

oh i missed that, now i got it

Like this:

int fd = open( pathToFile, O_RDONLY );

Anything else is extraneous - there's no point in using access() on a path just to check if if exists if you're going to open it for reading - the open will do that for you. If it doesn't exist, the open() call will fail with errno set to EEXIST. There's no point in checking if the permissions allow you to read the file, because if you can't the open will fail with errno set to either EPERM or EACCESS (I forget offhand which one it will be).

If it's empty, when you read from it you'll get zero bytes.

There's no point in checking to see if you can or can't do something - just make the call to do it and check your return status.

You DO check return status ALWAYS, don't you?

i'm am trying to read a unix word list file, using this code

int u=1;
char line[11];
    int length;
FILE *fr;
fr = fopen ("/usr/share/dict/words", "r");
while (fgets(line, 11, fr) != NULL) {
 length = str_len(&line);
 printf(line);
 printf("\n%d %d\n",length,u);
u++;
}

and for some reason i get stuff like empty strings
this is part of the output:

2 134536
hemoscope
9 134537

0 134538
hemoscopy
9 134539

0 134540
hemosider
9 134541
in
2 134542

why is this happenning?

The script (apart from changing str_len to strlen) seems to work - such as it is.

Knowing nothing about the format of this "words" file, do you not think that allocating ten characters to each word is maybe on the stingy side (char line[11];?

well i dont want to give a fixed number of allocating, as the string could be any length, and the str_len is my own function that gives the length of the string, excluding the \0 and \n at the end, so still i dont know whats wrong. if i loop through the word list and print the lines normally, it comes out right.....

And what, exactly, does you own str_len function give you thats greater than what fgets will read?

You gave a "fixed number of allocating" when you wrote char line[11].

It seems clear that you would get "extra blank lines" where you have ten-character words:

$ cat file1
1234567890
12345678901

$ ./main   
1234567890
10 1


1 2
1234567890
10 3
1

2 4

ok changing that 11 to 30 fixed it, but now after i do that i get some kind of error that never happened before

*** stack smashing detected ***: ./myprog terminated
======= Backtrace: =========
/lib/tls/i686/cmov/libc.so.6(__fortify_fail+0x48)[0xb7e7b238]
/lib/tls/i686/cmov/libc.so.6(__fortify_fail+0x0)[0xb7e7b1f0]
./myprog [0x8048cfd]
[0xb7000000]

You used 11 in two places. Did you change it in both?

haha thanks that fixed it.

but the only thing bugging me is that i changed it to 30, assuming the biggest string is 30 bytes, is there no generalised way to allocate the size of the biggest string or something?, like what if a string thats more then 30 comes up?

What's the biggest word in the dictionary?

Google it :slight_smile:

Would it hurt just to make it 1000? It's not like you're storing every word in the dictionary - you're getting them one at a time.

on wiki
Longest word in English - Wikipedia, the free encyclopedia
it says
189,819 (for the length)

so using the number 200000 is safe?
like it wont crash my program or anything?

Hmm. Maybe add a substr to your code, here or there :smiley:

They must have invented the five-letter chemical name (titin) when memory cost a million bucks a meg :smiley: