void gdbDestroyBlock(GdbBlock *block) { blocktype_t typeIndex; if (block == NULL) return; if (gdbCacheRemoveBlock(block->db, block) > 0) return; typeIndex = block->type - 1; if (block->detail != NULL) { if (blockTypeInfo[typeIndex].destroy != NULL) blockTypeInfo[typeIndex].destroy(block->detail); else free(block->detail); } if (GDB_IS_DIRTY(block)) { pmError(PM_ERROR_WARNING, _("GNUpdate DB: Dirty node at offset %ld has not been " "written to disk.\n"), block->offset); } if (block->chain != NULL) free(block->chain); free(block); }
void gdbWriteBlockHeader(GdbBlock *block) { GDatabase *db; char header[GDB_BLOCK_HEADER_SIZE]; int counter = 0; if (block == NULL || !GDB_IS_DIRTY(block)) return; db = block->db; if (block->offset == 0) return; /* Write the header to a buffer. */ gdbPut8(header, &counter, block->type); gdbPut32(header, &counter, block->dataSize); gdbPut16(header, &counter, block->flags); gdbPut32(header, &counter, block->next); gdbPut32(header, &counter, block->listNext); /* Write the header to disk. */ fseek(db->fp, block->offset, SEEK_SET); fwrite(header, GDB_BLOCK_HEADER_SIZE, 1, db->fp); fflush(db->fp); GDB_CLEAR_DIRTY(block); if (block->inList == 0) gdbCacheAddBlock(block->db, block); }
void btreeDestroyNodeBlock(void *data) { BTreeNode *node = (BTreeNode *)data; uint8_t i; if (node == NULL) { return; } for (i = 0; i < node->keyCount; i++) { if (node->keys[i] != NULL) { /* dbg_log(SEC_0130_BTREE, 9)(LOGSTDOUT,"[DEBUG]btreeDestroyNodeBlock: %d# size %d, addr %lx, %.*s\n", i, node->keySizes[i], node->keys[i], node->keySizes[i], node->keys[i]); */ keyFree(node->keys[i], LOC_BTREE_0170); } } if (GDB_IS_DIRTY(node->block)) { dbg_log(SEC_0130_BTREE, 0)(LOGSTDOUT, "error:btreeDestroyNodeBlock: Dirty node at offset %d has not been written to disk.\n", node->block->offset); } SAFE_FREE(node->children, LOC_BTREE_0171); SAFE_FREE(node->keySizes, LOC_BTREE_0172); SAFE_FREE(node->keys, LOC_BTREE_0173); SAFE_FREE(node, LOC_BTREE_0174); }
void gdbWriteBlock(GdbBlock *block) { GDatabase *db; char *buffer; offset_t *oldChain; blocktype_t typeIndex; unsigned int oldChainCount, oldDataSize; unsigned int i, pos; if (block == NULL || !GDB_IS_DIRTY(block)) return; /* Set a couple of vars we'll be using. */ db = block->db; typeIndex = block->type - 1; /* Save the old data. */ oldDataSize = block->dataSize; oldChainCount = block->chainCount; oldChain = block->chain; /* See if there is a write function assigned. */ if (blockTypeInfo[typeIndex].writeBlock != NULL) { /* Write the block info to a buffer. */ blockTypeInfo[typeIndex].writeBlock(block, &buffer, &block->dataSize); } else { buffer = (char *)block->detail; } if (buffer == NULL) { pmError(PM_ERROR_FATAL, _("GNUpdate DB: buffer == NULL in %s, line %d\n"), __FILE__, __LINE__); exit(1); } /* Get the number of needed blocks. */ block->chainCount = gdbGetNeededBlockCount(block->dataSize, block->multiple); if (oldChainCount == 0) { /* Reserve new blocks. */ block->chain = gdbReserveBlockChain(db, block->chainCount, block->type); } else if (block->chainCount < oldChainCount) { /* The number of needed blocks is shorter than before. */ MEM_CHECK(block->chain = (offset_t *)malloc(block->chainCount * sizeof(offset_t))); memcpy(block->chain, oldChain, block->chainCount * sizeof(offset_t)); } else if (block->chainCount > oldChainCount) { offset_t *newChain; int j; /* The number of needed blocks is longer than before. */ MEM_CHECK(block->chain = (offset_t *)malloc(block->chainCount * sizeof(offset_t))); newChain = gdbReserveBlockChain(db, block->chainCount - oldChainCount, block->type); memcpy(block->chain, oldChain, oldChainCount * sizeof(offset_t)); for (i = oldChainCount, j = 0; i < block->chainCount; i++, j++) block->chain[i] = newChain[j]; free(newChain); } /* * Set the offset and next block, if this spills over into * additional blocks. */ block->offset = block->chain[0]; if (block->chainCount > 1) block->next = block->chain[1]; else block->next = 0; /* Write the first block header */ gdbWriteBlockHeader(block); /* Write the first block. */ fwrite(buffer, 1, (block->dataSize < block->multiple - GDB_BLOCK_HEADER_SIZE ? block->dataSize : block->multiple - GDB_BLOCK_HEADER_SIZE), db->fp); if (block->dataSize < block->multiple - GDB_BLOCK_HEADER_SIZE) { gdbPad(db->fp, block->multiple - GDB_BLOCK_HEADER_SIZE - block->dataSize); } else { char *blockBuffer; MEM_CHECK(blockBuffer = (char *)malloc(block->multiple)); pos = block->multiple - GDB_BLOCK_HEADER_SIZE; /* Write any overflow blocks. */ for (i = 1; i < block->chainCount; i++) { offset_t nextOffset; unsigned long relPos; nextOffset = ((i + 1 < block->chainCount) ? block->chain[i + 1] : 0); relPos = block->dataSize - pos; /* Reset the block buffer. */ memset(blockBuffer, 0, block->multiple); /* Write to it. */ nextOffset = htonl(nextOffset); memcpy(blockBuffer, &nextOffset, sizeof(offset_t)); memcpy(blockBuffer + sizeof(offset_t), buffer + pos, (relPos < block->multiple - sizeof(offset_t) ? relPos : block->multiple - sizeof(offset_t))); /* Write the block buffer. */ if (block->chain[i - 1] + block->multiple != block->chain[i]) fseek(db->fp, block->chain[i], SEEK_SET); fwrite(blockBuffer, 1, block->multiple, db->fp); pos += block->multiple - sizeof(offset_t); } free(blockBuffer); } if (oldChainCount != 0) { /* If the chain shrunk, free up the discarded blocks. */ if (block->chainCount < oldChainCount) { gdbFreeBlockChain(db, &oldChain[block->chainCount], oldChainCount - block->chainCount, block->type); } if (oldChainCount != block->chainCount) free(oldChain); } fflush(db->fp); if (buffer != block->detail) free(buffer); }