/* {{{ flatfile_store */ int flatfile_store(flatfile *dba, datum key_datum, datum value_datum, int mode TSRMLS_DC) { if (mode == FLATFILE_INSERT) { if (flatfile_findkey(dba, key_datum TSRMLS_CC)) { return 1; } php_stream_seek(dba->fp, 0L, SEEK_END); php_stream_printf(dba->fp TSRMLS_CC, "%zu\n", key_datum.dsize); php_stream_flush(dba->fp); if (php_stream_write(dba->fp, key_datum.dptr, key_datum.dsize) < key_datum.dsize) { return -1; } php_stream_printf(dba->fp TSRMLS_CC, "%zu\n", value_datum.dsize); php_stream_flush(dba->fp); if (php_stream_write(dba->fp, value_datum.dptr, value_datum.dsize) < value_datum.dsize) { return -1; } } else { /* FLATFILE_REPLACE */ flatfile_delete(dba, key_datum TSRMLS_CC); php_stream_printf(dba->fp TSRMLS_CC, "%zu\n", key_datum.dsize); php_stream_flush(dba->fp); if (php_stream_write(dba->fp, key_datum.dptr, key_datum.dsize) < key_datum.dsize) { return -1; } php_stream_printf(dba->fp TSRMLS_CC, "%zu\n", value_datum.dsize); if (php_stream_write(dba->fp, value_datum.dptr, value_datum.dsize) < value_datum.dsize) { return -1; } } php_stream_flush(dba->fp); return 0; }
/* {{{ inifile_find_group * if found pos_grp_start points to "[group_name]" */ static int inifile_find_group(inifile *dba, const key_type *key, size_t *pos_grp_start) { int ret = FAILURE; php_stream_flush(dba->fp); php_stream_seek(dba->fp, 0, SEEK_SET); inifile_line_free(&dba->curr); inifile_line_free(&dba->next); if (key->group && strlen(key->group)) { int res; line_type ln = {{NULL,NULL},{NULL}}; res = 1; while(inifile_read(dba, &ln)) { if ((res=inifile_key_cmp(&ln.key, key)) < 2) { ret = SUCCESS; break; } *pos_grp_start = php_stream_tell(dba->fp); } inifile_line_free(&ln); } else { *pos_grp_start = 0; ret = SUCCESS; } if (ret == FAILURE) { *pos_grp_start = php_stream_tell(dba->fp); } return ret; }
static HRESULT STDMETHODCALLTYPE stm_commit(IStream *This, DWORD grfCommitFlags) { FETCH_STM(); php_stream_flush(stm->stream); return S_OK; }
/* {{{ flatfile_delete */ int flatfile_delete(flatfile *dba, datum key_datum TSRMLS_DC) { char *key = key_datum.dptr; size_t size = key_datum.dsize; size_t buf_size = FLATFILE_BLOCK_SIZE; char *buf = emalloc(buf_size); size_t num; size_t pos; php_stream_rewind(dba->fp); while(!php_stream_eof(dba->fp)) { /* read in the length of the key name */ if (!php_stream_gets(dba->fp, buf, 15)) { break; } num = atoi(buf); if (num >= buf_size) { buf_size = num + FLATFILE_BLOCK_SIZE; buf = erealloc(buf, buf_size); } pos = php_stream_tell(dba->fp); /* read in the key name */ num = php_stream_read(dba->fp, buf, num); if (num < 0) { break; } if (size == num && !memcmp(buf, key, size)) { php_stream_seek(dba->fp, pos, SEEK_SET); php_stream_putc(dba->fp, 0); php_stream_flush(dba->fp); php_stream_seek(dba->fp, 0L, SEEK_END); efree(buf); return SUCCESS; } /* read in the length of the value */ if (!php_stream_gets(dba->fp, buf, 15)) { break; } num = atoi(buf); if (num >= buf_size) { buf_size = num + FLATFILE_BLOCK_SIZE; buf = erealloc(buf, buf_size); } /* read in the value */ num = php_stream_read(dba->fp, buf, num); if (num < 0) { break; } } efree(buf); return FAILURE; }
/* {{{ 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; }
/* {{{ inifile_delete_replace_append */ static int inifile_delete_replace_append(inifile *dba, const key_type *key, const val_type *value, int append, zend_bool *found) { size_t pos_grp_start=0, pos_grp_next; inifile *ini_tmp = NULL; php_stream *fp_tmp = NULL; int ret; /* 1) Search group start * 2) Search next group * 3) If not append: Copy group to ini_tmp * 4) Open temp_stream and copy remainder * 5) Truncate stream * 6) If not append AND key.name given: Filtered copy back from ini_tmp * to stream. Otherwise the user wanted to delete the group. * 7) Append value if given * 8) Append temporary stream */ assert(!append || (key->name && value)); /* missuse */ /* 1 - 3 */ inifile_find_group(dba, key, &pos_grp_start); inifile_next_group(dba, key, &pos_grp_next); if (append) { ret = SUCCESS; } else { ret = inifile_copy_to(dba, pos_grp_start, pos_grp_next, &ini_tmp); } /* 4 */ if (ret == SUCCESS) { fp_tmp = php_stream_temp_create(0, 64 * 1024); if (!fp_tmp) { php_error_docref(NULL, E_WARNING, "Could not create temporary stream"); ret = FAILURE; } else { php_stream_seek(dba->fp, 0, SEEK_END); if (pos_grp_next != (size_t)php_stream_tell(dba->fp)) { php_stream_seek(dba->fp, pos_grp_next, SEEK_SET); if (SUCCESS != php_stream_copy_to_stream_ex(dba->fp, fp_tmp, PHP_STREAM_COPY_ALL, NULL)) { php_error_docref(NULL, E_WARNING, "Could not copy remainder to temporary stream"); ret = FAILURE; } } } } /* 5 */ if (ret == SUCCESS) { if (!value || (key->name && strlen(key->name))) { ret = inifile_truncate(dba, append ? pos_grp_next : pos_grp_start); /* writes error on fail */ } } if (ret == SUCCESS) { if (key->name && strlen(key->name)) { /* 6 */ if (!append && ini_tmp) { ret = inifile_filter(dba, ini_tmp, key, found); } /* 7 */ /* important: do not query ret==SUCCESS again: inifile_filter might fail but * however next operation must be done. */ if (value) { if (pos_grp_start == pos_grp_next && key->group && strlen(key->group)) { php_stream_printf(dba->fp, "[%s]\n", key->group); } php_stream_printf(dba->fp, "%s=%s\n", key->name, value->value ? value->value : ""); } } /* 8 */ /* important: do not query ret==SUCCESS again: inifile_filter might fail but * however next operation must be done. */ if (fp_tmp && php_stream_tell(fp_tmp)) { php_stream_seek(fp_tmp, 0, SEEK_SET); php_stream_seek(dba->fp, 0, SEEK_END); if (SUCCESS != php_stream_copy_to_stream_ex(fp_tmp, dba->fp, PHP_STREAM_COPY_ALL, NULL)) { zend_throw_error(NULL, "Could not copy from temporary stream - ini file truncated"); ret = FAILURE; } } } if (ini_tmp) { php_stream_close(ini_tmp->fp); inifile_free(ini_tmp, 0); } if (fp_tmp) { php_stream_close(fp_tmp); } php_stream_flush(dba->fp); php_stream_seek(dba->fp, 0, SEEK_SET); return ret; }