TreeNode * uffs_TreeFindDirNodeByName(uffs_Device *dev, const char *name, u32 len, u16 sum, u16 parent) { int i; u16 x; TreeNode *node; struct uffs_TreeSt *tree = &(dev->tree); for (i = 0; i < DIR_NODE_ENTRY_LEN; i++) { x = tree->dir_entry[i]; while (x != EMPTY_NODE) { node = FROM_IDX(x, TPOOL(dev)); if (node->u.dir.checksum == sum && node->u.dir.parent == parent) { //read file name from flash, and compare... if (uffs_TreeCompareFileName(dev, name, len, sum, node, UFFS_TYPE_DIR) == U_TRUE) { //Got it! return node; } } x = node->hash_next; } } return NULL; }
/* calculate file length, etc */ static URET _BuildTreeStepThree(uffs_Device *dev) { int i; u16 x; TreeNode *work; TreeNode *node; struct uffs_TreeSt *tree; uffs_Pool *pool; u16 blockSave; TreeNode *cache = NULL; u16 cacheSerial = INVALID_UFFS_SERIAL; tree = &(dev->tree); pool = TPOOL(dev); uffs_Perror(UFFS_MSG_NOISY, "build tree step three"); for (i = 0; i < DATA_NODE_ENTRY_LEN; i++) { x = tree->data_entry[i]; while (x != EMPTY_NODE) { work = FROM_IDX(x, pool); if (work->u.data.parent == cacheSerial) { node = cache; } else { node = uffs_TreeFindFileNode(dev, work->u.data.parent); cache = node; cacheSerial = work->u.data.parent; } if (node == NULL) { x = work->hash_next; //this data block does not belong to any file ? //should be erased. uffs_Perror(UFFS_MSG_NORMAL, "find a orphan data block:%d, " "parent:%d, serial:%d, will be erased!", work->u.data.block, work->u.data.parent, work->u.data.serial); uffs_BreakFromEntry(dev, UFFS_TYPE_DATA, work); blockSave = work->u.data.block; work->u.list.block = blockSave; uffs_FlashEraseBlock(dev, blockSave); if (HAVE_BADBLOCK(dev)) uffs_BadBlockProcess(dev, work); else uffs_TreeInsertToErasedListTail(dev, work); } else { node->u.file.len += work->u.data.len; x = work->hash_next; } } } return U_SUCC; }
static void _InsertToEntry(uffs_Device *dev, u16 *entry, int hash, TreeNode *node) { node->hash_next = entry[hash]; node->hash_prev = EMPTY_NODE; if (entry[hash] != EMPTY_NODE) { FROM_IDX(entry[hash], TPOOL(dev))->hash_prev = TO_IDX(node, TPOOL(dev)); } entry[hash] = TO_IDX(node, TPOOL(dev)); }
/** * break the node from entry */ void uffs_BreakFromEntry(uffs_Device *dev, u8 type, TreeNode *node) { u16 *entry; int hash; TreeNode *work; switch (type) { case UFFS_TYPE_DIR: hash = GET_DIR_HASH(node->u.dir.serial); entry = &(dev->tree.dir_entry[hash]); break; case UFFS_TYPE_FILE: hash = GET_FILE_HASH(node->u.file.serial); entry = &(dev->tree.file_entry[hash]); break; case UFFS_TYPE_DATA: hash = GET_DATA_HASH(node->u.data.parent, node->u.data.serial); entry = &(dev->tree.data_entry[hash]); break; default: uffs_Perror(UFFS_MSG_SERIOUS, "unknown type when break..."); return; } if (node->hash_prev != EMPTY_NODE) { work = FROM_IDX(node->hash_prev, &(dev->mem.tree_pool)); work->hash_next = node->hash_next; } if (node->hash_next != EMPTY_NODE) { work = FROM_IDX(node->hash_next, &(dev->mem.tree_pool)); work->hash_prev = node->hash_prev; } if (*entry == TO_IDX(node, &(dev->mem.tree_pool))) { *entry = node->hash_next; } }
TreeNode * uffs_TreeFindDataNodeByBlock(uffs_Device *dev, u16 block) { int hash; TreeNode *node; struct uffs_TreeSt *tree = &(dev->tree); u16 x; for (hash = 0; hash < DATA_NODE_ENTRY_LEN; hash++) { x = tree->data_entry[hash]; while (x != EMPTY_NODE) { node = FROM_IDX(x, TPOOL(dev)); if (node->u.data.block == block) return node; x = node->hash_next; } } return NULL; }
TreeNode * uffs_TreeFindDirNode(uffs_Device *dev, u16 serial) { int hash; u16 x; TreeNode *node; struct uffs_TreeSt *tree = &(dev->tree); hash = serial & DIR_NODE_HASH_MASK; x = tree->dir_entry[hash]; while (x != EMPTY_NODE) { node = FROM_IDX(x, TPOOL(dev)); if (node->u.dir.serial == serial) { return node; } else { x = node->hash_next; } } return NULL; }
TreeNode * uffs_TreeFindDataNode(uffs_Device *dev, u16 parent, u16 serial) { int hash; TreeNode *node; struct uffs_TreeSt *tree = &(dev->tree); u16 x; hash = GET_DATA_HASH(parent, serial); x = tree->data_entry[hash]; while(x != EMPTY_NODE) { node = FROM_IDX(x, TPOOL(dev)); if(node->u.data.parent == parent && node->u.data.serial == serial) return node; x = node->hash_next; } return NULL; }
TreeNode * uffs_TreeFindDirNodeWithParent(uffs_Device *dev, u16 parent) { int hash; u16 x; TreeNode *node; struct uffs_TreeSt *tree = &(dev->tree); for (hash = 0; hash < DIR_NODE_ENTRY_LEN; hash++) { x = tree->dir_entry[hash]; while (x != EMPTY_NODE) { node = FROM_IDX(x, TPOOL(dev)); if (node->u.dir.parent == parent) { return node; } else { x = node->hash_next; } } } return NULL; }
static URET do_FindObject(uffs_FindInfo *f, uffs_ObjectInfo *info, u16 x) { URET ret = U_SUCC; TreeNode *node; uffs_Device *dev = f->dev; if (f->step == 0) { //!< working on dirs while (x != EMPTY_NODE) { node = FROM_IDX(x, TPOOL(dev)); if (node->u.dir.parent == f->serial) { f->work = node; f->pos++; if (info) ret = _LoadObjectInfo(dev, node, info, UFFS_TYPE_DIR, NULL); goto ext; } x = node->hash_next; } f->hash++; //come to next hash entry for (; f->hash < DIR_NODE_ENTRY_LEN; f->hash++) { x = dev->tree.dir_entry[f->hash]; while (x != EMPTY_NODE) { node = FROM_IDX(x, TPOOL(dev)); if (node->u.dir.parent == f->serial) { f->work = node; f->pos++; if (info) ret = _LoadObjectInfo(dev, node, info, UFFS_TYPE_DIR, NULL); goto ext; } x = node->hash_next; } } //no subdirs, then lookup files .. f->step++; f->hash = 0; x = EMPTY_NODE; } if (f->step == 1) { while (x != EMPTY_NODE) { node = FROM_IDX(x, TPOOL(dev)); if (node->u.file.parent == f->serial) { f->work = node; f->pos++; if (info) ret = _LoadObjectInfo(dev, node, info, UFFS_TYPE_FILE, NULL); goto ext; } x = node->hash_next; } f->hash++; //come to next hash entry for (; f->hash < FILE_NODE_ENTRY_LEN; f->hash++) { x = dev->tree.file_entry[f->hash]; while (x != EMPTY_NODE) { node = FROM_IDX(x, TPOOL(dev)); if (node->u.file.parent == f->serial) { f->work = node; f->pos++; if (info) ret = _LoadObjectInfo(dev, node, info, UFFS_TYPE_FILE, NULL); goto ext; } x = node->hash_next; } } //no any files, stopped. f->step++; } ret = U_FAIL; ext: return ret; }