/** * \brief put all memory block back, return how many memory blocks were put back */ int uffs_PoolPutAll(uffs_Pool *pool) { void *p = NULL; int count = 0; do { p = uffs_PoolFindNextAllocated(pool, p); if (p) { uffs_PoolPut(pool, p); count++; } } while (p); return count; }
/** * Put all object which match dev */ int uffs_PutAllObjectBuf(uffs_Device *dev) { int count = 0; uffs_Object * obj = NULL; do { obj = (uffs_Object *) uffs_PoolFindNextAllocated(&_object_pool, (void *)obj); if (obj && obj->dev && obj->dev->dev_num == dev->dev_num) { uffs_PutObject(obj); count++; } } while (obj); return count; }
/** * Put all dir entry buf match dev */ int uffs_DirEntryBufPutAll(uffs_Device *dev) { int count = 0; uffs_DIR *dirp = NULL; do { dirp = (uffs_DIR *) uffs_PoolFindNextAllocated(&_dir_pool, dirp); if (dirp && dirp->obj && dirp->obj->dev && dirp->obj->dev->dev_num == dev->dev_num) { uffs_PoolPut(&_dir_pool, dirp); count++; } } while (dirp); return count; }
/** * \brief delete uffs object * * \param[in] name full name of object * \param[out] err return error code * * \return U_SUCC if object is deleted successfully. * return U_FAIL if error happen, error code is set to *err. */ URET uffs_DeleteObject(const char * name, int *err) { uffs_Object *obj, *work; TreeNode *node, *d_node; uffs_Device *dev = NULL; u16 block; u16 serial, parent, last_serial; UBOOL bad = U_FALSE; URET ret = U_FAIL; obj = uffs_GetObject(); if (obj == NULL) { if (err) *err = UEMFILE; goto ext_unlock; } if (uffs_OpenObject(obj, name, UO_RDWR|UO_DIR) == U_FAIL) { if (uffs_OpenObject(obj, name, UO_RDWR) == U_FAIL) { if (err) *err = UENOENT; goto ext_unlock; } } dev = obj->dev; // working throught object pool see if the object is opened ... uffs_ObjectDevLock(obj); work = NULL; while ((work = (uffs_Object *)uffs_PoolFindNextAllocated(&_object_pool, work)) != NULL) { if (work != obj && work->dev && work->dev == obj->dev && work->node && work->node == obj->node) { // this object is opened, can't delete it. if (err) *err = UEACCES; goto ext_lock; } } if (obj->type == UFFS_TYPE_DIR) { // if the dir is not empty, can't delete it. node = uffs_TreeFindDirNodeWithParent(dev, obj->serial); if (node != NULL) { if (err) *err = UEACCES; goto ext_lock; //have sub dirs ? } node = uffs_TreeFindFileNodeWithParent(dev, obj->serial); if (node != NULL) { if (err) *err = UEACCES; goto ext_lock; //have sub files ? } } // before erase the block, we need to take care of the buffer ... uffs_BufFlushAll(dev); if (_CheckObjBufRef(obj) > 0) { if (err) *err = UEACCES; goto ext_lock; } node = obj->node; // ok, now we are safe to erase DIR/FILE block :-) block = GET_BLOCK_FROM_NODE(obj); parent = obj->serial; last_serial = (obj->type == UFFS_TYPE_FILE && node->u.file.len > 0 ? GetFdnByOfs(obj, node->u.file.len - 1) : 0); uffs_BreakFromEntry(dev, obj->type, node); uffs_FlashEraseBlock(dev, block); node->u.list.block = block; node->u.list.u.serial = obj->serial; // From now on, the object is gone physically, // but we need to 'suspend' this node so that no one will re-use // the serial number during deleting the reset part of object. if (HAVE_BADBLOCK(dev)) { uffs_BadBlockProcessSuspend(dev, node); bad = U_TRUE; // will be put into 'bad' list later } else { uffs_TreeSuspendAdd(dev, node); bad = U_FALSE; // will be put into erased list later } // now erase DATA blocks if (obj->type == UFFS_TYPE_FILE && last_serial > 0) { for (serial = 1; serial <= last_serial; serial++) { uffs_ObjectDevUnLock(obj); ; // yield CPU to improve responsive when deleting large file. uffs_ObjectDevLock(obj); d_node = uffs_TreeFindDataNode(dev, parent, serial); if (uffs_Assert(d_node != NULL, "Can't find DATA node parent = %d, serial = %d\n", parent, serial)) { uffs_BreakFromEntry(dev, UFFS_TYPE_DATA, d_node); block = d_node->u.data.block; uffs_FlashEraseBlock(dev, block); d_node->u.list.block = block; if (HAVE_BADBLOCK(dev)) uffs_BadBlockProcess(dev, d_node); else uffs_TreeInsertToErasedListTail(dev, d_node); } } } // now process the suspend node uffs_TreeRemoveSuspendNode(dev, node); if (bad) uffs_TreeInsertToBadBlockList(dev, node); else uffs_TreeInsertToErasedListTail(dev, node); ret = U_SUCC; ext_lock: uffs_ObjectDevUnLock(obj); ext_unlock: do_ReleaseObjectResource(obj); uffs_PutObject(obj); return ret; }