Example #1
0
File: type.c Project: krakjoe/jitfu
PHP_METHOD(Type, dump) {
	zval *zoutput = NULL;
	php_jit_type_t *ptype;
	php_stream *pstream = NULL;

	JIT_WIN32_NOT_IMPLEMENTED();

	if (php_jit_parameters("|r", &zoutput) != SUCCESS) {
		php_jit_exception("unexpected parameters, expected ([resource output = STDOUT])");
		return;
	}

	ptype = PHP_JIT_FETCH_TYPE(getThis());
	
	if (!zoutput) {
		jit_dump_type(stdout, ptype->type);
		return;
	}
	
	php_stream_from_zval(pstream, zoutput);
	
	if (php_stream_can_cast(pstream, PHP_STREAM_AS_STDIO|PHP_STREAM_CAST_TRY_HARD) == SUCCESS) {
		FILE *stdio;
		if (php_stream_cast(pstream, PHP_STREAM_AS_STDIO, (void**)&stdio, 0) == SUCCESS) {
			jit_dump_type(stdio, ptype->type);
		}
	}
}
Example #2
0
int swoole_convert_to_fd(zval *zfd)
{
    php_stream *stream;
    int socket_fd;

#ifdef SWOOLE_SOCKETS_SUPPORT
    php_socket *php_sock;
#endif
    if (Z_TYPE_P(zfd) == IS_RESOURCE)
    {
        if (SW_ZEND_FETCH_RESOURCE_NO_RETURN(stream, php_stream *, &zfd, -1, NULL, php_file_le_stream()))
        {
            if (php_stream_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL, (void* )&socket_fd, 1) != SUCCESS || socket_fd < 0)
            {
                return SW_ERR;
            }
        }
        else
        {
#ifdef SWOOLE_SOCKETS_SUPPORT
            if (SW_ZEND_FETCH_RESOURCE_NO_RETURN(php_sock, php_socket *, &zfd, -1, NULL, php_sockets_le_socket()))
            {
                socket_fd = php_sock->bsd_socket;

            }
            else
            {
                swoole_php_fatal_error(E_WARNING, "fd argument must be either valid PHP stream or valid PHP socket resource");
                return SW_ERR;
            }
#else
            swoole_php_fatal_error(E_WARNING, "fd argument must be valid PHP stream resource");
            return SW_ERR;
#endif
        }
Example #3
0
/* Checks if the provides resource is a stream and if it provides a file descriptor */
static int php_posix_stream_get_fd(zval *zfp, int *fd) /* {{{ */
{
	php_stream *stream;

	php_stream_from_zval_no_verify(stream, zfp);

	if (stream == NULL) {
		php_error_docref(NULL, E_WARNING, "expects argument 1 to be a valid stream resource");
		return 0;
	}
	if (php_stream_can_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT) == SUCCESS) {
		php_stream_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT, (void*)fd, 0);
	} else if (php_stream_can_cast(stream, PHP_STREAM_AS_FD) == SUCCESS) {
		php_stream_cast(stream, PHP_STREAM_AS_FD, (void*)fd, 0);
	} else {
		php_error_docref(NULL, E_WARNING, "could not use stream of type '%s'",
				stream->ops->label);
		return 0;
	}
	return 1;
}
/**
 *  Get access to the internal filedescriptor
 *  Note that not every stream is always associated with a filedescriptor,
 *  in which case this function returns -1
 *  @return int
 */
int Stream::fd() const
{
    // the return value
    int retval = -1;
    
    // cast the stream to a filedescriptor, the cast-internal parameter is supposed to be to get
    // rid of warnings about buffered data (this code was copied from streamfuncs.c). We use
    // "FOR_SELECT" casting, as that is the most simple operations (without "FOR_SELECT" it flushes too)
    auto result = php_stream_cast(_stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL, (void **)&retval, 0);
    
    // on failure we return -1
    return result == SUCCESS ? retval : -1;
}
static inline long
hs_response_select(php_stream *stream, long timeout TSRMLS_DC)
{
    php_socket_t max_fd = 0;
    int retval, max_set_count = 0;
    struct timeval tv;
    struct timeval *tv_p = NULL;
    fd_set fds;

    FD_ZERO(&fds);

    if (php_stream_cast(stream,
                        PHP_STREAM_AS_FD_FOR_SELECT|PHP_STREAM_CAST_INTERNAL,
                        (void*)&max_fd, 1) == SUCCESS && max_fd != -1) {
        PHP_SAFE_FD_SET(max_fd, &fds);
        max_set_count++;
    }

    PHP_SAFE_MAX_FD(max_fd, max_set_count);

    if (timeout > 0) {
        tv.tv_sec = timeout;
        tv.tv_usec = 0;
        tv_p = &tv;
    }

    retval = php_select(max_fd+1, &fds, NULL, NULL, tv_p);
    if (retval == -1) {
        zend_error(E_WARNING, "[HandlerSocket] unable to select");
        return -1;
    }

    if (!PHP_SAFE_FD_ISSET(max_fd, &fds)) {
        return -1;
    }

    return 0;
}
Example #6
0
/* {{{ php_stream_cast */
PHPAPI int _php_stream_cast(php_stream *stream, int castas, void **ret, int show_err)
{
	int flags = castas & PHP_STREAM_CAST_MASK;
	castas &= ~PHP_STREAM_CAST_MASK;

	/* synchronize our buffer (if possible) */
	if (ret && castas != PHP_STREAM_AS_FD_FOR_SELECT) {
		php_stream_flush(stream);
		if (stream->ops->seek && (stream->flags & PHP_STREAM_FLAG_NO_SEEK) == 0) {
			zend_off_t dummy;

			stream->ops->seek(stream, stream->position, SEEK_SET, &dummy);
			stream->readpos = stream->writepos = 0;
		}
	}

	/* filtered streams can only be cast as stdio, and only when fopencookie is present */

	if (castas == PHP_STREAM_AS_STDIO) {
		if (stream->stdiocast) {
			if (ret) {
				*(FILE**)ret = stream->stdiocast;
			}
			goto exit_success;
		}

		/* if the stream is a stdio stream let's give it a chance to respond
		 * first, to avoid doubling up the layers of stdio with an fopencookie */
		if (php_stream_is(stream, PHP_STREAM_IS_STDIO) &&
			stream->ops->cast &&
			!php_stream_is_filtered(stream) &&
			stream->ops->cast(stream, castas, ret) == SUCCESS
		) {
			goto exit_success;
		}

#if HAVE_FOPENCOOKIE
		/* if just checking, say yes we can be a FILE*, but don't actually create it yet */
		if (ret == NULL) {
			goto exit_success;
		}

		{
			char fixed_mode[5];
			php_stream_mode_sanitize_fdopen_fopencookie(stream, fixed_mode);
			*(FILE**)ret = fopencookie(stream, fixed_mode, PHP_STREAM_COOKIE_FUNCTIONS);
		}

		if (*ret != NULL) {
			zend_off_t pos;

			stream->fclose_stdiocast = PHP_STREAM_FCLOSE_FOPENCOOKIE;

			/* If the stream position is not at the start, we need to force
			 * the stdio layer to believe it's real location. */
			pos = php_stream_tell(stream);
			if (pos > 0) {
				zend_fseek(*ret, pos, SEEK_SET);
			}

			goto exit_success;
		}

		/* must be either:
			a) programmer error
			b) no memory
			-> lets bail
		*/
		php_error_docref(NULL, E_ERROR, "fopencookie failed");
		return FAILURE;
#endif

		if (!php_stream_is_filtered(stream) && stream->ops->cast && stream->ops->cast(stream, castas, NULL) == SUCCESS) {
			if (FAILURE == stream->ops->cast(stream, castas, ret)) {
				return FAILURE;
			}
			goto exit_success;
		} else if (flags & PHP_STREAM_CAST_TRY_HARD) {
			php_stream *newstream;

			newstream = php_stream_fopen_tmpfile();
			if (newstream) {
				int retcopy = php_stream_copy_to_stream_ex(stream, newstream, PHP_STREAM_COPY_ALL, NULL);

				if (retcopy != SUCCESS) {
					php_stream_close(newstream);
				} else {
					int retcast = php_stream_cast(newstream, castas | flags, (void **)ret, show_err);

					if (retcast == SUCCESS) {
						rewind(*(FILE**)ret);
					}

					/* do some specialized cleanup */
					if ((flags & PHP_STREAM_CAST_RELEASE)) {
						php_stream_free(stream, PHP_STREAM_FREE_CLOSE_CASTED);
					}

					/* TODO: we probably should be setting .stdiocast and .fclose_stdiocast or
					 * we may be leaking the FILE*. Needs investigation, though. */
					return retcast;
				}
			}
		}
	}

	if (php_stream_is_filtered(stream)) {
		php_error_docref(NULL, E_WARNING, "cannot cast a filtered stream on this system");
		return FAILURE;
	} else if (stream->ops->cast && stream->ops->cast(stream, castas, ret) == SUCCESS) {
		goto exit_success;
	}

	if (show_err) {
		/* these names depend on the values of the PHP_STREAM_AS_XXX defines in php_streams.h */
		static const char *cast_names[4] = {
			"STDIO FILE*",
			"File Descriptor",
			"Socket Descriptor",
			"select()able descriptor"
		};

		php_error_docref(NULL, E_WARNING, "cannot represent a stream of type %s as a %s", stream->ops->label, cast_names[castas]);
	}

	return FAILURE;

exit_success:

	if ((stream->writepos - stream->readpos) > 0 &&
		stream->fclose_stdiocast != PHP_STREAM_FCLOSE_FOPENCOOKIE &&
		(flags & PHP_STREAM_CAST_INTERNAL) == 0
	) {
		/* the data we have buffered will be lost to the third party library that
		 * will be accessing the stream.  Emit a warning so that the end-user will
		 * know that they should try something else */

		php_error_docref(NULL, E_WARNING, ZEND_LONG_FMT " bytes of buffered data lost during stream conversion!", (zend_long)(stream->writepos - stream->readpos));
	}

	if (castas == PHP_STREAM_AS_STDIO && ret) {
		stream->stdiocast = *(FILE**)ret;
	}

	if (flags & PHP_STREAM_CAST_RELEASE) {
		php_stream_free(stream, PHP_STREAM_FREE_CLOSE_CASTED);
	}

	return SUCCESS;

}
Example #7
0
int php_yar_socket_send(yar_transport_interface_t* self, yar_request_t *request, char **msg) /* {{{ */ {
	fd_set rfds;
	zend_string *payload;
	struct timeval tv;
	int ret = -1, fd, retval;
	char buf[SEND_BUF_SIZE];
	yar_header_t header = {0};
	yar_socket_data_t *data = (yar_socket_data_t *)self->data;

	FD_ZERO(&rfds);
	if (SUCCESS == php_stream_cast(data->stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL, (void*)&fd, 1) && fd >= 0) {
		PHP_SAFE_FD_SET(fd, &rfds);
	} else {
		spprintf(msg, 0, "Unable cast socket fd form stream (%s)", strerror(errno));
		return 0;
	}

	if (!(payload = php_yar_request_pack(request, msg))) {
		return 0;
	}

	DEBUG_C(ZEND_ULONG_FMT": pack request by '%.*s', result len '%ld', content: '%.32s'", 
			request->id, 7, ZSTR_VAL(payload), ZSTR_LEN(payload), ZSTR_VAL(payload) + 8);

	/* for tcp/unix RPC, we need another way to supports auth */
	php_yar_protocol_render(&header, request->id, "Yar PHP Client", NULL, ZSTR_LEN(payload), data->persistent? YAR_PROTOCOL_PERSISTENT : 0);

	memcpy(buf, (char *)&header, sizeof(yar_header_t));

	tv.tv_sec = (ulong)(YAR_G(timeout) / 1000);
	tv.tv_usec = (ulong)((YAR_G(timeout) % 1000)? (YAR_G(timeout) & 1000) * 1000 : 0);

	retval = php_select(fd+1, NULL, &rfds, NULL, &tv);

	if (retval == -1) {
		zend_string_release(payload);
		spprintf(msg, 0, "select error '%s'", strerror(errno));
		return 0;
	} else if (retval == 0) {
		zend_string_release(payload);
		spprintf(msg, 0, "select timeout '%ld' seconds reached", YAR_G(timeout));
		return 0;
	}

	if (PHP_SAFE_FD_ISSET(fd, &rfds)) {
		size_t bytes_left = 0, bytes_sent = 0;

		if (ZSTR_LEN(payload) > (sizeof(buf) - sizeof(yar_header_t))) {
			memcpy(buf + sizeof(yar_header_t), ZSTR_VAL(payload), sizeof(buf) - sizeof(yar_header_t));
			if ((ret = php_stream_xport_sendto(data->stream, buf, sizeof(buf), 0, NULL, 0)) < 0) {
				zend_string_release(payload);
				spprintf(msg, 0, "unable to send data");
				return 0;
			}
		} else {
			memcpy(buf + sizeof(yar_header_t), ZSTR_VAL(payload), ZSTR_LEN(payload));
			if ((ret = php_stream_xport_sendto(data->stream, buf, sizeof(yar_header_t) + ZSTR_LEN(payload), 0, NULL, 0)) < 0) {
				zend_string_release(payload);
				spprintf(msg, 0, "unable to send data");
				return 0;
			}
		}

		bytes_sent = ret - sizeof(yar_header_t);
		bytes_left = ZSTR_LEN(payload) - bytes_sent;

wait_io:
		if (bytes_left) {
			retval = php_select(fd+1, NULL, &rfds, NULL, &tv);

			if (retval == -1) {
				zend_string_release(payload);
				spprintf(msg, 0, "select error '%s'", strerror(errno));
				return 0;
			} else if (retval == 0) {
				zend_string_release(payload);
				spprintf(msg, 0, "select timeout %ldms reached", YAR_G(timeout));
				return 0;
			}

			if (PHP_SAFE_FD_ISSET(fd, &rfds)) {
				if ((ret = php_stream_xport_sendto(data->stream, ZSTR_VAL(payload) + bytes_sent, bytes_left, 0, NULL, 0)) > 0) {
					bytes_left -= ret;
					bytes_sent += ret;
				}
			}
			goto wait_io;
		}
	}

	zend_string_release(payload);

	return ret < 0? 0 : 1;
} /* }}} */
Example #8
0
yar_response_t * php_yar_socket_exec(yar_transport_interface_t* self, yar_request_t *request) /* {{{ */ {
	fd_set rfds;
	struct timeval tv;
	yar_header_t *header;
	yar_response_t *response;
	int fd, retval, recvd;
   	size_t len = 0, total_recvd = 0;
	char *msg, buf[RECV_BUF_SIZE], *payload = NULL;
	yar_socket_data_t *data = (yar_socket_data_t *)self->data;

	response = ecalloc(1, sizeof(yar_response_t));

	FD_ZERO(&rfds);
	if (SUCCESS == php_stream_cast(data->stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL, (void*)&fd, 1) && fd >= 0) {
		PHP_SAFE_FD_SET(fd, &rfds);
	} else {
		len = snprintf(buf, sizeof(buf), "Unable cast socket fd form stream (%s)", strerror(errno));
		php_yar_response_set_error(response, YAR_ERR_TRANSPORT, buf, len);
		return response;
	}

	tv.tv_sec = (ulong)(YAR_G(timeout) / 1000);
	tv.tv_usec = (ulong)((YAR_G(timeout) % 1000)? (YAR_G(timeout) & 1000) * 1000 : 0);

wait_io:
	retval = php_select(fd+1, &rfds, NULL, NULL, &tv);

	if (retval == -1) {
		len = snprintf(buf, sizeof(buf), "Unable to select %d '%s'", fd, strerror(errno));
		php_yar_response_set_error(response, YAR_ERR_TRANSPORT, buf, len);
		return response;
	} else if (retval == 0) {
		len = snprintf(buf, sizeof(buf), "select timeout %ldms reached", YAR_G(timeout));
		php_yar_response_set_error(response, YAR_ERR_TRANSPORT, buf, len);
		return response;
	}

	if (PHP_SAFE_FD_ISSET(fd, &rfds)) {
		zval *retval, rret;
		if (!payload) {
			if ((recvd = php_stream_xport_recvfrom(data->stream, buf, sizeof(buf), 0, NULL, NULL, NULL)) > 0) {
				if (!(header = php_yar_protocol_parse(buf))) {
					php_yar_error(response, YAR_ERR_PROTOCOL, "malformed response header '%.32s'", payload);
					return response;
				}

				payload = emalloc(header->body_len);
				len = header->body_len;
				total_recvd  = recvd - sizeof(yar_header_t);

				memcpy(payload, buf + sizeof(yar_header_t), total_recvd);

				if (recvd < (sizeof(yar_header_t) + len)) {
					goto wait_io;	
				}
			} else if (recvd < 0) {
				/* this should never happen */
				goto wait_io;
			}
		} else {
			if ((recvd = php_stream_xport_recvfrom(data->stream, payload + total_recvd, len - total_recvd, 0, NULL, NULL, NULL)) > 0) {
				total_recvd += recvd;
			}

			if (total_recvd < len) {
				goto wait_io;
			}
		}

		if (len) {
			if (!(retval = php_yar_packager_unpack(payload, len, &msg, &rret))) {
				php_yar_response_set_error(response, YAR_ERR_PACKAGER, msg, strlen(msg));
				efree(msg);
				return response;
			}

			php_yar_response_map_retval(response, retval);

			DEBUG_C(ZEND_ULONG_FMT": server response content packaged by '%.*s', len '%ld', content '%.32s'",
					response->id, 7, payload, header->body_len, payload + 8);

			efree(payload);
			zval_ptr_dtor(retval);
		} else {
			php_yar_response_set_error(response, YAR_ERR_EMPTY_RESPONSE, ZEND_STRL("empty response"));
		}
		return response;
	} else {
		goto wait_io;
	}
} /* }}} */
Example #9
0
File: dba.c Project: Jille/php-src
/* {{{ php_dba_open
 */
static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, int persistent)
{
	zval *args = NULL;
	int ac = ZEND_NUM_ARGS();
	dba_mode_t modenr;
	dba_info *info, *other;
	dba_handler *hptr;
	char *key = NULL, *error = NULL;
	int keylen = 0;
	int i;
	int lock_mode, lock_flag, lock_dbf = 0;
	char *file_mode;
	char mode[4], *pmode, *lock_file_mode = NULL;
	int persistent_flag = persistent ? STREAM_OPEN_PERSISTENT : 0;
	zend_string *opened_path = NULL;
	char *lock_name;

	if (ac < 2) {
		WRONG_PARAM_COUNT;
	}

	/* we pass additional args to the respective handler */
	args = safe_emalloc(ac, sizeof(zval), 0);
	if (zend_get_parameters_array_ex(ac, args) != SUCCESS) {
		efree(args);
		WRONG_PARAM_COUNT;
	}

	/* we only take string arguments */
	for (i = 0; i < ac; i++) {
		if (Z_TYPE(args[i]) != IS_STRING) {
			convert_to_string_ex(&args[i]);
		} else if (Z_REFCOUNTED(args[i])) {
			Z_ADDREF(args[i]);
		}
		keylen += Z_STRLEN(args[i]);
	}

	if (persistent) {
		zend_resource *le;

		/* calculate hash */
		key = safe_emalloc(keylen, 1, 1);
		key[keylen] = '\0';
		keylen = 0;

		for(i = 0; i < ac; i++) {
			memcpy(key+keylen, Z_STRVAL(args[i]), Z_STRLEN(args[i]));
			keylen += Z_STRLEN(args[i]);
		}

		/* try to find if we already have this link in our persistent list */
		if ((le = zend_hash_str_find_ptr(&EG(persistent_list), key, keylen)) != NULL) {
			FREENOW;

			if (le->type != le_pdb) {
				RETURN_FALSE;
			}

			info = (dba_info *)le->ptr;

			GC_REFCOUNT(le)++;
			RETURN_RES(le);
			return;
		}
	}

	if (ac==2) {
		hptr = DBA_G(default_hptr);
		if (!hptr) {
			php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_WARNING, "No default handler selected");
			FREENOW;
			RETURN_FALSE;
		}
	} else {
		for (hptr = handler; hptr->name && strcasecmp(hptr->name, Z_STRVAL(args[2])); hptr++);
	}

	if (!hptr->name) {
		php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_WARNING, "No such handler: %s", Z_STRVAL(args[2]));
		FREENOW;
		RETURN_FALSE;
	}

	/* Check mode: [rwnc][fl]?t?
	 * r: Read
	 * w: Write
	 * n: Create/Truncate
	 * c: Create
	 *
	 * d: force lock on database file
	 * l: force lock on lck file
	 * -: ignore locking
	 *
	 * t: test open database, warning if locked
	 */
	strlcpy(mode, Z_STRVAL(args[1]), sizeof(mode));
	pmode = &mode[0];
	if (pmode[0] && (pmode[1]=='d' || pmode[1]=='l' || pmode[1]=='-')) { /* force lock on db file or lck file or disable locking */
		switch (pmode[1]) {
		case 'd':
			lock_dbf = 1;
			if ((hptr->flags & DBA_LOCK_ALL) == 0) {
				lock_flag = (hptr->flags & DBA_LOCK_ALL);
				break;
			}
			/* no break */
		case 'l':
			lock_flag = DBA_LOCK_ALL;
			if ((hptr->flags & DBA_LOCK_ALL) == 0) {
				php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_NOTICE, "Handler %s does locking internally", hptr->name);
			}
			break;
		default:
		case '-':
			if ((hptr->flags & DBA_LOCK_ALL) == 0) {
				php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_WARNING, "Locking cannot be disabled for handler %s", hptr->name);
				FREENOW;
				RETURN_FALSE;
			}
			lock_flag = 0;
			break;
		}
	} else {
		lock_flag = (hptr->flags&DBA_LOCK_ALL);
		lock_dbf = 1;
	}
	switch (*pmode++) {
		case 'r':
			modenr = DBA_READER;
			lock_mode = (lock_flag & DBA_LOCK_READER) ? LOCK_SH : 0;
			file_mode = "r";
			break;
		case 'w':
			modenr = DBA_WRITER;
			lock_mode = (lock_flag & DBA_LOCK_WRITER) ? LOCK_EX : 0;
			file_mode = "r+b";
			break;
		case 'c':
			modenr = DBA_CREAT;
			lock_mode = (lock_flag & DBA_LOCK_CREAT) ? LOCK_EX : 0;
			if (lock_mode) {
				if (lock_dbf) {
					/* the create/append check will be done on the lock
					 * when the lib opens the file it is already created
					 */
					file_mode = "r+b";       /* read & write, seek 0 */
					lock_file_mode = "a+b";  /* append */
				} else {
					file_mode = "a+b";       /* append */
					lock_file_mode = "w+b";  /* create/truncate */
				}
			} else {
				file_mode = "a+b";
			}
			/* In case of the 'a+b' append mode, the handler is responsible
			 * to handle any rewind problems (see flatfile handler).
			 */
			break;
		case 'n':
			modenr = DBA_TRUNC;
			lock_mode = (lock_flag & DBA_LOCK_TRUNC) ? LOCK_EX : 0;
			file_mode = "w+b";
			break;
		default:
			php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_WARNING, "Illegal DBA mode");
			FREENOW;
			RETURN_FALSE;
	}
	if (!lock_file_mode) {
		lock_file_mode = file_mode;
	}
	if (*pmode=='d' || *pmode=='l' || *pmode=='-') {
		pmode++; /* done already - skip here */
	}
	if (*pmode=='t') {
		pmode++;
		if (!lock_flag) {
			php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_WARNING, "You cannot combine modifiers - (no lock) and t (test lock)");
			FREENOW;
			RETURN_FALSE;
		}
		if (!lock_mode) {
			if ((hptr->flags & DBA_LOCK_ALL) == 0) {
				php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_WARNING, "Handler %s uses its own locking which doesn't support mode modifier t (test lock)", hptr->name);
				FREENOW;
				RETURN_FALSE;
			} else {
				php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_WARNING, "Handler %s doesn't uses locking for this mode which makes modifier t (test lock) obsolete", hptr->name);
				FREENOW;
				RETURN_FALSE;
			}
		} else {
			lock_mode |= LOCK_NB; /* test =: non blocking */
		}
	}
	if (*pmode) {
		php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_WARNING, "Illegal DBA mode");
		FREENOW;
		RETURN_FALSE;
	}

	info = pemalloc(sizeof(dba_info), persistent);
	memset(info, 0, sizeof(dba_info));
	info->path = pestrdup(Z_STRVAL(args[0]), persistent);
	info->mode = modenr;
	info->argc = ac - 3;
	info->argv = args + 3;
	info->flags = (hptr->flags & ~DBA_LOCK_ALL) | (lock_flag & DBA_LOCK_ALL) | (persistent ? DBA_PERSISTENT : 0);
	info->lock.mode = lock_mode;

	/* if any open call is a locking call:
	 * check if we already habe a locking call open that should block this call
	 * the problem is some systems would allow read during write
	 */
	if (hptr->flags & DBA_LOCK_ALL) {
		if ((other = php_dba_find(info->path)) != NULL) {
			if (   ( (lock_mode&LOCK_EX)        && (other->lock.mode&(LOCK_EX|LOCK_SH)) )
			    || ( (other->lock.mode&LOCK_EX) && (lock_mode&(LOCK_EX|LOCK_SH))        )
			   ) {
				error = "Unable to establish lock (database file already open)"; /* force failure exit */
			}
		}
	}

	if (!error && lock_mode) {
		if (lock_dbf) {
			lock_name = Z_STRVAL(args[0]);
		} else {
			spprintf(&lock_name, 0, "%s.lck", info->path);
			if (!strcmp(file_mode, "r")) {
				/* when in read only mode try to use existing .lck file first */
				/* do not log errors for .lck file while in read ony mode on .lck file */
				lock_file_mode = "rb";
				info->lock.fp = php_stream_open_wrapper(lock_name, lock_file_mode, STREAM_MUST_SEEK|IGNORE_PATH|persistent_flag, &opened_path);
			}
			if (!info->lock.fp) {
				/* when not in read mode or failed to open .lck file read only. now try again in create(write) mode and log errors */
				lock_file_mode = "a+b";
			} else {
				if (opened_path) {
					info->lock.name = pestrndup(opened_path->val, opened_path->len, persistent);
					zend_string_release(opened_path);
				}
			}
		}
		if (!info->lock.fp) {
			info->lock.fp = php_stream_open_wrapper(lock_name, lock_file_mode, STREAM_MUST_SEEK|REPORT_ERRORS|IGNORE_PATH|persistent_flag, &opened_path);
			if (info->lock.fp) {
				if (lock_dbf) {
					/* replace the path info with the real path of the opened file */
					pefree(info->path, persistent);
					info->path = pestrndup(opened_path->val, opened_path->len, persistent);
				}
				/* now store the name of the lock */
				info->lock.name = pestrndup(opened_path->val, opened_path->len, persistent);
				zend_string_release(opened_path);
			}
		}
		if (!lock_dbf) {
			efree(lock_name);
		}
		if (!info->lock.fp) {
			dba_close(info);
			/* stream operation already wrote an error message */
			FREENOW;
			RETURN_FALSE;
		}
		if (!php_stream_supports_lock(info->lock.fp)) {
			error = "Stream does not support locking";
		}
		if (php_stream_lock(info->lock.fp, lock_mode)) {
			error = "Unable to establish lock"; /* force failure exit */
		}
	}

	/* centralised open stream for builtin */
	if (!error && (hptr->flags&DBA_STREAM_OPEN)==DBA_STREAM_OPEN) {
		if (info->lock.fp && lock_dbf) {
			info->fp = info->lock.fp; /* use the same stream for locking and database access */
		} else {
			info->fp = php_stream_open_wrapper(info->path, file_mode, STREAM_MUST_SEEK|REPORT_ERRORS|IGNORE_PATH|persistent_flag, NULL);
		}
		if (!info->fp) {
			dba_close(info);
			/* stream operation already wrote an error message */
			FREENOW;
			RETURN_FALSE;
		}
		if (hptr->flags & (DBA_NO_APPEND|DBA_CAST_AS_FD)) {
			/* Needed because some systems do not allow to write to the original
			 * file contents with O_APPEND being set.
			 */
			if (SUCCESS != php_stream_cast(info->fp, PHP_STREAM_AS_FD, (void*)&info->fd, 1)) {
				php_error_docref(NULL, E_WARNING, "Could not cast stream");
				dba_close(info);
				FREENOW;
				RETURN_FALSE;
#ifdef F_SETFL
			} else if (modenr == DBA_CREAT) {
				int flags = fcntl(info->fd, F_SETFL);
				fcntl(info->fd, F_SETFL, flags & ~O_APPEND);
#endif
			}

		}
	}

	if (error || hptr->open(info, &error) != SUCCESS) {
		dba_close(info);
		php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_WARNING, "Driver initialization failed for handler: %s%s%s", hptr->name, error?": ":"", error?error:"");
		FREENOW;
		RETURN_FALSE;
	}

	info->hnd = hptr;
	info->argc = 0;
	info->argv = NULL;

	if (persistent) {
		zend_resource new_le;

		new_le.type = le_pdb;
		new_le.ptr = info;
		if (zend_hash_str_update_mem(&EG(persistent_list), key, keylen, &new_le, sizeof(zend_resource)) == NULL) {
			dba_close(info);
			php_error_docref2(NULL, Z_STRVAL(args[0]), Z_STRVAL(args[1]), E_WARNING, "Could not register persistent resource");
			FREENOW;
			RETURN_FALSE;
		}
	}

	RETVAL_RES(zend_register_resource(info, (persistent ? le_pdb : le_db)));
	FREENOW;
}
Example #10
0
int php_imagick_read_image_using_php_streams(php_imagick_object *intern, int type, char *filename, int filename_len TSRMLS_DC)
{
	php_stream *stream;
	MagickBooleanType status;
	FILE *fp;
#if ZEND_MODULE_API_NO > 20060613 
	zend_error_handling error_handling;
#endif
	
#if ZEND_MODULE_API_NO > 20060613 
	zend_replace_error_handling(EH_THROW, php_imagick_exception_class_entry, &error_handling TSRMLS_CC);
#else
	php_set_error_handling(EH_THROW, php_imagick_exception_class_entry TSRMLS_CC);
#endif
	
	stream = php_stream_open_wrapper(filename, "rb", (ENFORCE_SAFE_MODE|IGNORE_PATH) & ~REPORT_ERRORS, NULL);

	if (!stream) {
		goto return_error;
	}
	
	if (php_stream_can_cast(stream, PHP_STREAM_AS_STDIO|PHP_STREAM_CAST_INTERNAL) == FAILURE) {
		goto return_error;
	}

	if (php_stream_cast(stream, PHP_STREAM_AS_STDIO|PHP_STREAM_CAST_INTERNAL, (void*)&fp, 0) == FAILURE) {
		goto return_error;
	}
	
#if ZEND_MODULE_API_NO > 20060613 
	zend_restore_error_handling(&error_handling TSRMLS_CC);
#else
	php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
#endif

	if (type == 1) {
		status = MagickReadImageFile(intern->magick_wand, fp);
	} else {
		status = MagickPingImageFile(intern->magick_wand, fp);
	}
	
	if (status == MagickFalse) {
		php_stream_close(stream);
		return IMAGICK_READ_WRITE_UNDERLYING_LIBRARY;
	}
	
	if (php_stream_is(stream, PHP_STREAM_IS_STDIO)) {
		char *absolute = expand_filepath(filename, NULL TSRMLS_CC);
		MagickSetImageFilename(intern->magick_wand, absolute);
		efree(absolute);
	} else {
		/* Set to empty filename, otherwise it will point to MAGICK_TEMP/magick-XXXXX */
		MagickSetImageFilename(intern->magick_wand, "");
	}
	php_stream_close(stream);

	if (status == MagickFalse) {
		return IMAGICK_READ_WRITE_UNDERLYING_LIBRARY;
	}
	
	IMAGICK_CORRECT_ITERATOR_POSITION(intern);
	return IMAGICK_READ_WRITE_NO_ERROR;
	
return_error:
#if ZEND_MODULE_API_NO > 20060613 
	zend_restore_error_handling(&error_handling TSRMLS_CC);
#else
	php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
#endif
	if (stream) php_stream_close(stream);
	return IMAGICK_READ_WRITE_UNDERLYING_LIBRARY;
}