3

How to check whether an opened file is in read mode or write mode i.e. "r" or "w"?

Note that the file was opened using fopen command and it has to be in a standard way instead of platform-specific hacks.

EDIT 1:

It seems that the FILE data structure is implementation-dependent. The only way to get it must be in the FILE.flags variable however in my Mingw32, it has only FILE._flags.

  • It sounds like you have a problem with a better solution. Where do you get the FILE from? Can that code also pass the mode? – Daniel May 21 '16 at 15:55
  • @Dani I know that I have a better solution by simply storing the mode at the time of opening it in my structure. But since a `FILE` is state-based, it must be storing that information somewhere. –  May 21 '16 at 16:02
  • You could always attempt to backup 1 char, read the char, save it, backup again and attempt to write it.. I haven't tried it, but that came to mind. – David C. Rankin May 21 '16 at 16:02
  • @smlq: Nothing in the FILE interface requires saving the mode, it could just pass it to the operating system and forget about it. – Daniel May 21 '16 at 16:10
  • Can you explain why you want to know this information? Simply checking whether an actual read/write operation succeeded is probably much faster (and easier if you're wanting code that's portable beyond POSIX and Windows platforms). –  May 21 '16 at 19:45
  • @ChronoKitsune: I am writing an user-defined `BITFRAMEFILE` structure on top of `FILE` that will read `bitframes` instead of `bytes` which will have the similar functions like `fread`, `fwrite`, `fseek`, etc. So, in order to catch errors like `fwrite`ing an `BITFRAMEFILE` that was opened with `r` beforehand, I required this. However, as I already mentioned earlier, I could have stored that information in `BITFRAMEFILE` itself during opening the underlying `FILE`. But nevertheless, I thought that there must be some way in C itself for the `FILE` structure. –  May 22 '16 at 01:46
  • 2
    @smlq In that case, as you've found out, the only way to do this portably is to store the information yourself. I wish there was a better solution for you, but that's really the only acceptable answer in such a context. –  May 22 '16 at 01:50

3 Answers3

2

As Ezequiel Garcia mentioned, every FILE has an associated file descriptor, and you can inquire about the mode of the file descriptor with

const int word = fcntl(fd, F_GETFL);

Now a key point is how to go from word to the opening mode. That was the subject of question How to get the mode of a file descriptor?

It took me some asking, tinkering and learning to get to the answer, which left some intriguing issues, and significant gaps between man pages and what one gets with experimenting.

I suggest you try using the code I posted, in your system (mingw32) and see what results it produces. It will help you writing (more) portable code.

  • "every FILE has an associated file descriptor" => not always true. POSIX has `open_memstream`/`open_wmemstream` which allow you to create a `FILE*` backed by a memory buffer, which has no corresponding file descriptor. Beyond POSIX, various OS define functions such as `fmemopen`, `funopen`, `fopencookie` which also let you create FD-less streams. File descriptors aren't 100% portable, since `fileno` is a POSIX extension not in ISO C. (Although all major non-POSIX OS, such as Windows, incompletely emulate them.) – Simon Kissane Nov 02 '22 at 04:57
1

A file descriptor access mode can be obtained with fcntl call.

However, if you are using fopen() (which returns a FILE* and not an integer file descriptor), you need to get the file descriptor first.

You can use int fileno(FILE *stream) for that. Keep in mind this is not in the C standard, but rather POSIX standard.

EDIT: Dirty example:

FILE *file = fopen("/home/zeta/a.c", "r");
int fd = fileno(file);
int mode = fcntl(fd, F_GETFL);

The man page has all you need to know about fcntl:

http://man7.org/linux/man-pages/man2/fcntl.2.html

ilent2
  • 5,171
  • 3
  • 21
  • 30
Ezequiel Garcia
  • 1,037
  • 8
  • 20
  • It would be helpful if you provided the call to fcntl and its arguments. – Uyghur Lives Matter May 21 '16 at 22:49
  • @EzequielGarcía: thanks! but do you have any hints on msvc? –  May 22 '16 at 01:37
  • 1
    @smlq No. In my opinion, you should just keep track of the access mode in your program and stop worrying. Also, it will be cheaper to get that information. In the example I provided, getting the access mode results in a system call, which means a context switch will be needed, just to get this tiny piece of information. Storing the access mode together with the FILE* is in my opinion, faster, simpler and portable. – Ezequiel Garcia May 23 '16 at 18:45
  • How would you interpret the result that you get in `mode` in terms of the available modes, "r", "r+", "w", "w+", "a", "a+"? – sancho.s ReinstateMonicaCellio May 19 '20 at 22:57
  • @sancho.sReinstateMonicaCellio I think they map quite nicely, check open, fopen and fcntl man pages. E.g. is F_GETFL returns O_RDWR then it should be "r+". Perhaps you can do some experiments to confirm. – Ezequiel Garcia May 20 '20 at 02:16
  • I am currently not being able to navigate the man pages to come up with simple listings of modes, flags, etc. – sancho.s ReinstateMonicaCellio May 20 '20 at 09:03
  • Please check my added answer and the links there. It was not obvious at all from the man pages, and there are actually significant gaps, I guess. – sancho.s ReinstateMonicaCellio May 21 '20 at 11:13
1

a more complete code to Ezequiel Garcia, which gives you opening mode of file.

int main() {
FILE *file = fopen("mand.txt", "r");
int fd = fileno(file);
int mode = fcntl(fd, F_GETFL);
//printf("%d",mode);
switch(mode){
    case 32768 : printf("r"); break;
    case 32769 : printf("w"); break;
    case 33793 : printf("a"); break;
    case 32770 : printf("r+ || w+"); break;
    case 32794 : printf("a+"); break;
}
return 0;

}

for more details check the man page [http://man7.org/linux/man-pages/man2/fcntl.2.html]

Harsh Tripathi
  • 109
  • 1
  • 5