Mam jakiś strumień "stream" z funkcji wrapper->wops->stream_opener (stream=wrapper->wops->stream_opener(argumenty)).
Jak pobrać wielkość pliku?

Mój obecny kod (main/streams/streams.c w funkcji php_stream_open_wrapper_ex):

	/* START max file size mod */
	int size     =   CO TU WPISAĆ?
	int max_size =    PG(upload_max_filesize);
	if (size > max_size && (options & REPORT_ERRORS)) {
		php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to open stream: max file size is 3MB");
		if (opened_path && *opened_path) {
			efree(*opened_path);
			*opened_path = NULL;
		}
		return false;
	}
	/* END max file size mod */

Cały kod funkcji php_stream_open_wrapper_ex:

/* {{{ php_stream_open_wrapper_ex */
PHPAPI php_stream *_php_stream_open_wrapper_ex(char *path, char *mode, int options,
		char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC)
{
	php_stream *stream = NULL;
	php_stream_wrapper *wrapper = NULL;
	char *path_to_open;
	int persistent = options & STREAM_OPEN_PERSISTENT;
	char *resolved_path = NULL;
	char *copy_of_path = NULL;

	
	if (opened_path) {
		*opened_path = NULL;
	}

	if (!path || !*path) {
		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Filename cannot be empty");
		return NULL;
	}

	if (options & USE_PATH) {
		resolved_path = zend_resolve_path(path, strlen(path) TSRMLS_CC);
		if (resolved_path) {
			path = resolved_path;
			/* we've found this file, don't re-check include_path or run realpath */
			options |= STREAM_ASSUME_REALPATH;
			options &= ~USE_PATH;
		}
	}

	path_to_open = path;

	wrapper = php_stream_locate_url_wrapper(path, &path_to_open, options TSRMLS_CC);
	if (options & STREAM_USE_URL && (!wrapper || !wrapper->is_url)) {
		php_error_docref(NULL TSRMLS_CC, E_WARNING, "This function may only be used against URLs");
		if (resolved_path) {
			efree(resolved_path);
		}
		return NULL;
	}

	if (wrapper) {
		if (!wrapper->wops->stream_opener) {
			php_stream_wrapper_log_error(wrapper, options ^ REPORT_ERRORS TSRMLS_CC,
					"wrapper does not support stream open");
		} else {
			/* refcount++ to make sure the context doesn't get destroyed 
			 * if open() fails and stream is closed */
			if (context) {
				zend_list_addref(context->rsrc_id);
			}

			stream = wrapper->wops->stream_opener(wrapper,
				path_to_open, mode, options ^ REPORT_ERRORS,
				opened_path, context STREAMS_REL_CC TSRMLS_CC);

			/* if open() succeeded and context was not used, do refcount-- 
			 * XXX if a wrapper didn't actually use context (no way to know that) 
			 * and open() failed, refcount will stay increased */
			if (context && stream && !stream->context) {
				zend_list_delete(context->rsrc_id);
			}
		}

		/* if the caller asked for a persistent stream but the wrapper did not
		 * return one, force an error here */
		if (stream && (options & STREAM_OPEN_PERSISTENT) && !stream->is_persistent) {
			php_stream_wrapper_log_error(wrapper, options ^ REPORT_ERRORS TSRMLS_CC,
					"wrapper does not support persistent streams");
			php_stream_close(stream);
			stream = NULL;
		}
		
		if (stream) {
			stream->wrapper = wrapper;
		}
	}

	if (stream) {
		if (opened_path && !*opened_path && resolved_path) {
			*opened_path = resolved_path;
			resolved_path = NULL;
		}
		if (stream->orig_path) {
			pefree(stream->orig_path, persistent);
		}
		copy_of_path = pestrdup(path, persistent);
		stream->orig_path = copy_of_path;
#if ZEND_DEBUG
		stream->open_filename = __zend_orig_filename ? __zend_orig_filename : __zend_filename;
		stream->open_lineno = __zend_orig_lineno ? __zend_orig_lineno : __zend_lineno;
#endif
	}

	if (stream != NULL && (options & STREAM_MUST_SEEK)) {
		php_stream *newstream;

		switch(php_stream_make_seekable_rel(stream, &newstream,
					(options & STREAM_WILL_CAST)
						? PHP_STREAM_PREFER_STDIO : PHP_STREAM_NO_PREFERENCE)) {
			case PHP_STREAM_UNCHANGED:
				if (resolved_path) {
					efree(resolved_path);
				}
				return stream;
			case PHP_STREAM_RELEASED:
				if (newstream->orig_path) {
					pefree(newstream->orig_path, persistent);
				}
				newstream->orig_path = pestrdup(path, persistent);
				if (resolved_path) {
					efree(resolved_path);
				}
				return newstream;
			default:
				php_stream_close(stream);
				stream = NULL;
				if (options & REPORT_ERRORS) {
					char *tmp = estrdup(path);
					php_strip_url_passwd(tmp);
					php_error_docref1(NULL TSRMLS_CC, tmp, E_WARNING, "could not make seekable - %s",
							tmp);
					efree(tmp);

					options ^= REPORT_ERRORS;
				}
		}
	}

	if (stream && stream->ops->seek && (stream->flags & PHP_STREAM_FLAG_NO_SEEK) == 0 && strchr(mode, 'a') && stream->position == 0) {
		off_t newpos = 0;

		/* if opened for append, we need to revise our idea of the initial file position */
		if (0 == stream->ops->seek(stream, 0, SEEK_CUR, &newpos TSRMLS_CC)) {
			stream->position = newpos;
		}
	}

	if (stream == NULL && (options & REPORT_ERRORS)) {
		php_stream_display_wrapper_errors(wrapper, path, "failed to open stream" TSRMLS_CC);
		if (opened_path && *opened_path) {
			efree(*opened_path);
			*opened_path = NULL;
		}
	}
	
	/* START max file size mod */
	int size     =   CO TU WPISAĆ?
	int max_size =    PG(upload_max_filesize);
	if (size > max_size && (options & REPORT_ERRORS)) {
		php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to open stream: max file size is 3MB");
		if (opened_path && *opened_path) {
			efree(*opened_path);
			*opened_path = NULL;
		}
		return false;
	}
	/* END max file size mod */

	
	php_stream_tidy_wrapper_error_log(wrapper TSRMLS_CC);
#if ZEND_DEBUG
	if (stream == NULL && copy_of_path != NULL) {
		pefree(copy_of_path, persistent);
	}
#endif
	if (resolved_path) {
		efree(resolved_path);
	}
	return stream;
}
/* }}} */

Kod całej aplikacji: http://pl.php.net/get/php-5.3.0.tar.bz2/from/this/mirror (nie modyfikowałem innych plików).

PS: Pierwszy raz robię coś w C.