/** * create a new object and open it if success */ URET uffs_CreateObject(uffs_Object *obj, const char *fullname, int oflag) { oflag |= UO_CREATE; if (uffs_ParseObject(obj, fullname) == U_SUCC) uffs_CreateObjectEx(obj, obj->dev, obj->parent, obj->name, obj->name_len, oflag); return (obj->err == UENOERR ? U_SUCC : U_FAIL); }
/** * create a new object and open it if success */ URET uffs_CreateObject(uffs_Object *obj, const char *fullname, int oflag) { URET ret = U_FAIL; oflag |= UO_CREATE; if (uffs_ParseObject(obj, fullname) == U_SUCC) uffs_CreateObjectEx(obj, obj->dev, obj->parent, obj->name, obj->name_len, oflag); if (obj->err == UENOERR) { ret = U_SUCC; } else { if (obj->dev) { uffs_PutDevice(obj->dev); obj->dev = NULL; } ret = U_FAIL; } return ret; }
/** * Open object under the given dir. * * \param[in|out] obj to be open, obj is returned from uffs_GetObject() * \param[in] dev uffs device * \param[in] dir object parent dir serial NO. * \param[in] name point to the object name * \param[in] name_len object name length * \param[in] oflag open flag. UO_DIR should be passed for an dir object. * * \return U_SUCC or U_FAIL (error code in obj->err). */ URET uffs_OpenObjectEx(uffs_Object *obj, uffs_Device *dev, int dir, const char *name, int name_len, int oflag) { obj->err = UENOERR; obj->open_succ = U_FALSE; if (dev == NULL) { obj->err = UEINVAL; goto ext; } if ((oflag & (UO_WRONLY | UO_RDWR)) == (UO_WRONLY | UO_RDWR)) { /* UO_WRONLY and UO_RDWR can't appear together */ uffs_Perror(UFFS_MSG_NOISY, "UO_WRONLY and UO_RDWR can't appear together"); obj->err = UEINVAL; goto ext; } obj->oflag = oflag; obj->parent = dir; obj->type = (oflag & UO_DIR ? UFFS_TYPE_DIR : UFFS_TYPE_FILE); obj->pos = 0; obj->dev = dev; obj->name = name; obj->name_len = name_len; // adjust the name length if (obj->type == UFFS_TYPE_DIR) { if (obj->name_len > 0 && name[obj->name_len - 1] == '/') obj->name_len--; // truncate the ending '/' for dir } obj->sum = (obj->name_len > 0 ? uffs_MakeSum16(name, obj->name_len) : 0); obj->head_pages = obj->dev->attr->pages_per_block - 1; if (obj->type == UFFS_TYPE_DIR) { if (obj->name_len == 0) { if (dir != PARENT_OF_ROOT) { uffs_Perror(UFFS_MSG_SERIOUS, "Bad parent for root dir!"); obj->err = UEINVAL; } else { obj->serial = ROOT_DIR_SERIAL; } goto ext; } } else { if (obj->name_len == 0 || name[obj->name_len - 1] == '/') { uffs_Perror(UFFS_MSG_SERIOUS, "Bad file name."); obj->err = UEINVAL; } } uffs_ObjectDevLock(obj); if (obj->type == UFFS_TYPE_DIR) { obj->node = uffs_TreeFindDirNodeByName(obj->dev, obj->name, obj->name_len, obj->sum, obj->parent); } else { obj->node = uffs_TreeFindFileNodeByName(obj->dev, obj->name, obj->name_len, obj->sum, obj->parent); } if (obj->node == NULL) { // dir or file not exist if (obj->oflag & UO_CREATE) { // expect to create a new one uffs_ObjectDevUnLock(obj); if (obj->name == NULL || obj->name_len == 0) obj->err = UEEXIST; else uffs_CreateObjectEx(obj, dev, dir, obj->name, obj->name_len, oflag); goto ext; } else { obj->err = UENOENT; goto ext_1; } } if ((obj->oflag & (UO_CREATE | UO_EXCL)) == (UO_CREATE | UO_EXCL)){ obj->err = UEEXIST; goto ext_1; } obj->serial = GET_OBJ_NODE_SERIAL(obj); obj->open_succ = U_TRUE; if (obj->oflag & UO_TRUNC) if (do_TruncateObject(obj, 0, eDRY_RUN) == U_SUCC) { //NOTE: obj->err will be set in do_TruncateObject() if failed. do_TruncateObject(obj, 0, eREAL_RUN); } ext_1: uffs_ObjectDevUnLock(obj); ext: obj->open_succ = (obj->err == UENOERR ? U_TRUE : U_FALSE); return (obj->err == UENOERR ? U_SUCC : U_FAIL); }