static int write_log_page(struct file *file, struct log_param *lp) { struct file_header hdr; uint16_t region; coffee_page_t log_page; int16_t log_record; uint16_t log_record_size; uint16_t log_records; cfs_offset_t offset; struct log_param lp_out; read_header(&hdr, file->page); adjust_log_config(&hdr, &log_record_size, &log_records); region = modify_log_buffer(log_record_size, &lp->offset, &lp->size); log_page = 0; if(HDR_MODIFIED(hdr)) { /* A log structure has already been created. */ log_page = hdr.log_page; log_record = find_next_record(file, log_page, log_records); if(log_record >= log_records) { /* The log is full; merge the log. */ PRINTF(("Coffee: Merging the file %s with its log\n", hdr.name)); return merge_log(file->page, 0); } } else { /* Create a log structure. */ log_page = create_log(file, &hdr); if(log_page == INVALID_PAGE) { return -1; } PRINTF(("Coffee: Created a log structure for file %s at page %u\n", hdr.name, (unsigned)log_page)); hdr.log_page = log_page; log_record = 0; } { char copy_buf[log_record_size]; lp_out.offset = offset = region * log_record_size; lp_out.buf = copy_buf; lp_out.size = log_record_size; if((lp->offset > 0 || lp->size != log_record_size) && read_log_page(&hdr, log_record, &lp_out) < 0) { COFFEE_READ(copy_buf, sizeof(copy_buf), absolute_offset(file->page, offset)); } memcpy(©_buf[lp->offset], lp->buf, lp->size); /* * Write the region number in the region index table. * The region number is incremented to avoid values of zero. */ offset = absolute_offset(log_page, 0); ++region; COFFEE_WRITE(®ion, sizeof(region), offset + log_record * sizeof(region)); offset += log_records * sizeof(region); COFFEE_WRITE(copy_buf, sizeof(copy_buf), offset + log_record * log_record_size); file->record_count = log_record + 1; } return lp->size; }
bool resolver::parse_message(msg& msg) { if ((size_t) (msg.end - msg.data) <= sizeof(header)) { return false; } if (!parse_header(msg)) { return false; } if (msg.h->ancount == 0) { return false; } if (!find_first_record(msg)) { return false; } dns_entry entry; entry.name = msg.name; entry.namelen = msg.namelen; red_black_tree<dns_entry>::iterator it; if (!_M_cache.find(entry, it)) { // Name not found in the cache. return false; } dns_entry* e = it.data; msg.narecords = 0; msg.cnamelen = 0; for (unsigned short i = msg.h->ancount; (msg.ptr < msg.end) && (i > 0); i--) { rr rr; if (!find_next_record(msg, rr)) { return false; } if (!process_record(msg, rr)) { return false; } } time_t now = time(NULL); if (msg.narecords == 1) { // If not the original request... if (e->cnamelen > 0) { // The domain name of the original request is in e->cname. red_black_tree<dns_entry>::iterator itcname; if (!find(e->cname, e->cnamelen, itcname)) { _M_cache.erase(it); return false; } _M_cache.erase(it); e = itcname.data; } struct address* addr = msg.arecords; e->address.addr = addr->addr; e->address.expire = now + addr->expire; e->address.preference = addr->preference; e->addresses = &e->address; e->naddresses = 1; e->status = STATUS_VALID; return true; } else if (msg.narecords > 1) { // If not the original request... if (e->cnamelen > 0) { // The domain name of the original request is in e->cname. red_black_tree<dns_entry>::iterator itcname; if (!find(e->cname, e->cnamelen, itcname)) { _M_cache.erase(it); return false; } _M_cache.erase(it); e = itcname.data; } if ((e->addresses = (struct address*) malloc(msg.narecords * sizeof(struct address))) == NULL) { _M_cache.erase(it); return false; } struct address* addr = msg.arecords; for (unsigned short i = 0; i < msg.narecords; i++, addr++) { e->addresses[i].addr = addr->addr; e->addresses[i].expire = now + addr->expire; e->addresses[i].preference = addr->preference; } e->naddresses = msg.narecords; e->status = STATUS_VALID; return true; } else if (msg.cnamelen > 0) { dns_entry* ecname; // If not the original request... if (e->cnamelen > 0) { // The domain name of the original request is in e->cname. char* cname = e->cname; unsigned short cnamelen = e->cnamelen; red_black_tree<dns_entry>::iterator itcname; if (!find(cname, cnamelen, itcname)) { _M_cache.erase(it); return false; } e->cnamelen = 0; _M_cache.erase(it); if (++itcname.data->recursion > MAX_RECURSION) { _M_cache.erase(itcname); free(cname); return false; } if (!add_to_cache(msg.cname, msg.cnamelen, (rr_type) msg.type, &itcname)) { _M_cache.erase(itcname); free(cname); return false; } ecname = itcname.data; ecname->cname = cname; ecname->cnamelen = cnamelen; } else { red_black_tree<dns_entry>::iterator itcname; if (!add_to_cache(msg.cname, msg.cnamelen, (rr_type) msg.type, &itcname)) { _M_cache.erase(it); return false; } ecname = itcname.data; if ((ecname->cname = (char*) malloc(msg.namelen)) == NULL) { _M_cache.erase(itcname); _M_cache.erase(it); return false; } memcpy(ecname->cname, msg.name, msg.namelen); ecname->cnamelen = msg.namelen; } return make_request(ecname->name, ecname->namelen, (rr_type) ecname->type, true); } else { return false; } }