⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fsmdfs.c

📁 norflash的文件系统。 用于中低端手机开发的参考
💻 C
📖 第 1 页 / 共 5 页
字号:
	FsmDfsFileDescriptorT *	FdP;


	FdP = &FsmDfsFds[fd];

	if(FdP->Flag != DFD_FLAG_IN_USE)
	{
		return ERR_PARAM;
	}

	/* Get the semaphore of this file. */
	status = FsmGetMtxSem(FdP->MutexSem);

	if(status != ERR_NONE)
	{
		return status;
	}

	/* CHECK if the fd is in PENDING or FREE state. */
	if(FdP->Flag != DFD_FLAG_IN_USE)
	{
		FsmReleaseMtxSem(FdP->MutexSem);
		return ERR_PARAM;
	}

	if (FdP->Attrib == ENTRY_TYPE_SUBDIR)
	{
		FsmReleaseMtxSem(FdP->MutexSem);
		return ERR_PARAM;
	}

	status = ERR_PARAM;

	if (arg->whence == FSM_FILE_BEGIN)
	{
		if ((arg->offset >= 0) && ((uint32)arg->offset <= FdP->FileLength))
		{
			FdP->FilePointer = arg->offset;
			status = ERR_NONE;
		}
	}
	else if (arg->whence == FSM_FILE_END)
	{
		if ((arg->offset <= 0) && (FdP->FileLength >= (uint32)(-arg->offset)))
		{
			FdP->FilePointer = FdP->FileLength - (uint32)(-arg->offset);
			status = ERR_NONE;
		}
	}
	else if (arg->whence == FSM_FILE_CURRENT)
	{
		if ((arg->offset >= 0)
			&& ((arg->offset + FdP->FilePointer) <= FdP->FileLength))
		{
			FdP->FilePointer = arg->offset + FdP->FilePointer;
			status = ERR_NONE;
		}
		else if((arg->offset < 0)
				&& (FdP->FilePointer >= (uint32)(-arg->offset)))
		{
			FdP->FilePointer = FdP->FilePointer - (uint32)(-arg->offset);
			status = ERR_NONE;
		}
	}

	FsmReleaseMtxSem(FdP->MutexSem);

	return status;
}

/*  */
uint32  DfsFileGetAttrib(uint32 fd, FsmFileAttribT * attrib)
{
	uint32		status;

	/* Get the semaphore of this file. */
	status = FsmGetMtxSem(FsmDfsFds[fd].MutexSem);

	if(status != ERR_NONE)
	{
		return status;
	}

	attrib->FileLength = FsmDfsFds[fd].FileLength;
	attrib->CreateDate = FsmDfsFds[fd].CreateDate;
	attrib->CreateTime = FsmDfsFds[fd].CreateTime;
	attrib->Attrib     = FsmDfsFds[fd].Attrib;

	FsmReleaseMtxSem(FsmDfsFds[fd].MutexSem);

    switch(attrib->Attrib)
    {
	case ENTRY_TYPE_SUBDIR:
		attrib->Attrib = FSM_FILE_ATTRIB_DIR;
		break;

	case ENTRY_TYPE_FILE:
		attrib->Attrib = FSM_FILE_ATTRIB_ARCHIVE;
		break;

	default:
#if (OS_TYPE == OS_WINDOWS)
		ASSERT(0);
#endif
		break;
    }

	return ERR_NONE;
}

/* implement the Truncate */
uint32 DfsFileTruncate(uint32 fd, uint32 size)
{
	uint32		status;
	uint32		AvailSpace;
	uint32		needSpace;

	FsmDfsFileDescriptorT *	FdP;

	FdP = &FsmDfsFds[fd];

	if(FdP->Flag != DFD_FLAG_IN_USE)
	{
		return ERR_PARAM;
	}

	/* Get the semaphore of this file. */
	status = FsmGetMtxSem(FdP->MutexSem);

	if(status != ERR_NONE)
	{
		return status;
	}

	/* CHECK if the fd is in PENDING or FREE state. */
	if(FdP->Flag != DFD_FLAG_IN_USE)
	{
		FsmReleaseMtxSem(FdP->MutexSem);
		return ERR_PARAM;
	}

	if (FdP->Attrib == ENTRY_TYPE_SUBDIR)
	{
		FsmReleaseMtxSem(FdP->MutexSem);
		return ERR_ACCESS_DENY;
	}

	if ((FdP->AccessMode & FSM_OPEN_WRITE) != FSM_OPEN_WRITE)
	{
		FsmReleaseMtxSem(FdP->MutexSem);
		return ERR_ACCESS_DENY;
	}

	if (FdP->FileLength == size)
	{
		FsmReleaseMtxSem(FdP->MutexSem);
		return ERR_NONE;
	}

	if (FdP->FileLength < size)
	{
		FsmReleaseMtxSem(FdP->MutexSem);
		return ERR_PARAM;
	}

#ifdef DFS_DIR_LOCK_ENABLED


	/* !!!!!!!!!!  NOTE  !!!!!!!!!*/
	/*
	 *  We have kept the file semaphore.
	 *  Care should be taken to avoid deadlock.
	 */
	/* check the directory operation */
	if ((status = FsmGetMtxSem(FsmDfsMtxSem)) != ERR_NONE)
	{
		FsmReleaseMtxSem(FdP->MutexSem);
		return status;
	}

	if (DfsIsParentDirOpened(FsmDfsFds[fd].PathName) != 0)
	{
		FsmReleaseMtxSem(FsmDfsMtxSem);
		FsmReleaseMtxSem(FdP->MutexSem);
		return ERR_ACCESS_DENY;
	}

	FsmReleaseMtxSem(FsmDfsMtxSem); 

#endif /* DFS_DIR_LOCK_ENABLED */


	AvailSpace = DfsAvailSpaceCalc((FsmFlashMediaT *)FdP->FdHdr.DevObjP->MediaObjP);

	needSpace = ACCUM_CNT_TRUNCATE;

	if (AvailSpace < needSpace)
	{
		FsmReleaseMtxSem(FdP->MutexSem);

		return ERR_FULL;
	}

	status = QueueAddFileDir(CMD_TRUNCATE, fd, size, NULL, 0);

	if (status == ERR_NONE)
	{
		FdP->FileLength = size;

		if(FdP->FilePointer > size)
			FdP->FilePointer = size;
	}

	FsmReleaseMtxSem(FdP->MutexSem);

	return status;
}

/*
 * rename a file or a directory.
 */
uint32 DfsFileRename(FsmIoctlRenameT * arg)
{
	uint32				status;
	FsmFileDirEntryT	entry;
    uint32				AvailSpace;
    uint32				needSpace;
	uint32				ParentDirFirstLsn;
	uint32				fd;
	uint32				len;

	char			newpath[DFS_MAX_PATH_LEN + 1];


	len = strlen((char *)arg->path);

	if(len > DFS_MAX_PATH_LEN)
	{
		return ERR_PARAM;
	}

	/* Is it root directory ? */
	if ((len == 1)
		&& ((*(arg->path) == '\\') || (*(arg->path) == '/')))
	{
		return ERR_ACCESS_DENY;
	}

	if(arg->newname == NULL)
	{
		return ERR_PARAM;
	}

	len = strlen(arg->newname);

	if((len == 0) || (len > DFS_MAX_FILE_NAME_LEN))
	{
		return ERR_PARAM;
	}

	if(ExtractDir(arg->path, &len) != 0)
	{
		if((len + strlen(arg->newname)) > DFS_MAX_PATH_LEN)
		{
			return ERR_PARAM;
		}
		else if(len > 0)
		{
			FsmMemoryMove((uint8 *)newpath, (uint8 *)arg->path, len);
			newpath[len] = 0;
			strcat(newpath, arg->newname);
		}
		else
		{
			return ERR_PARAM;
		}
	}
	else
	{
		return ERR_PARAM;
	}

	if((status = FsmGetMtxSem(FsmDfsMtxSem)) != ERR_NONE)
	{
		return status;
	}

	if(DfsIsFileOpened((char *)arg->path) != INVALID_FILE_HANDLE)
	{
		FsmReleaseMtxSem(FsmDfsMtxSem);
		return ERR_ACCESS_DENY;
	}

	if(DfsIsFileOpened((char *)newpath) != INVALID_FILE_HANDLE)
	{
		FsmReleaseMtxSem(FsmDfsMtxSem);
		return ERR_EXIST;
	}

#ifdef DFS_DIR_LOCK_ENABLED

	if (DfsIsParentDirOpened((char *)arg->path) != 0)
	{
		FsmReleaseMtxSem(FsmDfsMtxSem);
		return ERR_ACCESS_DENY;
	}

#endif /* DFS_DIR_LOCK_ENABLED */


	if ((fd = DfsAllocFd()) == INVALID_FILE_HANDLE)
	{
		FsmReleaseMtxSem(FsmDfsMtxSem);
		return ERR_MAX_OPEN;
	}

	FsmDfsFds[fd].AccessMode = FSM_OPEN_WRITE;
	FsmDfsFds[fd].FdHdr.DevObjP = arg->DevObjP;	/* prevent this device from being unmounted. */
	strcpy(FsmDfsFds[fd].PathName, arg->path);

	FsmReleaseMtxSem(FsmDfsMtxSem);

	status = FsmGetMtxSem(FsmDfsFds[fd].MutexSem);

	if(status != ERR_NONE)
	{
		DfsFreeFd(fd);
		return status;
	}

	/* check if the new name file exist. */
	status = DfsLocateFile(arg->DevObjP, newpath, &ParentDirFirstLsn, &entry);

	if (status == ERR_NONE)
	{
		/* new name exists. */
		FsmReleaseMtxSem(FsmDfsFds[fd].MutexSem);
		DfsFreeFd(fd);
		return ERR_EXIST;
	}

	/* check if the old filename exists. */
	status = DfsLocateFile(arg->DevObjP, (char *)arg->path, &ParentDirFirstLsn, &entry);

	if(status != ERR_NONE)
	{
		/* file doesn't exist. */
		FsmReleaseMtxSem(FsmDfsFds[fd].MutexSem);
		DfsFreeFd(fd);
		return ERR_NOTEXIST;
	}

	/*  */
	FsmDfsFds[fd].FileLength = entry.Length;
	FsmDfsFds[fd].FirstLsn   = entry.FirstLsn;
	FsmDfsFds[fd].ParentDirFirstLsn = ParentDirFirstLsn;
	FsmDfsFds[fd].FilePointer = 0;
	FsmDfsFds[fd].CreateDate  = entry.Date;
	FsmDfsFds[fd].CreateTime  = entry.Time;
	FsmDfsFds[fd].Attrib      = entry.Type;

	AvailSpace = DfsAvailSpaceCalc((FsmFlashMediaT *)FsmDfsFds[fd].FdHdr.DevObjP->MediaObjP);

	needSpace = ACCUM_CNT_RENAME;

	if (AvailSpace < needSpace)
	{
		FsmReleaseMtxSem(FsmDfsFds[fd].MutexSem);
	    DfsFreeFd(fd);
		return ERR_FULL;
	}

	status = QueueAddFileDir(CMD_RENAME, fd, 0, (uint8 *)arg->newname, strlen(arg->newname) + 1);
											 /* Added '1' for the NULL-terminated string -----^ */

	if (status != ERR_NONE)
	{
		FsmReleaseMtxSem(FsmDfsFds[fd].MutexSem);
		DfsFreeFd(fd);
		return status;
	}

	WaitFdEmpty(fd, WAIT_FOREVER);
	FsmReleaseMtxSem(FsmDfsFds[fd].MutexSem);
	DfsFreeFd(fd);

	return ERR_NONE;
}

uint32 DfsFileFlush(uint32 fd)
{
	uint32		status;

	FsmDfsFileDescriptorT *	FdP;

	FdP = &FsmDfsFds[fd];

	if(FdP->Flag != DFD_FLAG_IN_USE)
	{
		return ERR_PARAM;
	}

	/* Get the semaphore of this file. */
	status = FsmGetMtxSem(FdP->MutexSem);

	if(status != ERR_NONE)
	{
		return status;
	}

	/* CHECK if the fd is in PENDING or FREE state. */
	if(FdP->Flag != DFD_FLAG_IN_USE)
	{
		FsmReleaseMtxSem(FdP->MutexSem);
		return ERR_PARAM;
	}

	WaitFdEmpty(fd, WAIT_FOREVER);
	FsmReleaseMtxSem(FsmDfsFds[fd].MutexSem);

	return ERR_NONE;
}

uint32 DfsGetVolumeFreeSpace(FsmIoctlGetFreeSpaceT* arg)
{
	FsmFlashMediaT *	MediaP;
	FsmFlashDevT *		DevP;

	DevP = (FsmFlashDevT *)arg->DevObjP;
	MediaP = (FsmFlashMediaT *)arg->DevObjP->MediaObjP;

	*(arg->total_space) = (DevP->Blocks - 1) * MediaP->SectorSize * MediaP->SectorsPerBlock;

	*(arg->avail_space) = DfsAvailSpaceCalc(MediaP);
	*(arg->avail_space) *= MediaP->SectorSize;

	*(arg->free_space)  = *(arg->avail_space);

	return ERR_NONE;
}

uint32 DfsFormat(FsmDevObjHdrT * DevObjP)
{
	uint16		i;
	uint32		status;
	uint32		Address;
	uint32		FsmTag;

	DEV_WRITE_FUNCPTR	DevWrite;

	if(DevObjP == NULL)
	{
		return ERR_PARAM;
	}

	DevWrite = DevObjP->DevDrvP->FsmDevWrite;

	if (DevWrite == NULL)
	{
		return ERR_SYSTEM;
	}

	FsmTag = 0;

	Address = ((FsmFlashDevT *)DevObjP)->BlockSize;
	Address -= (sizeof(FsmBlockInfoT) - FIELD_OFFSET(FsmBlockInfoT, Tag));

	for (i = 0; i < ((FsmFlashDevT *)DevObjP)->Blocks; i++)
	{
		status = DevWrite( DevObjP,
				    		(uint8 *)&FsmTag,
							Address,
							FIELD_SIZE(FsmBlockInfoT, Tag)
							);

		if (status != ERR_NONE)
		{
			return status;
		}

		Address += ((FsmFlashDevT *)DevObjP)->BlockSize;
	}

	return ERR_NONE;
}

#if 0
/* for wear-level test only. */
uint32 DfsGetBlockInfo(FsmDevObjHdrT * DevObjP, uint32 * EraseNum)
{
    uint16                  i;
    FsmFlashMediaT          * MediaP;
    FsmBlockStatisticT      * BlkInfoP;
    
    if(DevObjP == NULL)
    {
        return ERR_SYSTEM;
    }
    
    MediaP = DevObjP->MediaObjP;
    
    if (MediaP == NULL)
    {
        return ERR_SYSTEM;
    }
    
    BlkInfoP = MediaP->BlockInfoP;
    
    for (i = 0; i < ((FsmFlashDevT *)DevObjP)->Blocks; i++)
    {
        EraseNum[i] = BlkInfoP[i].EraseCount; 
	}

	return ERR_NONE;
}
#endif

/************************************** help functions ************************************/

/* locate file in the flash. */
static uint32 DfsLocateFile(
	FsmDevObjHdrT * DevP,
	char *		path,
	uint32 *	ParentDirFirstLsn,
	FsmFileDirEntryT *	entry
	)
{
	uint32		status = ERR_PARAM;

	uint32		FirstLsn;

	uint32		SectorLsn;
	uint32		sector_offset;

	uint32		name_len;
	uint32		offset;
	uint32		start;
	uint32		dir_name_len;
	uint32		max_name_len = FIELD_SIZE(FsmFileDirEntryT, FileName);

	char		dirname[FIELD_SIZE(FsmFileDirEntryT, FileName) + 1];
	char		read_dirname[FIELD_SIZE(FsmFileDirEntryT, FileName) + 1];

#ifdef FSM_DEBUG
	MonPrintf("Enter the DfsLocateFile\n");
#endif

	if(path == NULL)
	{
		return ERR_PARAM;
	}

	name_len = strlen(path);

	if(name_len == 0)
	{
		return ERR_PARAM;
	}

	FsmMemorySet((uint8 *)entry, 0, sizeof(FsmFileDirEntryT));

	if(name_len == 1)
	{
		if((*path == '/') || (*path == '\\'))
		{
			/* it is root directory. */
			entry->FirstLsn = 0;
			entry->Length = 0;
			entry->Status = ENTRY_VALID;
			entry->Type = ENTRY_TYPE_SUBDIR;

			*ParentDirFirstLsn = (uint32)(-1);

			return ERR_NONE;
		}
	}

	*ParentDirFirstLsn = (uint32)(-1);

	FirstLsn = 0;

	SectorLsn = FirstLsn;
	sector_offset = 0;

	offset = 0;
	start  = 0;

	dir_name_len = 0;

	GetFirstPath(&path[offset], &start, &dir_name_len);

	if(dir_name_len > max_name_len)
	{
		return ERR_PARAM;
	}

	FsmMemoryMove((uint8 *)dirname, (uint8 *)&path[offset + start], dir_name_len);
	dirname[dir_name_len] = 0;

	while(offset < name_len)
	{
		status = DfsReadFileEntry(DevP, &SectorLsn, &sector_offset, entry);

		if(status != ERR_NONE)
		{
			break;
		}

		FsmMemoryMove((uint8 *)read_dirname, 
					  (uint8 *)entry->FileName, 
					  FIELD_SIZE(FsmFileDirEntryT, FileName)
					  );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -