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

📄 yaffsfs.c

📁 yaffs2 lastest sourcecode~~
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. * * Copyright (C) 2002-2007 Aleph One Ltd. *   for Toby Churchill Ltd and Brightstar Engineering * * Created by Charles Manning <charles@aleph1.co.uk> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */#include "yaffsfs.h"#include "yaffs_guts.h"#include "yaffscfg.h"#include <string.h> // for memset#include "yportenv.h"#define YAFFSFS_MAX_SYMLINK_DEREFERENCES 5#ifndef NULL#define NULL ((void *)0)#endifconst char *yaffsfs_c_version="$Id: yaffsfs.c,v 1.25 2009/03/05 01:47:17 charles Exp $";// configurationList is the list of devices that are supportedstatic yaffsfs_DeviceConfiguration *yaffsfs_configurationList;/* Some forward references */static yaffs_Object *yaffsfs_FindObject(yaffs_Object *relativeDirectory, const YCHAR *path, int symDepth);static void yaffsfs_RemoveObjectCallback(yaffs_Object *obj);// Handle management.//unsigned int yaffs_wr_attempts;typedef struct{	__u8  inUse:1;		// this handle is in use	__u8  readOnly:1;	// this handle is read only	__u8  append:1;		// append only	__u8  exclusive:1;	// exclusive	__u32 position;		// current position in file	yaffs_Object *obj;	// the object}yaffsfs_Handle;static yaffsfs_Handle yaffsfs_handle[YAFFSFS_N_HANDLES];// yaffsfs_InitHandle/// Inilitalise handles on start-up.//static int yaffsfs_InitHandles(void){	int i;	for(i = 0; i < YAFFSFS_N_HANDLES; i++)	{		yaffsfs_handle[i].inUse = 0;		yaffsfs_handle[i].obj = NULL;	}	return 0;}yaffsfs_Handle *yaffsfs_GetHandlePointer(int h){	if(h < 0 || h >= YAFFSFS_N_HANDLES)	{		return NULL;	}	return &yaffsfs_handle[h];}yaffs_Object *yaffsfs_GetHandleObject(int handle){	yaffsfs_Handle *h = yaffsfs_GetHandlePointer(handle);	if(h && h->inUse)	{		return h->obj;	}	return NULL;}//yaffsfs_GetHandle// Grab a handle (when opening a file)//static int yaffsfs_GetHandle(void){	int i;	yaffsfs_Handle *h;	for(i = 0; i < YAFFSFS_N_HANDLES; i++)	{		h = yaffsfs_GetHandlePointer(i);		if(!h)		{			// todo bug: should never happen		}		if(!h->inUse)		{			memset(h,0,sizeof(yaffsfs_Handle));			h->inUse=1;			return i;		}	}	return -1;}// yaffs_PutHandle// Let go of a handle (when closing a file)//static int yaffsfs_PutHandle(int handle){	yaffsfs_Handle *h = yaffsfs_GetHandlePointer(handle);	if(h)	{		h->inUse = 0;		h->obj = NULL;	}	return 0;}// Stuff to search for a directory from a pathint yaffsfs_Match(YCHAR a, YCHAR b){	// case sensitive	return (a == b);}int yaffsfs_IsPathDivider(YCHAR ch){	YCHAR *str = YAFFS_PATH_DIVIDERS;	while(*str){		if(*str == ch)			return 1;		str++;	}	return 0;}// yaffsfs_FindDevice// yaffsfs_FindRoot// Scan the configuration list to find the root.// Curveballs: Should match paths that end in '/' too// Curveball2 Might have "/x/ and "/x/y". Need to return the longest matchstatic yaffs_Device *yaffsfs_FindDevice(const YCHAR *path, YCHAR **restOfPath){	yaffsfs_DeviceConfiguration *cfg = yaffsfs_configurationList;	const YCHAR *leftOver;	const YCHAR *p;	yaffs_Device *retval = NULL;	int thisMatchLength;	int longestMatch = -1;	int matching;	// Check all configs, choose the one that:	// 1) Actually matches a prefix (ie /a amd /abc will not match	// 2) Matches the longest.	while(cfg && cfg->prefix && cfg->dev)	{		leftOver = path;		p = cfg->prefix;		thisMatchLength = 0;		matching = 1;		while(matching && *p && *leftOver){			// Skip over any /s			while(yaffsfs_IsPathDivider(*p))			      p++;			// Skip over any /s			while(yaffsfs_IsPathDivider(*leftOver))		              leftOver++;			// Now match the text part		        while(matching &&		              *p && !yaffsfs_IsPathDivider(*p) &&		              *leftOver && !yaffsfs_IsPathDivider(*leftOver)){			      	if(yaffsfs_Match(*p,*leftOver)){			      		p++;			      		leftOver++;			      		thisMatchLength++;				} else {					matching = 0;				}			}		}		// Skip over any /s in leftOver		while(yaffsfs_IsPathDivider(*leftOver))	              leftOver++;				if( matching && (thisMatchLength > longestMatch))		{			// Matched prefix			*restOfPath = (YCHAR *)leftOver;			retval = cfg->dev;			longestMatch = thisMatchLength;		}		cfg++;	}	return retval;}#if 0static yaffs_Device *yaffsfs_FindDevice(const YCHAR *path, YCHAR **restOfPath){	yaffsfs_DeviceConfiguration *cfg = yaffsfs_configurationList;	const YCHAR *leftOver;	const YCHAR *p;	yaffs_Device *retval = NULL;	int thisMatchLength;	int longestMatch = -1;	// Check all configs, choose the one that:	// 1) Actually matches a prefix (ie /a amd /abc will not match	// 2) Matches the longest.	while(cfg && cfg->prefix && cfg->dev)	{		leftOver = path;		p = cfg->prefix;		thisMatchLength = 0;		while(*p &&  //unmatched part of prefix		      !(yaffsfs_IsPathDivider(*p) && (p[1] == 0)) && // the rest of the prefix is not / (to catch / at end)		      *leftOver &&		      yaffsfs_Match(*p,*leftOver))		{			p++;			leftOver++;			thisMatchLength++;		}		if((!*p || (yaffsfs_IsPathDivider(*p) && (p[1] == 0))) &&      // end of prefix		   (!*leftOver || yaffsfs_IsPathDivider(*leftOver)) && // no more in this path name part		   (thisMatchLength > longestMatch))		{			// Matched prefix			*restOfPath = (YCHAR *)leftOver;			retval = cfg->dev;			longestMatch = thisMatchLength;		}		cfg++;	}	return retval;}#endifstatic yaffs_Object *yaffsfs_FindRoot(const YCHAR *path, YCHAR **restOfPath){	yaffs_Device *dev;	dev= yaffsfs_FindDevice(path,restOfPath);	if(dev && dev->isMounted)	{		return dev->rootDir;	}	return NULL;}static yaffs_Object *yaffsfs_FollowLink(yaffs_Object *obj,int symDepth){	while(obj && obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK)	{		YCHAR *alias = obj->variant.symLinkVariant.alias;		if(yaffsfs_IsPathDivider(*alias))		{			// Starts with a /, need to scan from root up			obj = yaffsfs_FindObject(NULL,alias,symDepth++);		}		else		{			// Relative to here, so use the parent of the symlink as a start			obj = yaffsfs_FindObject(obj->parent,alias,symDepth++);		}	}	return obj;}// yaffsfs_FindDirectory// Parse a path to determine the directory and the name within the directory.//// eg. "/data/xx/ff" --> puts name="ff" and returns the directory "/data/xx"static yaffs_Object *yaffsfs_DoFindDirectory(yaffs_Object *startDir,const YCHAR *path,YCHAR **name,int symDepth){	yaffs_Object *dir;	YCHAR *restOfPath;	YCHAR str[YAFFS_MAX_NAME_LENGTH+1];	int i;	if(symDepth > YAFFSFS_MAX_SYMLINK_DEREFERENCES)	{		return NULL;	}	if(startDir)	{		dir = startDir;		restOfPath = (YCHAR *)path;	}	else	{		dir = yaffsfs_FindRoot(path,&restOfPath);	}	while(dir)	{		// parse off /.		// curve ball: also throw away surplus '/'		// eg. "/ram/x////ff" gets treated the same as "/ram/x/ff"		while(yaffsfs_IsPathDivider(*restOfPath))		{			restOfPath++; // get rid of '/'		}		*name = restOfPath;		i = 0;		while(*restOfPath && !yaffsfs_IsPathDivider(*restOfPath))		{			if (i < YAFFS_MAX_NAME_LENGTH)			{				str[i] = *restOfPath;				str[i+1] = '\0';				i++;			}			restOfPath++;		}		if(!*restOfPath)		{			// got to the end of the string			return dir;		}		else		{			if(yaffs_strcmp(str,_Y(".")) == 0)			{				// Do nothing			}			else if(yaffs_strcmp(str,_Y("..")) == 0)			{				dir = dir->parent;			}			else			{				dir = yaffs_FindObjectByName(dir,str);				while(dir && dir->variantType == YAFFS_OBJECT_TYPE_SYMLINK)				{					dir = yaffsfs_FollowLink(dir,symDepth);				}				if(dir && dir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY)				{					dir = NULL;				}			}		}	}	// directory did not exist.	return NULL;}static yaffs_Object *yaffsfs_FindDirectory(yaffs_Object *relativeDirectory,const YCHAR *path,YCHAR **name,int symDepth){	return yaffsfs_DoFindDirectory(relativeDirectory,path,name,symDepth);}// yaffsfs_FindObject turns a path for an existing object into the object//static yaffs_Object *yaffsfs_FindObject(yaffs_Object *relativeDirectory, const YCHAR *path,int symDepth){	yaffs_Object *dir;	YCHAR *name;	dir = yaffsfs_FindDirectory(relativeDirectory,path,&name,symDepth);	if(dir && *name)	{		return yaffs_FindObjectByName(dir,name);	}	return dir;}int yaffs_dup(int fd){	int newHandle = -1;	yaffsfs_Handle *oldPtr = NULL;	yaffsfs_Handle *newPtr = NULL;	yaffsfs_Lock();	oldPtr = yaffsfs_GetHandlePointer(fd);	if(oldPtr && oldPtr->inUse)		newHandle = yaffsfs_GetHandle();	if(newHandle >= 0)		newPtr = yaffsfs_GetHandlePointer(newHandle);	if(newPtr){		*newPtr = *oldPtr;		return newHandle;	}	if(!oldPtr)		yaffsfs_SetError(-EBADF);	else		yaffsfs_SetError(-ENOMEM);	return -1;}int yaffs_open(const YCHAR *path, int oflag, int mode){	yaffs_Object *obj = NULL;	yaffs_Object *dir = NULL;	YCHAR *name;	int handle = -1;	yaffsfs_Handle *h = NULL;	int alreadyOpen = 0;	int alreadyExclusive = 0;	int openDenied = 0;	int symDepth = 0;	int errorReported = 0;	int i;	// todo sanity check oflag (eg. can't have O_TRUNC without WRONLY or RDWR	yaffsfs_Lock();	handle = yaffsfs_GetHandle();	if(handle >= 0)	{		h = yaffsfs_GetHandlePointer(handle);		// try to find the exisiting object		obj = yaffsfs_FindObject(NULL,path,0);		if(obj && obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK)		{			obj = yaffsfs_FollowLink(obj,symDepth++);		}		if(obj && obj->variantType != YAFFS_OBJECT_TYPE_FILE)		{			obj = NULL;		}		if(obj)		{			// Check if the object is already in use			alreadyOpen = alreadyExclusive = 0;			for(i = 0; i < YAFFSFS_N_HANDLES; i++)			{				if(i != handle &&				   yaffsfs_handle[i].inUse &&				    obj == yaffsfs_handle[i].obj)				 {				 	alreadyOpen = 1;					if(yaffsfs_handle[i].exclusive)					{						alreadyExclusive = 1;					}				 }			}			if(((oflag & O_EXCL) && alreadyOpen) || alreadyExclusive)			{				openDenied = 1;			}			// Open should fail if O_CREAT and O_EXCL are specified			if((oflag & O_EXCL) && (oflag & O_CREAT))			{				openDenied = 1;				yaffsfs_SetError(-EEXIST);				errorReported = 1;			}			// Check file permissions			if( (oflag & (O_RDWR | O_WRONLY)) == 0 &&     // ie O_RDONLY			   !(obj->yst_mode & S_IREAD))			{				openDenied = 1;			}			if( (oflag & O_RDWR) &&			   !(obj->yst_mode & S_IREAD))			{				openDenied = 1;			}			if( (oflag & (O_RDWR | O_WRONLY)) &&			   !(obj->yst_mode & S_IWRITE))			{				openDenied = 1;			}		}		else if((oflag & O_CREAT))		{			// Let's see if we can create this file			dir = yaffsfs_FindDirectory(NULL,path,&name,0);			if(dir)			{				obj = yaffs_MknodFile(dir,name,mode,0,0);			}			else			{				yaffsfs_SetError(-ENOTDIR);				errorReported = 1;			}		}		if(obj && !openDenied)		{			h->obj = obj;			h->inUse = 1;	    	h->readOnly = (oflag & (O_WRONLY | O_RDWR)) ? 0 : 1;			h->append =  (oflag & O_APPEND) ? 1 : 0;			h->exclusive = (oflag & O_EXCL) ? 1 : 0;			h->position = 0;                        obj->inUse++;                        if((oflag & O_TRUNC) && !h->readOnly)                        {                                yaffs_ResizeFile(obj,0);                        }		}		else		{			yaffsfs_PutHandle(handle);			if(!errorReported)			{				yaffsfs_SetError(-EACCES);				errorReported = 1;			}			handle = -1;		}	}	yaffsfs_Unlock();	return handle;}int yaffs_flush(int fd){	yaffsfs_Handle *h = NULL;	int retVal = 0;	yaffsfs_Lock();	h = yaffsfs_GetHandlePointer(fd);	if(h && h->inUse)	{		// flush the file		yaffs_FlushFile(h->obj,1);	}	else	{		// bad handle		yaffsfs_SetError(-EBADF);		retVal = -1;	}	yaffsfs_Unlock();	return retVal;}int yaffs_close(int fd){	yaffsfs_Handle *h = NULL;	int retVal = 0;	yaffsfs_Lock();	h = yaffsfs_GetHandlePointer(fd);	if(h && h->inUse)	{		// clean up		yaffs_FlushFile(h->obj,1);		h->obj->inUse--;		if(h->obj->inUse <= 0 && h->obj->unlinked)		{			yaffs_DeleteObject(h->obj);		}		yaffsfs_PutHandle(fd);		retVal = 0;	}	else	{		// bad handle		yaffsfs_SetError(-EBADF);		retVal = -1;	}	yaffsfs_Unlock();	return retVal;}int yaffs_read(int fd, void *buf, unsigned int nbyte){	yaffsfs_Handle *h = NULL;	yaffs_Object *obj = NULL;	int pos = 0;	int nRead = -1;	unsigned int maxRead;	yaffsfs_Lock();	h = yaffsfs_GetHandlePointer(fd);	obj = yaffsfs_GetHandleObject(fd);	if(!h || !obj)	{		// bad handle		yaffsfs_SetError(-EBADF);	}	else if( h && obj)

⌨️ 快捷键说明

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