Example #1
0
/* This function is exactly like filter_read, except the fact that we can't
   use tmpfile () all the time. That's why we open the real file when there
   is no last filter. */
static cdk_error_t
stream_filter_write (cdk_stream_t s)
{
    struct stream_filter_s *f;
    cdk_error_t rc = 0;

    assert (s);

    if (s->flags.filtrated)
    {
        gnutls_assert ();
        return CDK_Inv_Value;
    }

    for (f = s->filters; f; f = f->next)
    {
        if (!f->flags.enabled)
            continue;
        /* if there is no next filter, create the final output file */
        _cdk_log_debug ("filter [write]: last filter=%d fname=%s\n",
                        f->next ? 1 : 0, s->fname);
        if (!f->next && s->fname)
            f->tmp = fopen (s->fname, "w+b");
        else
            f->tmp = _cdk_tmpfile ();
        if (!f->tmp)
        {
            rc = CDK_File_Error;
            break;
        }
        /* If there is no next filter, flush the cache. We also do this
           when the next filter is the armor filter because this filter
           is special and before it starts, all data should be written. */
        if ((!f->next || f->next->type == fARMOR) && s->cache.size)
        {
            rc = stream_cache_flush (s, f->tmp);
            if (rc)
                break;
        }
        rc = f->fnct (f->opaque, f->ctl, s->fp, f->tmp);
        _cdk_log_debug ("filter [write]: type=%d rc=%d\n", f->type, rc);
        if (!rc)
            rc = stream_fp_replace (s, &f->tmp);
        if (!rc)
            rc = cdk_stream_seek (s, 0);
        if (rc)
        {
            _cdk_log_debug ("filter [close]: fd=%d\n", fileno (f->tmp));
            fclose (f->tmp);
            break;
        }
    }
    return rc;
}
Example #2
0
/* Here all data from the file handle is passed through all filters.
   The scheme works like this:
   Create a tempfile and use it for the output of the filter. Then the
   original file handle will be closed and replace with the temp handle.
   The file pointer will be set to the begin and the game starts again. */
static int
stream_filter_read( cdk_stream_t s )
{
    struct stream_filter_s * f;
    int rc = 0;

    assert( s );
    
    if( s->flags.filtrated )
        return 0;

    for( f = s->filters; f; f = f->next ) {
        if( !f->flags.enabled )
            continue;
        f->tmp = tmpfile( );
        if( !f->tmp ) {
            rc = CDK_File_Error;
            break;
        }
        rc = f->fnct( f->opaque, f->ctl, s->fp, f->tmp );
        _cdk_log_debug( "filter %s [read]: type=%d rc=%d\n",
                        s->fname? s->fname : "[temp]", f->type, rc );
        if( rc )
            break;
      
        /* if the filter is read-only, do not replace the FP because
           the contents were not altered in any way. */
        if( !f->flags.rdonly ) {
            rc = stream_fp_replace( s, &f->tmp );
            if( rc )
                break;
        }
        else {
            fclose( f->tmp );
            f->tmp = NULL;
        }
        rc = cdk_stream_seek( s, 0 );
        if( rc )
            break;
        /* Disable the filter after it was successfully used. The idea
           is the following: let's say the armor filter was pushed and
           later more filters were added. The second time the filter code
           will be executed, only the new filter should be started but
           not the old because we already used it. */
        f->flags.enabled = 0;
    }
    return rc;
}