int uffs_stat(const char *name, struct uffs_stat *buf) { uffs_Object *obj; int ret = 0; int err = 0; URET result; obj = uffs_GetObject(); if (obj) { if (*name && name[strlen(name) - 1] == '/') { result = uffs_OpenObject(obj, name, UO_RDONLY | UO_DIR); } else { if ((result = uffs_OpenObject(obj, name, UO_RDONLY)) != U_SUCC) // try file result = uffs_OpenObject(obj, name, UO_RDONLY | UO_DIR); // then try dir } if (result == U_SUCC) { ret = do_stat(obj, buf); uffs_CloseObject(obj); } else { err = uffs_GetObjectErr(obj); ret = -1; } uffs_PutObject(obj); } else { err = UENOMEM; ret = -1; } uffs_set_error(-err); return ret; }
uffs_DIR * uffs_opendir(const char *path) { int err = 0; uffs_DIR *ret = NULL; uffs_DIR *dirp = GetDirEntry(); if (dirp) { dirp->obj = uffs_GetObject(); if (dirp->obj) { if (uffs_OpenObject(dirp->obj, path, UO_RDONLY | UO_DIR) == U_SUCC) { if (uffs_FindObjectOpen(&dirp->f, dirp->obj) == U_SUCC) { ret = dirp; goto ext; } else { uffs_CloseObject(dirp->obj); } } else { err = uffs_GetObjectErr(dirp->obj); } uffs_PutObject(dirp->obj); dirp->obj = NULL; } else { err = UEMFILE; } PutDirEntry(dirp); } else { err = UEMFILE; } ext: uffs_set_error(-err); return ret; }
int uffs_mkdir(const char *name, ...) { uffs_Object *obj; int ret = 0; int err = 0; uffs_GlobalFsLockLock(); obj = uffs_GetObject(); if (obj) { if (uffs_CreateObject(obj, name, UO_CREATE|UO_DIR) != U_SUCC) { err = obj->err; ret = -1; } else { uffs_CloseObject(obj); ret = 0; } uffs_PutObject(obj); } else { err = UEMFILE; ret = -1; } uffs_set_error(-err); uffs_GlobalFsLockUnlock(); return ret; }
int uffs_open(const char *name, int oflag, ...) { uffs_Object *obj; int ret = 0; uffs_GlobalFsLockLock(); obj = uffs_GetObject(); if (obj == NULL) { uffs_set_error(-UEMFILE); ret = -1; } else { if (uffs_OpenObject(obj, name, oflag) == U_FAIL) { uffs_set_error(-uffs_GetObjectErr(obj)); uffs_PutObject(obj); ret = -1; } else { ret = OBJ2FD(obj); } } uffs_GlobalFsLockUnlock(); return ret; }
/* * 函数功能: 创建一个文件 * 输入参数: 文件名称 * 返回参数: */ int uffs_mkfile(const char *name) { uffs_Object *fp; int ret = 0; int err = 0; fp = uffs_GetObject(); if(fp != NULL) { if(uffs_CreateObject(fp, name, UO_CREATE) != U_SUCC) { err = fp->err; ret = -1; uffs_Perror(UFFS_ERR_NORMAL, "Create %s fail, err: %d", name, uffs_get_error()); } else { uffs_Perror(UFFS_ERR_NORMAL, "Create %s succ.", name); uffs_CloseObject(fp); ret = 0; } uffs_PutObject(fp); } else { err = UEMFILE; ret = -1; } uffs_set_error(-err); return ret; }
/** * \brief rename(move) file or dir. * \return U_SUCC if success, otherwise return U_FAIL and set error code to *err. * \note rename/move file between different mount point is not allowed. */ URET uffs_RenameObject(const char *old_name, const char *new_name, int *err) { uffs_Object *obj = NULL, *new_obj = NULL; URET ret = U_FAIL; int oflag; obj = uffs_GetObject(); new_obj = uffs_GetObject(); if (obj == NULL || new_obj == NULL) { if (err) *err = UEINVAL; goto ext; } oflag = UO_RDONLY; if (uffs_OpenObject(new_obj, new_name, oflag) == U_SUCC) { uffs_CloseObject(new_obj); uffs_Perror(UFFS_MSG_NOISY, "new object already exist!"); if (err) *err = UEEXIST; goto ext; } oflag |= UO_DIR; if (uffs_OpenObject(new_obj, new_name, oflag) == U_SUCC) { uffs_CloseObject(new_obj); uffs_Perror(UFFS_MSG_NOISY, "new object already exist!"); if (err) *err = UEEXIST; goto ext; } if (uffs_ParseObject(new_obj, new_name) != U_SUCC) { uffs_Perror(UFFS_MSG_NOISY, "parse new name fail !"); if (err) *err = UENOENT; goto ext; } if (new_obj->name_len == 0) { uffs_Perror(UFFS_MSG_NOISY, "invalid new name"); if (err) *err = UEINVAL; goto ext; } oflag = UO_RDONLY; if (uffs_OpenObject(obj, old_name, oflag) != U_SUCC) { oflag |= UO_DIR; if (uffs_OpenObject(obj, old_name, oflag) != U_SUCC) { uffs_Perror(UFFS_MSG_NOISY, "Can't open old object !"); if (err) *err = UEACCES; goto ext; } } if (obj->dev != new_obj->dev) { uffs_Perror(UFFS_MSG_NOISY, "Can't move object between different mount point"); if (err) *err = UEACCES; } else { ret = uffs_MoveObjectEx(obj, new_obj->parent, new_obj->name, new_obj->name_len); if (ret == U_FAIL && err) *err = obj->err; } uffs_CloseObject(obj); ext: if (obj) uffs_PutObject(obj); if (new_obj) { do_ReleaseObjectResource(new_obj); uffs_PutObject(new_obj); } return ret; }
/** * \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; }
/** * \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; TreeNode *node; uffs_Device *dev; u16 block; uffs_Buf *buf; URET ret = U_FAIL; obj = uffs_GetObject(); if (obj == NULL) { if (err) *err = UEMFILE; goto err1; } 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 err1; } } uffs_TruncateObject(obj, 0); uffs_ObjectDevLock(obj); dev = obj->dev; 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 err; //have sub dirs ? } node = uffs_TreeFindFileNodeWithParent(dev, obj->serial); if (node != NULL) { if (err) *err = UEACCES; goto err; //have sub files ? } } block = GET_BLOCK_FROM_NODE(obj); node = obj->node; // before erase the block, we need to take care of the buffer ... uffs_BufFlushAll(dev); if (HAVE_BADBLOCK(dev)) uffs_BadBlockRecover(dev); buf = uffs_BufFind(dev, obj->parent, obj->serial, 0); if (buf) { //need to expire this buffer ... if (buf->ref_count != 0) { //there is other obj for this file still in use ? uffs_Perror(UFFS_ERR_NORMAL, "Try to delete object but still have buf referenced."); if (err) *err = UEACCES; goto err; } buf->mark = UFFS_BUF_EMPTY; //!< make this buffer expired. } //TODO: need to take care of other obj->node ? uffs_BreakFromEntry(dev, obj->type, node); uffs_FlashEraseBlock(dev, block); node->u.list.block = block; if (HAVE_BADBLOCK(dev)) uffs_BadBlockProcess(dev, node); else uffs_TreeInsertToErasedListTail(dev, node); ret = U_SUCC; err: uffs_ObjectDevUnLock(obj); err1: do_ReleaseObjectResource(obj); uffs_PutObject(obj); return ret; }
int dfs_uffs_open(struct dfs_fd* fd) { if (fd->flags & DFS_O_DIRECTORY) { /* directory */ uffs_DIR* dirp; int oflag = UO_DIR; if (fd->flags & DFS_O_CREAT) oflag |= UO_CREATE; if (fd->flags & DFS_O_RDONLY) oflag |= UO_RDONLY; if (fd->flags & DFS_O_WRONLY) oflag |= UO_WRONLY; if (oflag & UO_CREATE) { /* create directory right now */ uffs_Object* fp = uffs_GetObject(); if(fp == NULL) { uffs_set_error(-UEMFILE); return U_FAIL; } if(uffs_OpenObject(fp, fd->path, oflag) != U_SUCC) { return U_FAIL; } /* release object hander */ uffs_PutObject(fp); } /* use directory handler */ dirp = uffs_opendir(fd->path); if(dirp == NULL) { uffs_set_error(-UEMFILE); return U_FAIL; } fd->data = dirp; return U_SUCC; } else {/* file */ uffs_Object *fp; int mode = UO_RDONLY; if (fd->flags & DFS_O_WRONLY) mode |= UO_WRONLY; if ((fd->flags & DFS_O_ACCMODE) & DFS_O_RDWR) mode |= UO_WRONLY; /* Opens the file, if it is existing. If not, a new file is created. */ if (fd->flags & DFS_O_CREAT) mode |= UO_CREATE; /* Creates a new file. If the file is existing, it is truncated and overwritten. */ if (fd->flags & DFS_O_TRUNC) mode |= UO_TRUNC; /* Creates a new file. The function fails if the file is already existing. */ if (fd->flags & DFS_O_EXCL) mode |= UO_EXCL; /* get an object hander */ fp = uffs_GetObject(); if(fp == NULL) { uffs_set_error(-UEMFILE); return U_FAIL; } if(uffs_OpenObject(fp, fd->path, mode) == U_SUCC) { struct uffs_stat stat_buf; uffs_stat(fd->path, &stat_buf); fd->pos = fp->pos; fd->size = stat_buf.st_size; fd->data = fp; if(fd->flags & DFS_O_APPEND) { fd->pos = uffs_SeekObject(fp, 0, USEEK_END); } return U_SUCC; } else { /* open failed, return */ uffs_set_error(-uffs_GetObjectErr(fp)); /* release object hander */ uffs_PutObject(fp); return U_FAIL; } } }