What is the difference between fopen "r +" and "rw +" modes in PHP?

Many answers here in Qaru use fopen($file, "rw+") , but manual does not list the mode "rw+" , there is only the mode "r+" (or "w+" ).

So, I was wondering what the "rw+" mode does? What is the difference between fopen($file, "rw+" or "r+" ? I ask this because there is no documentation in the "rw+" mode.

One approach is to keep in mind that the modes are additive, but I could not find a mention of the mode combinations on the fopen page (except that it means combining "r" with "w+" if "w+" already makes it available for reading?). But most importantly, w+ mode truncates the file, and rw+ does not truncate it (therefore, they cannot be additive). There is probably no rw+ mode, despite its use by Stack Overflow users. Perhaps this works because the parser ignores the letter "w" because the rw+ mode looks like === r+ ?

To clarify my question: what is the "rw+" mode, that is, how does it differ from other modes? I received only two answers in the comments: either I have to check the documentation (I have already checked and double-checked), or an incorrect answer, which said that it is equal to "w+" (this is not so). "w+" truncates the file, but "rw+" does not.

Here's a script for testing (this proves that w+ truncates the file, but rw+ doesn't work):

 <?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; ?> 
+55
php fopen
May 05 '17 at 5:30 a.m.
source share
1 answer

I think you understand a lot. Although, I think you need an authoritative answer.

It is true that the documentation does not mention "rw+" . However, there is something better: the PHP source code !




Rabbit hole

It was difficult for me to navigate in the source code until I found an article with PHP source code for PHP developers ( part 1 , part 2 , part 3 , part 4 ). I know that links jump between two sites, this series is as follows. By the way, I did not find the announced part 5.

Note These articles are old, they talk about PHP 5.4.

Let's see what fopen actually does ... let's fall into a rabbit hole ...

First we look at the definition of a function (which I found on the recommendation of related part 2 above). I noticed that 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 with mode ? It passes it stream_opener .

Searching for the definition of stream_opener led me to type php_stream_wrapper_ops in php_streams.h .

Finding a usage like php_stream_wrapper_ops led me to plain_wrapper.c .

In fact, there are many php_stream_wrapper_ops initializations that allow you to open different things. We look at php_fopen_wrapper.c as it has initialization php_stream_wrapper_ops where stream_opener is php_plain_files_stream_opener .

We get there ...

php_plain_files_stream_opener further in the same file . He delegates to php_stream_fopen_rel .

php_streams.h defines php_stream_fopen_rel with _php_stream_fopen . What is called back to plain_wrapper.c .

Finally, _php_stream_fopen calls php_stream_parse_fopen_modes . Which will take a line and display some flags, Yay!




Wonderland

Let's take 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 the abstract, this is what it does (ignoring the details):

  • It takes the first character mode and checks if it is r , w , a , x , c . If he recognizes any of them, he sets the corresponding flag. Otherwise, we have FAILURE .

  • It searches + somewhere in the string and sets the appropriate flags.

  • It searches for e , n and t (depending on the preprocessor directives) somewhere in the string and sets the appropriate flags.

  • Return SUCCESS .




Return to the real world

You asked:

What is the difference between fopen "r +" and "rw +" modes in PHP?

Nothing. PHP only cares that the line starts with "r" and has a "+" . "w" ignored.

Final note . Although it is tempting to play with her and write things like "read+" , be careful with this because this letter may someday have some meaning. It would not be compatible with the transition. In fact, in some context, "e" already makes sense. Instead, I suggest sticking to the documentation.




Thanks for the excuse to view the PHP source code.

+68
Jun 11 '17 at 11:35
source share



All Articles