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

📄 dosfs.c

📁 代码,来自google,关于FAT16/32文件系统编程源代码!适合初合者学习,有很全的注释!
💻 C
📖 第 1 页 / 共 3 页
字号:
		fileinfo->cluster = cluster;
		fileinfo->firstcluster = cluster;
		fileinfo->filelen = 0;
		
		// write the directory entry
		// note that we no longer have the sector containing the directory entry,
		// tragically, so we have to re-read it
		if (DFS_ReadSector(volinfo->unit, scratch, fileinfo->dirsector, 1))
			return DFS_ERRMISC;
		memcpy(&(((PDIRENT) scratch)[di.currententry-1]), &de, sizeof(DIRENT));
		if (DFS_WriteSector(volinfo->unit, scratch, fileinfo->dirsector, 1))
			return DFS_ERRMISC;

		// Mark newly allocated cluster as end of chain			
		switch(volinfo->filesystem) {
			case FAT12:		cluster = 0xff8;	break;
			case FAT16:		cluster = 0xfff8;	break;
			case FAT32:		cluster = 0x0ffffff8;	break;
			default:		return DFS_ERRMISC;
		}
		temp = 0;
		DFS_SetFAT(volinfo, scratch, &temp, fileinfo->cluster, cluster);

		return DFS_OK;
	}

	return DFS_NOTFOUND;
}

/*
	Read an open file
	You must supply a prepopulated FILEINFO as provided by DFS_OpenFile, and a
	pointer to a SECTOR_SIZE scratch buffer.
	Note that returning DFS_EOF is not an error condition. This function updates the
	successcount field with the number of bytes actually read.
*/
uint32_t DFS_ReadFile(PFILEINFO fileinfo, uint8_t *scratch, uint8_t *buffer, uint32_t *successcount, uint32_t len)
{
	uint32_t remain;
	uint32_t result = DFS_OK;
	uint32_t sector;
	uint32_t bytesread;

	// Don't try to read past EOF
	if (len > fileinfo->filelen - fileinfo->pointer)
		len = fileinfo->filelen - fileinfo->pointer;

	remain = len;
	*successcount = 0;

	while (remain && result == DFS_OK) {
		// This is a bit complicated. The sector we want to read is addressed at a cluster
		// granularity by the fileinfo->cluster member. The file pointer tells us how many
		// extra sectors to add to that number.
		sector = fileinfo->volinfo->dataarea +
		  ((fileinfo->cluster - 2) * fileinfo->volinfo->secperclus) +
		  div(div(fileinfo->pointer,fileinfo->volinfo->secperclus * SECTOR_SIZE).rem, SECTOR_SIZE).quot;

		// Case 1 - File pointer is not on a sector boundary
		if (div(fileinfo->pointer, SECTOR_SIZE).rem) {
			uint16_t tempreadsize;

			// We always have to go through scratch in this case
			result = DFS_ReadSector(fileinfo->volinfo->unit, scratch, sector, 1);

			// This is the number of bytes that we actually care about in the sector
			// just read.
			tempreadsize = SECTOR_SIZE - (div(fileinfo->pointer, SECTOR_SIZE).rem);
					
			// Case 1A - We want the entire remainder of the sector. After this
			// point, all passes through the read loop will be aligned on a sector
			// boundary, which allows us to go through the optimal path 2A below.
		   	if (remain >= tempreadsize) {
				memcpy(buffer, scratch + (SECTOR_SIZE - tempreadsize), tempreadsize);
				bytesread = tempreadsize;
				buffer += tempreadsize;
				fileinfo->pointer += tempreadsize;
				remain -= tempreadsize;
			}
			// Case 1B - This read concludes the file read operation
			else {
				memcpy(buffer, scratch + (SECTOR_SIZE - tempreadsize), remain);

				buffer += remain;
				fileinfo->pointer += remain;
				bytesread = remain;
				remain = 0;
			}
		}
		// Case 2 - File pointer is on sector boundary
		else {
			// Case 2A - We have at least one more full sector to read and don't have
			// to go through the scratch buffer. You could insert optimizations here to
			// read multiple sectors at a time, if you were thus inclined (note that
			// the maximum multi-read you could perform is a single cluster, so it would
			// be advantageous to have code similar to case 1A above that would round the
			// pointer to a cluster boundary the first pass through, so all subsequent
			// [large] read requests would be able to go a cluster at a time).
			if (remain >= SECTOR_SIZE) {
				result = DFS_ReadSector(fileinfo->volinfo->unit, buffer, sector, 1);
				remain -= SECTOR_SIZE;
				buffer += SECTOR_SIZE;
				fileinfo->pointer += SECTOR_SIZE;
				bytesread = SECTOR_SIZE;
			}
			// Case 2B - We are only reading a partial sector
			else {
				result = DFS_ReadSector(fileinfo->volinfo->unit, scratch, sector, 1);
				memcpy(buffer, scratch, remain);
				buffer += remain;
				fileinfo->pointer += remain;
				bytesread = remain;
				remain = 0;
			}
		}

		*successcount += bytesread;

		// check to see if we stepped over a cluster boundary
		if (div(fileinfo->pointer - bytesread, fileinfo->volinfo->secperclus * SECTOR_SIZE).quot !=
		  div(fileinfo->pointer, fileinfo->volinfo->secperclus * SECTOR_SIZE).quot) {
			// An act of minor evil - we use bytesread as a scratch integer, knowing that
			// its value is not used after updating *successcount above
			bytesread = 0;
			if (((fileinfo->volinfo->filesystem == FAT12) && (fileinfo->cluster >= 0xff8)) ||
			  ((fileinfo->volinfo->filesystem == FAT16) && (fileinfo->cluster >= 0xfff8)) ||
			  ((fileinfo->volinfo->filesystem == FAT32) && (fileinfo->cluster >= 0x0ffffff8)))
				result = DFS_EOF;
			else
				fileinfo->cluster = DFS_GetFAT(fileinfo->volinfo, scratch, &bytesread, fileinfo->cluster);
		}
	}
	
	return result;
}

/*
	Seek file pointer to a given position
	This function does not return status - refer to the fileinfo->pointer value
	to see where the pointer wound up.
	Requires a SECTOR_SIZE scratch buffer
*/
void DFS_Seek(PFILEINFO fileinfo, uint32_t offset, uint8_t *scratch)
{
	uint32_t tempint;

	// larwe 9/16/06 bugfix split case 0a/0b and changed fallthrough handling
	// Case 0a - Return immediately for degenerate case
	if (offset == fileinfo->pointer) {
		return;
	}
	
	// Case 0b - Don't allow the user to seek past the end of the file
	if (offset > fileinfo->filelen) {
		offset = fileinfo->filelen;
		// NOTE NO RETURN HERE!
	}

	// Case 1 - Simple rewind to start
	// Note _intentional_ fallthrough from Case 0b above
	if (offset == 0) {
		fileinfo->cluster = fileinfo->firstcluster;
		fileinfo->pointer = 0;
		return;		// larwe 9/16/06 +1 bugfix
	}
	// Case 2 - Seeking backwards. Need to reset and seek forwards
	else if (offset < fileinfo->pointer) {
		fileinfo->cluster = fileinfo->firstcluster;
		fileinfo->pointer = 0;
		// NOTE NO RETURN HERE!
	}

	// Case 3 - Seeking forwards
	// Note _intentional_ fallthrough from Case 2 above

	// Case 3a - Seek size does not cross cluster boundary - 
	// very simple case
	// larwe 9/16/06 changed .rem to .quot in both div calls, bugfix
	if (div(fileinfo->pointer, fileinfo->volinfo->secperclus * SECTOR_SIZE).quot ==
	  div(fileinfo->pointer + offset, fileinfo->volinfo->secperclus * SECTOR_SIZE).quot) {
		fileinfo->pointer = offset;
	}
	// Case 3b - Seeking across cluster boundary(ies)
	else {
		// round file pointer down to cluster boundary
		fileinfo->pointer = div(fileinfo->pointer, fileinfo->volinfo->secperclus * SECTOR_SIZE).quot *
		  fileinfo->volinfo->secperclus * SECTOR_SIZE;

		// seek by clusters
		// larwe 9/30/06 bugfix changed .rem to .quot in both div calls
		while (div(fileinfo->pointer, fileinfo->volinfo->secperclus * SECTOR_SIZE).quot !=
		  div(fileinfo->pointer + offset, fileinfo->volinfo->secperclus * SECTOR_SIZE).quot) {

			fileinfo->cluster = DFS_GetFAT(fileinfo->volinfo, scratch, &tempint, fileinfo->cluster);
			// Abort if there was an error
			if (fileinfo->cluster == 0x0ffffff7) {
				fileinfo->pointer = 0;
				fileinfo->cluster = fileinfo->firstcluster;
				return;
			}
			fileinfo->pointer += SECTOR_SIZE * fileinfo->volinfo->secperclus;
		}

		// since we know the cluster is right, we have no more work to do
		fileinfo->pointer = offset;
	}
}

/*
	Delete a file
	scratch must point to a sector-sized buffer
*/
uint32_t DFS_UnlinkFile(PVOLINFO volinfo, uint8_t *path, uint8_t *scratch)
{
	PDIRENT de = (PDIRENT) scratch;
	FILEINFO fi;
	uint32_t cache = 0;
	uint32_t tempclus;

	// DFS_OpenFile gives us all the information we need to delete it
	if (DFS_OK != DFS_OpenFile(volinfo, path, DFS_READ, scratch, &fi))
		return DFS_NOTFOUND;

	// First, read the directory sector and delete that entry
	if (DFS_ReadSector(volinfo->unit, scratch, fi.dirsector, 1))
		return DFS_ERRMISC;
	((PDIRENT) scratch)[fi.diroffset].name[0] = 0xe5;
	if (DFS_WriteSector(volinfo->unit, scratch, fi.dirsector, 1))
		return DFS_ERRMISC;

	// Now follow the cluster chain to free the file space
	while (!((volinfo->filesystem == FAT12 && fi.firstcluster >= 0x0ff7) ||
	  (volinfo->filesystem == FAT16 && fi.firstcluster >= 0xfff7) ||
	  (volinfo->filesystem == FAT32 && fi.firstcluster >= 0x0ffffff7))) {
		tempclus = fi.firstcluster;

		fi.firstcluster = DFS_GetFAT(volinfo, scratch, &cache, fi.firstcluster);
		DFS_SetFAT(volinfo, scratch, &cache, tempclus, 0);

	}
	return DFS_OK;
}


/*
	Write an open file
	You must supply a prepopulated FILEINFO as provided by DFS_OpenFile, and a
	pointer to a SECTOR_SIZE scratch buffer.
	This function updates the successcount field with the number of bytes actually written.
*/
uint32_t DFS_WriteFile(PFILEINFO fileinfo, uint8_t *scratch, uint8_t *buffer, uint32_t *successcount, uint32_t len)
{
	uint32_t remain;
	uint32_t result = DFS_OK;
	uint32_t sector;
	uint32_t byteswritten;

	// Don't allow writes to a file that's open as readonly
	if (!(fileinfo->mode & DFS_WRITE))
		return DFS_ERRMISC;

	remain = len;
	*successcount = 0;

	while (remain && result == DFS_OK) {
		// This is a bit complicated. The sector we want to read is addressed at a cluster
		// granularity by the fileinfo->cluster member. The file pointer tells us how many
		// extra sectors to add to that number.
		sector = fileinfo->volinfo->dataarea +
		  ((fileinfo->cluster - 2) * fileinfo->volinfo->secperclus) +
		  div(div(fileinfo->pointer,fileinfo->volinfo->secperclus * SECTOR_SIZE).rem, SECTOR_SIZE).quot;

		// Case 1 - File pointer is not on a sector boundary
		if (div(fileinfo->pointer, SECTOR_SIZE).rem) {
			uint16_t tempsize;

			// We always have to go through scratch in this case
			result = DFS_ReadSector(fileinfo->volinfo->unit, scratch, sector, 1);

			// This is the number of bytes that we don't want to molest in the
			// scratch sector just read.
			tempsize = div(fileinfo->pointer, SECTOR_SIZE).rem;
					
			// Case 1A - We are writing the entire remainder of the sector. After
			// this point, all passes through the read loop will be aligned on a
			// sector boundary, which allows us to go through the optimal path
			// 2A below.
		   	if (remain >= SECTOR_SIZE - tempsize) {
				memcpy(scratch + tempsize, buffer, SECTOR_SIZE - tempsize);
				if (!result)
					result = DFS_WriteSector(fileinfo->volinfo->unit, scratch, sector, 1);

				byteswritten = SECTOR_SIZE - tempsize;
				buffer += SECTOR_SIZE - tempsize;
				fileinfo->pointer += SECTOR_SIZE - tempsize;
				if (fileinfo->filelen < fileinfo->pointer) {
					fileinfo->filelen = fileinfo->pointer;
				}
				remain -= SECTOR_SIZE - tempsize;
			}
			// Case 1B - This concludes the file write operation
			else {
				memcpy(scratch + tempsize, buffer, remain);
				if (!result)
					result = DFS_WriteSector(fileinfo->volinfo->unit, scratch, sector, 1);

				buffer += remain;
				fileinfo->pointer += remain;
				if (fileinfo->filelen < fileinfo->pointer) {
					fileinfo->filelen = fileinfo->pointer;
				}
				byteswritten = remain;
				remain = 0;
			}
		} // case 1
		// Case 2 - File pointer is on sector boundary
		else {
			// Case 2A - We have at least one more full sector to write and don't have
			// to go through the scratch buffer. You could insert optimizations here to
			// write multiple sectors at a time, if you were thus inclined. Refer to
			// similar notes in DFS_ReadFile.
			if (remain >= SECTOR_SIZE) {
				result = DFS_WriteSector(fileinfo->volinfo->unit, buffer, sector, 1);
				remain -= SECTOR_SIZE;
				buffer += SECTOR_SIZE;
				fileinfo->pointer += SECTOR_SIZE;
				if (fileinfo->filelen < fileinfo->pointer) {
					fileinfo->filelen = fileinfo->pointer;
				}
				byteswritten = SECTOR_SIZE;
			}
			// Case 2B - We are only writing a partial sector and potentially need to
			// go through the scratch buffer.
			else {
				// If the current file pointer is not yet at or beyond the file
				// length, we are writing somewhere in the middle of the file and
				// need to load the original sector to do a read-modify-write.
				if (fileinfo->pointer < fileinfo->filelen) {
					result = DFS_ReadSector(fileinfo->volinfo->unit, scratch, sector, 1);
					if (!result) {
						memcpy(scratch, buffer, remain);
						result = DFS_WriteSector(fileinfo->volinfo->unit, scratch, sector, 1);
					}
				}
				else {
					result = DFS_WriteSector(fileinfo->volinfo->unit, buffer, sector, 1);
				}

				buffer += remain;
				fileinfo->pointer += remain;
				if (fileinfo->filelen < fileinfo->pointer) {
					fileinfo->filelen = fileinfo->pointer;
				}
				byteswritten = remain;
				remain = 0;
			}
		}

		*successcount += byteswritten;

		// check to see if we stepped over a cluster boundary
		if (div(fileinfo->pointer - byteswritten, fileinfo->volinfo->secperclus * SECTOR_SIZE).quot !=
		  div(fileinfo->pointer, fileinfo->volinfo->secperclus * SECTOR_SIZE).quot) {
		  	uint32_t lastcluster;

		  	// We've transgressed into another cluster. If we were already at EOF,
		  	// we need to allocate a new cluster.
			// An act of minor evil - we use byteswritten as a scratch integer, knowing
			// that its value is not used after updating *successcount above
			byteswritten = 0;

			lastcluster = fileinfo->cluster;
			fileinfo->cluster = DFS_GetFAT(fileinfo->volinfo, scratch, &byteswritten, fileinfo->cluster);
			
			// Allocate a new cluster?
			if (((fileinfo->volinfo->filesystem == FAT12) && (fileinfo->cluster >= 0xff8)) ||
			  ((fileinfo->volinfo->filesystem == FAT16) && (fileinfo->cluster >= 0xfff8)) ||
			  ((fileinfo->volinfo->filesystem == FAT32) && (fileinfo->cluster >= 0x0ffffff8))) {
			  	uint32_t tempclus;

				tempclus = DFS_GetFreeFAT(fileinfo->volinfo, scratch);
				byteswritten = 0; // invalidate cache
				if (tempclus == 0x0ffffff7)
					return DFS_ERRMISC;

				// Link new cluster onto file
				DFS_SetFAT(fileinfo->volinfo, scratch, &byteswritten, lastcluster, tempclus);
				fileinfo->cluster = tempclus;

				// Mark newly allocated cluster as end of chain			
				switch(fileinfo->volinfo->filesystem) {
					case FAT12:		tempclus = 0xff8;	break;
					case FAT16:		tempclus = 0xfff8;	break;
					case FAT32:		tempclus = 0x0ffffff8;	break;
					default:		return DFS_ERRMISC;
				}
				DFS_SetFAT(fileinfo->volinfo, scratch, &byteswritten, fileinfo->cluster, tempclus);

				result = DFS_OK;
			}
			// No else clause is required.
		}
	}
	
	// Update directory entry
		if (DFS_ReadSector(fileinfo->volinfo->unit, scratch, fileinfo->dirsector, 1))
			return DFS_ERRMISC;
		((PDIRENT) scratch)[fileinfo->diroffset].filesize_0 = fileinfo->filelen & 0xff;
		((PDIRENT) scratch)[fileinfo->diroffset].filesize_1 = (fileinfo->filelen & 0xff00) >> 8;
		((PDIRENT) scratch)[fileinfo->diroffset].filesize_2 = (fileinfo->filelen & 0xff0000) >> 16;
		((PDIRENT) scratch)[fileinfo->diroffset].filesize_3 = (fileinfo->filelen & 0xff000000) >> 24;
		if (DFS_WriteSector(fileinfo->volinfo->unit, scratch, fileinfo->dirsector, 1))
			return DFS_ERRMISC;
	return result;
}

⌨️ 快捷键说明

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