Esempio n. 1
0
/** 
 * find a node from tree
 * \param[in] dev uffs device
 * \param[in] type type of node
 * \param[in] parent parent serial num
 * \param[in] serial serial num
 */
TreeNode * uffs_FindFromTree(uffs_Device *dev,
							 u8 type, u16 parent, u16 serial)
{
	switch (type) {
	case UFFS_TYPE_DIR:
		return uffs_TreeFindDirNode(dev, serial);
	case UFFS_TYPE_FILE:
		return uffs_TreeFindFileNode(dev, serial);
	case UFFS_TYPE_DATA:
		return uffs_TreeFindDataNode(dev, parent, serial);
	}
	uffs_Perror(UFFS_MSG_SERIOUS,
				"unkown type, can't find node");
	return NULL;
}
Esempio n. 2
0
/**
 * Open a FindInfo for finding objects under dir
 *
 * \param[out] f uffs_FindInfo structure
 * \param[in] dev uffs device
 * \param[in] dir serial number of the dir to be searched
 *
 * \return U_SUCC if success, U_FAIL if invalid param or the dir
 *			serial number is not valid.
 */
URET uffs_FindObjectOpenEx(uffs_FindInfo *f, uffs_Device *dev, int dir)
{
	TreeNode *node;

	if (f == NULL || dev == NULL)
		return U_FAIL;

	node = uffs_TreeFindDirNode(dev, dir);

	if (node == NULL)
		return U_FAIL;

	f->serial = dir;
	f->dev = dev;
	ResetFindInfo(f);

	return U_SUCC;
}
Esempio n. 3
0
/** 
 * find a free file or dir serial NO
 * \param[in] dev uffs device
 * \return if no free serial found, return #INVALID_UFFS_SERIAL
 */
u16 uffs_FindFreeFsnSerial(uffs_Device *dev)
{
	u16 i;
	TreeNode *node;

	//TODO!! Do we need a faster serial number generating method?
	//		 it depends on how often creating files or directories

	for (i = ROOT_DIR_SERIAL + 1; i < MAX_UFFS_FSN; i++) {
		node = uffs_TreeFindDirNode(dev, i);
		if (node == NULL) {
			node = uffs_TreeFindFileNode(dev, i);
			if (node == NULL) {
				node = uffs_TreeFindSuspendNode(dev, i);
				if (node == NULL)
					return i;
			}
		}
	}

	return INVALID_UFFS_SERIAL;
}
Esempio n. 4
0
File: uffs_fs.c Progetto: mazj/uffs
/**
 * Create an object under the given dir.
 *
 * \param[in|out] obj to be created, 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_CreateObjectEx(uffs_Object *obj, uffs_Device *dev, 
						   int dir, const char *name, int name_len, int oflag)
{
	uffs_Buf *buf = NULL;
	uffs_FileInfo fi;
	TreeNode *node;

	obj->dev = dev;
	obj->parent = dir;
	obj->type = (oflag & UO_DIR ? UFFS_TYPE_DIR : UFFS_TYPE_FILE);
	obj->name = name;
	obj->name_len = name_len;

	if (obj->type == UFFS_TYPE_DIR) {
		if (name[obj->name_len - 1] == '/')		// get rid of ending '/' for dir
			obj->name_len--;
	}
	else {
		if (name[obj->name_len - 1] == '/') {	// file name can't end with '/'
			obj->err = UENOENT;
			goto ext;
		}
	}

	if (obj->name_len == 0) {	// empty name ?
		obj->err = UENOENT;
		goto ext;
	}

	obj->sum = uffs_MakeSum16(obj->name, obj->name_len);

	uffs_ObjectDevLock(obj);

	if (obj->type == UFFS_TYPE_DIR) {
		//find out whether have file with the same name
		node = uffs_TreeFindFileNodeByName(obj->dev, obj->name,
											obj->name_len, obj->sum,
											obj->parent);
		if (node != NULL) {
			obj->err = UEEXIST;	// we can't create a dir has the
								// same name with exist file.
			goto ext_1;
		}
		obj->node = uffs_TreeFindDirNodeByName(obj->dev, obj->name,
												obj->name_len, obj->sum,
												obj->parent);
		if (obj->node != NULL) {
			obj->err = UEEXIST; // we can't create a dir already exist.
			goto ext_1;
		}
	}
	else {
		//find out whether have dir with the same name
		node = uffs_TreeFindDirNodeByName(obj->dev, obj->name,
											obj->name_len, obj->sum,
											obj->parent);
		if (node != NULL) {
			obj->err = UEEXIST;
			goto ext_1;
		}
		obj->node = uffs_TreeFindFileNodeByName(obj->dev, obj->name,
												obj->name_len, obj->sum,
												obj->parent);
		if (obj->node) {
			/* file already exist, truncate it to zero length */
			obj->serial = GET_OBJ_NODE_SERIAL(obj);
			obj->open_succ = U_TRUE; // set open_succ to U_TRUE before
									 // call do_TruncateObject()
			if (do_TruncateObject(obj, 0, eDRY_RUN) == U_SUCC)
				do_TruncateObject(obj, 0, eREAL_RUN);
			goto ext_1;
		}
	}

	/* dir|file does not exist, create a new one */
	obj->serial = uffs_FindFreeFsnSerial(obj->dev);
	if (obj->serial == INVALID_UFFS_SERIAL) {
		uffs_Perror(UFFS_MSG_SERIOUS, "No free serial num!");
		obj->err = UENOMEM;
		goto ext_1;
	}

	if (obj->dev->tree.erased_count < obj->dev->cfg.reserved_free_blocks) {
		uffs_Perror(UFFS_MSG_NOISY,
					"insufficient block in create obj");
		obj->err = UENOMEM;
		goto ext_1;
	}

	buf = uffs_BufNew(obj->dev, obj->type, obj->parent, obj->serial, 0);
	if (buf == NULL) {
		uffs_Perror(UFFS_MSG_SERIOUS,
						"Can't create new buffer when create obj!");
		goto ext_1;
	}

	memset(&fi, 0, sizeof(uffs_FileInfo));
	fi.name_len = obj->name_len < sizeof(fi.name) ? obj->name_len : sizeof(fi.name) - 1;
	memcpy(fi.name, obj->name, fi.name_len);
	fi.name[fi.name_len] = '\0';

	fi.access = 0;
	fi.attr |= FILE_ATTR_WRITE;

	if (obj->type == UFFS_TYPE_DIR)
		fi.attr |= FILE_ATTR_DIR;

	fi.create_time = fi.last_modify = uffs_GetCurDateTime();

	uffs_BufWrite(obj->dev, buf, &fi, 0, sizeof(uffs_FileInfo));
	uffs_BufPut(obj->dev, buf);

	// flush buffer immediately,
	// so that the new node will be inserted into the tree
	uffs_BufFlushGroup(obj->dev, obj->parent, obj->serial);

	// update obj->node: after buf flushed,
	// the NEW node can be found in the tree
	if (obj->type == UFFS_TYPE_DIR)
		obj->node = uffs_TreeFindDirNode(obj->dev, obj->serial);
	else
		obj->node = uffs_TreeFindFileNode(obj->dev, obj->serial);

	if (obj->node == NULL) {
		uffs_Perror(UFFS_MSG_NOISY, "Can't find the node in the tree ?");
		obj->err = UEIOERR;
		goto ext_1;
	}

	if (obj->type == UFFS_TYPE_FILE)
		obj->node->u.file.len = 0;	//init the length to 0

	if (HAVE_BADBLOCK(obj->dev))
		uffs_BadBlockRecover(obj->dev);

	obj->open_succ = U_TRUE;

ext_1:
	uffs_ObjectDevUnLock(obj);
ext:
	return (obj->err == UENOERR ? U_SUCC : U_FAIL);
}