Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C File Operations: Check opened file pointer access mode

Tags:

c

A simple question:

How do I check the access mode of an already opened file pointer?

So say a function is passed an already opened FILE pointer:

    //Pseudo code
    bool PseudoFunction(FILE *Ptr)
    {
        if( ... Insert check for read-only access rights )
        {
            //It's read only access mode
            return true;
        }
       //File pointer is not read-only and thus write operations are permitted
       return false;
    }

What would I use in the if statement to check the FILE pointer had been opened as read-only (or not, as the case may be), without writing to the file, and without relying on the user passing (possibly contradicting) arguments?

System is windows, code::blocks compiler, but for interests of code portability, cross-compatibility preferred.

Note, this isn't asking about file rights, but what access mode has been used by FILE pointer.

SELF-ANSWER [Cannot append a separate answer due to user rights limitations]:

There is a better answer by another poster below that includes the proper #defines

As earlier suggested, it appears the FILE pointer's _flag (as defined under _iobuf) is the key for knowing whether or not a file is read only. Your mileage may vary though, but the same basic concept should be easily adaptable, example code:

#define READ_ONLY_FLAG 1

bool PrintFlagPtr(const char FileName[], const char AccessMode[])
{
    FILE *Ptr = NULL;
    Ptr = fopen(FileName,AccessMode);
    printf("%s: %d ",AccessMode,Ptr->_flag);

    int IsReadOnly = Ptr->_flag;
    fclose(Ptr);
    Ptr = NULL;


    if( (IsReadOnly&READ_ONLY_FLAG) == READ_ONLY_FLAG )
    {
        printf("File is read only!\n");
        return true;
    }

    printf("\n");
    return false;
}

That, when all the different access mode combinations are used with above function, produces an output of:

Output:
w: 2
r: 1 File is read only!
a: 2
wb: 2
rb: 1 File is read only!
ab: 2
w+: 128
r+: 128
a+: 128
w+b: 128
r+b: 128
a+b: 128

I am curious as to why this was never suggested (or never used), given a cross-compatible front-end function (simply a function with the same name, with declarations depending on platform) passing a const int sourced from the given FILE pointer _flag would be quite a simple and easy solution to the problem.

like image 786
SSight3 Avatar asked Aug 11 '11 12:08

SSight3


1 Answers

On Linux (and possibly all UNIX systems) you could use fcntl to get the access mode of the file:

int get_file_status(FILE* f) {
    int fd = fileno(f);
    return fcntl(fd, F_GETFL);
}

Note that the returned value is an integer as combination of flags like O_RDONLY or O_RDWR, not the "r" or "w+" strings. See http://pubs.opengroup.org/onlinepubs/007908799/xsh/open.html for some of these flags.

Not sure about Windows, see On Windows/mingw, what is the equivalent of `fcntl(fd, F_GETFL) | O_ACCMODE`?.

like image 188
kennytm Avatar answered Sep 21 '22 06:09

kennytm