Exemple #1
0
static void
stdstream_init()
{
    output_stream tmp;
    output_stream tmp2;

    fd_output_stream_attach(1, &tmp);
    buffer_output_stream_init(&tmp, &tmp2, TERM_BUFFER_SIZE);
    mt_output_stream_init(&tmp2, &__termout__);

    fd_output_stream_attach(2, &tmp);
    buffer_output_stream_init(&tmp, &tmp2, TERM_BUFFER_SIZE);
    mt_output_stream_init(&tmp2, &__termerr__);
}
static ya_result
logger_channel_file_append(const char *fullpath, uid_t uid, gid_t gid, u16 mode, file_data* sd)
{
    output_stream errlog_os;
    output_stream buffered_errlog_os;
    ya_result return_code;

    if(FAIL(return_code = file_output_stream_open_ex(fullpath,
                    O_CREAT|O_APPEND|O_RDWR,
                    mode,
                    &errlog_os)))
    {
        sd->fd = -1;
        return return_code;
    }

    /*
     * Change ownership of the file here.
     */

    int fd = fd_output_stream_get_filedescriptor(&errlog_os);
    
    if(fchown(fd, uid, gid) < 0)
    {
        return_code = ERRNO_ERROR;
        output_stream_close(&errlog_os);
        sd->fd = -1;
        return return_code;
    }
    
    sd->fd = fd;
    
    if(FAIL(return_code = buffer_output_stream_init(&errlog_os, &buffered_errlog_os, FILE_CHANNEL_BUFFER_SIZE)))
    {
        output_stream_close(&errlog_os);
        sd->fd = -1;
        return return_code;
    }

    sd->os.data = buffered_errlog_os.data;
    sd->os.vtbl = buffered_errlog_os.vtbl;

    return SUCCESS;
}
Exemple #3
0
static ya_result
journal_ix_append_ixfr_stream(journal *jh, input_stream *ixfr_wire_is)
{
    journal_ix *jix = (journal_ix*)jh;
    
    journal_ix_writelock(jix);
    
    /*
     * Move at the end of the file
     * Check that the wire starts with the last soa/serial
     * Append the wire
     * update the last serial
     */
    
    // read the record
    
    ya_result return_value;    
    dns_resource_record rr;
    
    dns_resource_record_init(&rr);
    
    if((return_value = dns_resource_record_read(&rr, ixfr_wire_is)) <= 0)
    {
        /* FAIL or EOF */
        
        dns_resource_record_clear(&rr);
        journal_ix_writeunlock(jix);
        
        log_err("journal: ix: unable to read record: %r", return_value);
        
        return return_value;
    }
    
    /*
     * The first record is an SOA and our starting point (to be deleted)
     */
    
#ifdef DEBUG
    rdata_desc rdatadesc = {rr.tctr.qtype, rr.rdata_size, rr.rdata};
    log_debug("journal: ix: DEL %{dnsname} %{typerdatadesc}", rr.name, &rdatadesc);
#endif
        
    if(rr.tctr.qtype != TYPE_SOA)
    {
        u16 rtype = rr.tctr.qtype;
        dns_resource_record_clear(&rr);
        journal_ix_writeunlock(jix);
        
        log_err("journal: ix: expected SOA record but got %{dnstype} instead", &rtype);
        
        return ZDB_JOURNAL_SOA_RECORD_EXPECTED;
    }
    
    /*
     * check the journal file exists/is defined
     * do it now if not
     * proceed
     */
    
    if(((jix->first_serial == 0) && (jix->last_serial == 0)) || (jix->fd == -1))
    {
        /* the file does not exists yet */
        
        if(FAIL(return_value = rr_soa_get_serial(rr.rdata, rr.rdata_size, &jix->first_serial)))
        {
            dns_resource_record_clear(&rr);
            journal_ix_writeunlock(jix);
            
            log_err("journal: ix: unable to read record: %r", return_value);

            return return_value;
        }
        
        int fd = open_create_ex(jix->journal_name, O_RDWR|O_CREAT, 0644);

        if(fd < 0)
        {
            return_value = ERRNO_ERROR;
            dns_resource_record_clear(&rr);
            journal_ix_writeunlock(jix);
            
            log_err("journal: ix: unable to open journal file '%s': %r", jix->journal_name, return_value);
            
            return return_value;
        }
        
        log_info("journal: ix: journal file created '%s'", jix->journal_name);
        
        jix->fd = fd;
    }
    
    if(FAIL(return_value = journal_ix_ensure_opened(jix)))
    {
        return return_value;
    }
    
    u64 valid_offset = lseek(jix->fd, 0, SEEK_END);
    u64 current_offset = valid_offset;
    
    u32 valid_serial = jix->last_serial;
    u32 potential_serial = valid_serial;
    
    s64 valid_page_offset = jix->last_page_offset;
    s64 potential_page_offset = current_offset;
    
#ifdef DEBUG
    log_debug("journal: ix: ready to append to journal after serial %08x (%d) at offset %lld", valid_serial, valid_serial, valid_offset);
#endif
    
    u8 mode = 0; /* 0: del, 1: add */
    
    output_stream fos;
    output_stream bos;
    fd_output_stream_attach(&fos, jix->fd);
    buffer_output_stream_init(&bos, &fos, 512);
    
    for(;;)
    {
        /* write the first */

        if(FAIL(return_value = dns_resource_record_write(&rr, &bos)))
        {
            /* this is VERY bad */
            
            log_err("journal: ix: error writing a record to the journal: %r", return_value);

            break;
        }
        
        /* update the current offset */
        
        current_offset += return_value;        
        
        if((return_value = dns_resource_record_read(&rr, ixfr_wire_is)) <= 0) /* no bytes read OR error, there is no macro for this */
        {
            /* error or end of stream */
            
            if(return_value == 0)           /* end of stream */
            {
                if(mode != 0)               /* on add mode so everything should be fine */
                {
                    valid_offset = current_offset;
                    valid_serial = potential_serial;
                    valid_page_offset = potential_page_offset;
                }
                else                        /* but on delete mode instead of add mode */
                {
                    log_err("journal: ix: ixfr stream unexpected eof");

                    return_value = UNEXPECTED_EOF;  /* we have an error */
                }
            }

            break;
        }
        
        if(rr.tctr.qtype == TYPE_SOA)
        {
            mode ^= 1;
            
#ifdef DEBUG
            rdata_desc rdatadesc = {rr.tctr.qtype, rr.rdata_size, rr.rdata};
            log_debug("journal: ix: %s %{dnsname} %{typerdatadesc}", (mode!=0)?"add":"del", rr.name, &rdatadesc);
#endif
            
            if(mode == 0)
            {
                /* 
                 * new SOA to delete
                 * 
                 * it's a new "page" (delete -> add)
                 * 
                 * the offset before we write this record is the highest valid one in the file
                 * so the error correcting truncation will be made at that offset
                 */
                
                valid_offset = current_offset;
                
                /*
                 * the serial number that has been added with the previous page
                 */
                
                valid_serial = potential_serial;
                
                /*
                 * the offset of the previous page
                 */
                
                valid_page_offset = potential_page_offset;
                
                /*
                 * the new page starts here : update
                 */
                
                potential_page_offset = current_offset;
            }
            else
            {
                /*
                 * new SOA add
                 * 
                 * this is the second half of the page, we know what serial it is about
                 */
                
                if(FAIL(return_value = rr_soa_get_serial(rr.rdata, rr.rdata_size, &potential_serial)))
                {
                    break;
                }
            }
        }
#ifdef DEBUG
        else
        {
            rdata_desc rdatadesc = {rr.tctr.qtype, rr.rdata_size, rr.rdata};
            log_debug("journal: ix: %s %{dnsname} %{typerdatadesc}", (mode!=0)?"add":"del", rr.name, &rdatadesc);
        }
#endif
    }

    if(FAIL(return_value))
    {
        /*
         * The journal is only valid up to valid_offset with serial ...
         */
        
        log_err("journal: ix: rewinding journal up to last valid point (%lld)", valid_offset);
        
        ftruncate(jix->fd, valid_offset);
    }
    
#ifdef DEBUG
    log_debug("journal: ix: page offset got from %d to %d", jix->last_page_offset, valid_page_offset);
    log_debug("journal: ix: serial got from %d to %d", jix->last_serial, valid_serial);
#endif
    
    jix->last_page_offset = valid_page_offset;    
    jix->last_serial = valid_serial;
    
    /*
     * rename the file
     */
    
    if(ISOK(return_value))
    {
        char new_name[PATH_MAX];
        memcpy(new_name, jix->journal_name, jix->journal_name_len);
        snformat(&new_name[jix->journal_name_len - FIRST_FROM_END], 8 + 1 + 8 + 1 + IX_EXT_STRLEN + 1,
                "%08x-%08x." IX_EXT , jix->first_serial, jix->last_serial);
        if(rename(jix->journal_name, new_name) >= 0)
        {
            memcpy(jix->journal_name, new_name, jix->journal_name_len);
        }
    }
    
    /*
     */

#ifdef DEBUG
    log_debug("journal: ix: fd=%i from=%08x to=%08x soa@%lld file=%s",
            jix->fd, jix->first_serial, jix->last_serial, jix->last_page_offset, (jix->journal_name!=NULL)?jix->journal_name:"NONE-YET");
#endif
    
    output_stream_flush(&bos);
    fd_output_stream_detach(buffer_output_stream_get_filtered(&bos));
    output_stream_close(&bos);
    
    dns_resource_record_clear(&rr);
    
    journal_ix_writeunlock(jix);
    
    if(ISOK(return_value))
    {
#ifdef DEBUG
        log_debug("journal: ix: page added (fd=%i from=%08x to=%08x soa@%lld file=%s): %r",
                jix->fd, jix->first_serial, jix->last_serial, jix->last_page_offset, (jix->journal_name!=NULL)?jix->journal_name:"NONE-YET",
                return_value);
#endif
        return TYPE_IXFR;       /* that's what the caller expects to handle the new journal pages */
    }
    else
    {    
        log_err("journal: ix: failed to add page");
        return return_value;
    }
}