What is the difference between fopen modes "r+" and "rw+" in PHP?
fopen, php
Solution
I think you have pretty much figured this out. Although I guess, you want authoritative answer.
It is true that the documentation does not mention `"rw+"`. Yet, there is something better: PHP source code!
The Rabbit Hole
I had a hard time trying to navigate the source code until I found the article series PHP's Source Code For PHP Developers (Part 1, Part 2, Part 3, Part 4). I know the links jump between two sites, that series is hip like that. By the way, I didn't find the announced Part 5.
Note: Those articles are old, they are talking about PHP 5.4.
Let us see what `fopen` actually does... let us fall into the rabbit hole...
First we look at the function definition (which I found following the advice of the linked part 2 above). I notice it uses `php_stream_open_wrapper_ex`, which I found elsewhere, it just uses `_php_stream_open_wrapper_ex` which we find in stream.c.
What does `_php_stream_open_wrapper_ex` do with `mode`? It passes it to `stream_opener`.
Looking for the definition of `stream_opener` took me to the type `php_stream_wrapper_ops` in php_streams.h.
Searching for uses of the type `php_stream_wrapper_ops` leaded me to plain_wrapper.c.
There are actually a lot of initializations of `php_stream_wrapper_ops` that allow to open different things. We are looking at php_fopen_wrapper.c because it has an initialization of `php_stream_wrapper_ops` where `stream_opener` is `php_plain_files_stream_opener`.
We are getting there...
`php_plain_files_stream_opener` is further down in the same file. It delegates to `php_stream_fopen_rel`.
`php_streams.h` defines `php_stream_fopen_rel` by using `_php_stream_fopen`. Which is back on plain_wrapper.c.
Finally, `_php_stream_fopen` calls `php_stream_parse_fopen_modes`. Which will take the string and output some flags, Yay!
Wonderland
Let us have a look at `php_stream_parse_fopen_modes`:
PHPAPI int php_stream_parse_fopen_modes(const char *mode, int *open_flags)
{
int flags;
switch (mode[0]) {
case 'r':
flags = 0;
break;
case 'w':
flags = O_TRUNC|O_CREAT;
break;
case 'a':
flags = O_CREAT|O_APPEND;
break;
case 'x':
flags = O_CREAT|O_EXCL;
break;
case 'c':
flags = O_CREAT;
break;
default:
/* unknown mode */
return FAILURE;
}
if (strchr(mode, '+')) {
flags |= O_RDWR;
} else if (flags) {
flags |= O_WRONLY;
} else {
flags |= O_RDONLY;
}
#if defined(O_CLOEXEC)
if (strchr(mode, 'e')) {
flags |= O_CLOEXEC;
}
#endif
#if defined(O_NONBLOCK)
if (strchr(mode, 'n')) {
flags |= O_NONBLOCK;
}
#endif
#if defined(_O_TEXT) && defined(O_BINARY)
if (strchr(mode, 't')) {
flags |= _O_TEXT;
} else {
flags |= O_BINARY;
}
#endif
*open_flags = flags;
return SUCCESS;
}
For abstract, this is what it does (ignoring the details):
It takes the first character of `mode` and checks if it is `r`, `w`, `a`, `x`, `c`. If it recognizes any of those, it sets the appropriate flag. Otherwise we have a `FAILURE`.
It looks for `+` somewhere in the string and sets the appropriate flags.
It looks for `e`, `n` and `t` (depending on Preprocessor Directives) somewhere in the string and sets the appropriate flags.
Return `SUCCESS`.
Back to the real world
You asked:
What is the difference between fopen modes “r+” and “rw+” in PHP?
Nothing. PHP only cares that the string starts with `"r"` and has a `"+"`. The `"w"` is ignored.
Final note: While it is tempting to play with it and write stuff like `"read+"`, be careful with that, because those letter could someday have some meaning. It would not be forward compatible. In fact, in some context, `"e"` already has a meaning. Instead, I suggest, sticking to the documentation.
Thanks for the excuse to give a look at the PHP source code.
Problem
Many answers here in Stack Overflow use `fopen($file, "rw+")`, but the manual doesn't list the `"rw+"` mode, there's only the `"r+"` mode (or `"w+"` mode). So I was wondering, what does the `"rw+"` mode do? What's the difference between `fopen($file,` `"rw+"` or `"r+"`? I'm asking this because there is no documentation on the `"rw+"` mode. One approach is to consider that the modes are additive, but I couldn't find any mention of combining modes in the `fopen` manual page (besides, what's the sense of combining `"r"` with `"w+"`, if `"w+"` already makes it readable?). But most importantly, `w+` mode truncates the file, while `rw+` does not truncate it (therefore, they cannot be additive). Probably there is no `rw+` mode, despite its use by Stack Overflow users. Maybe it works because the parser ignores the "w" letter, as the `rw+` mode appears to be === `r+`? To clarify my question: what is the `"rw+"` mode, that is, how does it differ from other modes? I only received two answers in the comments: either that I should check the documentation (I already checked and rechecked) and a wrong answer, which said it is equal to `"w+"` (it isn't). `"w+"` truncates the file, while `"rw+"` doesn't. Here's a script for testing (it proves that `w+` truncates the file, but `rw+` doesn't): ``` <?php $file = "somefile"; $fileOpened = fopen($file, "w"); fwrite($fileOpened, "0000000000000000000"); fclose($fileOpened); $fileOpened = fopen($file, "rw+"); fwrite($fileOpened, "data"); fclose($fileOpened); $fileOpened = fopen($file, "r"); $output = fgets($fileOpened); echo "First, with 'rw+' mode:<br>".$output; $fileOpened = fopen($file, "w+"); fwrite($fileOpened, "data"); fclose($fileOpened); $fileOpened = fopen($file, "r"); $output = fgets($fileOpened); echo "<br><br><br>Now with only 'w+' mode:<br>".$output; ?> ```