0xAA55 发表于 2018-1-31 03:41:17

【PHP】fopen()的坑

原帖网址:https://www.0xaa55.com/thread-16709-1-1.html
转载请保留出处。

注:此处所说的fopen()指的是PHP的fopen()函数而非C库的fopen()函数。

在PHP官方文档的描述上我注意到有人用"rw"方式来打开文件,但这样写对不对呢?PHP的官方文档并没有说。
它的原文是:



那咋办?我们直接去看PHP源码就知道它是怎么实现的了。
传送门点此

然后注意观察,它是这样写的:/* parse standard "fopen" modes into open() flags */
PHPAPI int php_stream_parse_fopen_modes(const char *mode, int *open_flags)
{
        int flags;

        switch (mode) {
                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;
}它只判断“模式”的第一个字符,也就是mode,看它是r还是w还是a还是x还是c,然后决定打开方式——直接翻译成C库open()函数的功能。

也就是说,"rw"这种模式,里面的字母w是被无视掉的。效果等同于"r"。
既然这样……嘿嘿嘿,我要皮了。$fp = fopen("session.lock", "crap+"); // 读写模式打开或创建文件
$fp = fopen("foo.txt", "rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr+"); // 读写模式打开文件
$fp = fopen("bar.txt", "rabbit+"); // 读写模式打开文件
$fp = fopen("baz.txt", "what th3 fuck"); // 写文件模式
$fp = fopen("latest.log", "abcdEfghijklmNopqrsTuvwxyz"); // 写文件末尾模式皮这一下很开心。嗯。

参考资料:
http://php.net/manual/zh/function.fopen.php
https://stackoverflow.com/questions/43797180/what-is-the-difference-between-fopen-modes-r-and-rw-in-php
https://github.com/php/php-src/blob/master/main/streams/plain_wrapper.c#L66
http://man7.org/linux/man-pages/man2/open.2.html

思齐 发表于 2018-2-1 13:14:42

abcdEfghijklmNopqrsTuvwxyz 写这么多有啥用,人家是strchar判断的:$

0xAA55 发表于 2018-2-1 15:28:22

思齐 发表于 2018-2-1 13:14
abcdEfghijklmNopqrsTuvwxyz 写这么多有啥用,人家是strchar判断的

是strchr不是strchar。
另外,写得多的话,比较皮。皮!懂不?

思齐 发表于 2018-2-1 15:55:24

oooooooooooo
页: [1]
查看完整版本: 【PHP】fopen()的坑