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

📄 fat_write.c

📁 索尼公司著名游戏机PS2使用的引导工具文件源代码,这是爱好者自编的工具,可以使用它来引导自己的程序,达到跳过原光驱启动执行自己制作的程序的目的,在windows上可以安装使用ps2的专用开发包,搭建c
💻 C
📖 第 1 页 / 共 5 页
字号:
	for (i= 2; i < entryCount; i++) {  //first two records should be '.' & '..'

		if ((entry[i] & 0x03) != 0) {

			XPRINTF("I: directory not empty!\n");

			return 0;

		}

	}

	XPRINTF("I: directory is empty.\n");

	return 1;

}



/*

   Remove the name (direntries of the file or directory) from the directory space.



   lname        - long name (without the path)

   directory    - 0->delete file    1-delete directory

   startCluster - start cluster of the directory space

*/



int fat_clearDirSpace(fat_bpb* bpb, unsigned char* lname, char directory, unsigned int* startCluster) {

	int ret;

	int i;

	unsigned char sname[12]; //short name 8+3 + terminator

	unsigned int dirCluster;

	unsigned int theSector;

	int entryCount;

	int entryIndex;

	int direntrySize;

	fat_direntry_sfn* dsfn;

	unsigned int sfnSector;

	int sfnOffset;

	unsigned char entry[DIRENTRY_COUNT]; 



	memset(entry, 0, DIRENTRY_COUNT);

	sname[0] = 0;

	



	dirCluster = *startCluster;

	//get information about existing direntries (palcement of the empty/reusable direntries)

	//and find the lname in the directory

	//also fill up the dsSec and dsOfs information

	ret = fat_fillDirentryInfo(bpb, lname, sname, directory, startCluster, entry, DIRENTRY_COUNT, &sfnSector, &sfnOffset);

	if (ret != 0) {

		XPRINTF("E: direntry not found!\n");

		return -ENOENT;

	}

	XPRINTF("clear dir space: dir found at  cluster=%d \n ", *startCluster);



	//Check wether any file or directory exist in te target directory space.

	//We should not delete the directory if files/directories exist

	//because just clearing the dir doesn't free the fat clusters 

	//occupied by files. 

	if (directory) {

		//check wether sub-directory is empty

		//startCluster now points to subdirectory start cluster

		ret = checkDirspaceEmpty(bpb, *startCluster, entry);

		if (ret == 0) { //directorty contains some files 

			return -ENOTEMPTY;

		}

		//read the direntry info again, because we lost it during subdir check

		*startCluster = dirCluster;

		memset(entry, 0, DIRENTRY_COUNT);



		ret = fat_fillDirentryInfo(bpb, lname, sname, directory, startCluster, entry, DIRENTRY_COUNT, &sfnSector, &sfnOffset);

		if (ret != 0) {

			XPRINTF("E: direntry not found!\n");

			return -ENOENT;

		}

	}





#ifdef DEBUG

	for (i = 0; i < deIdx; i++) {

		printf("Sector=%d (%d) Offset=%d (%d) \n", 

			deSec[i], deSec[i]*bpb->sectorSize,

			deOfs[i], deSec[i]*bpb->sectorSize + deOfs[i]);

	}

#endif



	//now mark direntries as deleted

	theSector = 0;	

	for (i = 0; i < deIdx; i++) {

	        if (deSec[i] != theSector) {

			if (theSector > 0) {

				ret = WRITE_SECTOR(theSector);

				if (ret < 0) {

					printf("FAT writer: write directory sector failed ! sector=%i\n", theSector);

					return -EIO;

				}

			}

			theSector = deSec[i];

			ret = READ_SECTOR(theSector, sbuf); 

			if (ret < 0) {

				printf("FAT writer: read directory sector failed ! sector=%i\n", theSector);

				return -EIO;

			}

		}

		sbuf[deOfs[i]] = 0xE5; //delete marker

	}

	if (theSector > 0) {

		ret = WRITE_SECTOR(theSector);

		if (ret < 0) {

			printf("FAT writer: write directory sector failed ! sector=%i\n", theSector);

			return -EIO;

		}

	}



	//now delete whole cluster chain starting at the file's first cluster

	ret = fat_deleteClusterChain(bpb, *startCluster);

	if (ret < 0) {

		XPRINTF("E: delete cluster chain failed!\n");

		return ret;		

	}

	FLUSH_SECTORS();

	return 1;

}









/* ===================================================================== */



/*

  cluster  - start cluster of the file

  sfnSector - short filename entry sector

  sfnOffset - short filename entry offset from the sector start

*/

int fat_truncateFile(fat_bpb* bpb, unsigned int cluster, unsigned int sfnSector, int sfnOffset ) {

	int ret;

	fat_direntry_sfn* dsfn;



	if (cluster == 0 || sfnSector == 0) {

		return -EFAULT;

	}

	



	//now delete whole cluster chain starting at the file's first cluster

	ret = fat_deleteClusterChain(bpb, cluster);

	if (ret < 0) {

		XPRINTF("E: delete cluster chain failed!\n");

		return ret;		

	}



	//terminate cluster

	ret = fat_createClusterChain(bpb, cluster);

	if (ret < 0) {

		XPRINTF("E: truncate cluster chain failed!\n");

		return ret;		

	}



	ret = READ_SECTOR(sfnSector, sbuf); 

	if (ret < 0) {

		printf("FAT writer: read direntry sector failed ! sector=%i\n", sfnSector);

		return -EIO;

	}

	dsfn = (fat_direntry_sfn*) (sbuf + sfnOffset);

	dsfn->size[0] = 0;

	dsfn->size[1] = 0;

	dsfn->size[2] = 0;

	dsfn->size[3] = 0;



	ret = WRITE_SECTOR(sfnSector);

	if (ret < 0) {

		printf("FAT writer: write directory sector failed ! sector=%i\n", sfnSector);

		return -EIO;

	}

	return 1;

}





/*

  Update size of the SFN entry



  cluster  - start cluster of the file

  sfnSector - short filename entry sector

  sfnOffset - short filename entry offset from the sector start

*/

int fat_updateSfn(int size, unsigned int sfnSector, int sfnOffset ) {

	int ret;

	fat_direntry_sfn* dsfn;



	if (sfnSector == 0) {

		return -EFAULT;

	}

	



	ret = READ_SECTOR(sfnSector, sbuf); 

	if (ret < 0) {

		printf("FAT writer: read direntry sector failed ! sector=%i\n", sfnSector);

		return -EIO;

	}

	dsfn = (fat_direntry_sfn*) (sbuf + sfnOffset);

	dsfn->size[0] = size & 0xFF;

	dsfn->size[1] = (size & 0xFF00) >> 8;

	dsfn->size[2] = (size & 0xFF0000) >> 16;

	dsfn->size[3] = (size & 0xFF000000) >> 24;



	setSfnDate(dsfn, DATE_MODIFY);



	ret = WRITE_SECTOR(sfnSector);

	if (ret < 0) {

		printf("FAT writer: write directory sector failed ! sector=%i\n", sfnSector);

		return -EIO;

	}

	XPRINTF("I: sfn updated, file size=%d \n", size);

	return 1;

}





/*

 create file or directory



 fname          - path and filename

 directory      - set to 0 to create file, 1 to create directory

 escapeNotExist - set to 1 if you want to report error if file not exist. 

                  Otherwise set to 0 and file/dir will be created.

 cluster        - start cluster of the directory space - default is 0 -> root directory

 sfnSector      - sector of the SFN entry (output) - helps to modify direntry (size, date, time)

 sfnOffset      - offset (in bytes) of the SFN entry (output)

*/



int fat_createFile(fat_bpb* bpb, const char* fname, char directory, char escapeNotExist, unsigned int* cluster, unsigned int* sfnSector, int* sfnOffset) {
	int ret;
	unsigned int startCluster;
	unsigned char path[FAT_MAX_PATH];
	unsigned char lname[FAT_MAX_NAME];

	ret = separatePathAndName(fname, path, lname);
	if (lname[0] == 0 || lname[0]=='.' || ret < 0) {

		XPRINTF("E: file name not exist or not valid!");
		return -ENOENT;
	}

	//get start cluster of the last sub-directory of the path
	startCluster = 0;
	ret = fat_getFileStartCluster(bpb, (const char*)path, &startCluster, NULL);
	if (ret > 0) {
		XPRINTF("directory=%s name=%s cluster=%d \n", path, lname, startCluster);
	}else {
		XPRINTF("E: directory not found! \n");
		return -ENOENT;
	}

	//modify directory space of the path (cread direntries)
	//and/or create new (empty) directory space if directory creation requested
	ret = fat_modifyDirSpace(bpb, lname, directory, escapeNotExist, &startCluster, sfnSector, sfnOffset);
	if (ret < 0) {
		XPRINTF("E: modifyDirSpace failed!\n");
		return ret;
	}
	XPRINTF("I: SFN info: sector=%d (%d)  offset=%d (%d) startCluster=%d\n", *sfnSector, *sfnSector * bpb->sectorSize, *sfnOffset, *sfnOffset + (*sfnSector * bpb->sectorSize), startCluster);
	
	*cluster = startCluster;
	if (ret == 0) {
		XPRINTF("I: file already exists at cluster=%d\n", startCluster);
		return 2;
	}
	return 1;
}




int fat_deleteFile(fat_bpb* bpb, const char* fname, char directory) {

	int ret;

	unsigned int startCluster;

	unsigned int directoryCluster;

	unsigned char path[FAT_MAX_PATH];

	unsigned char lname[FAT_MAX_NAME];





	ret = separatePathAndName(fname, path, lname);

	if (lname[0] == 0 || lname[0]=='.' || ret < 0) {

		XPRINTF("E: file name not exist or not valid!");

		return -ENOENT;

	}



	//get start cluster of the last sub-directory of the path

	startCluster = 0;

	ret = fat_getFileStartCluster(bpb, (const char*)path, &startCluster, NULL);

	if (ret > 0) {

		XPRINTF("directory=%s name=%s cluster=%d \n", path, lname, startCluster);

	}else {

		XPRINTF("E: directory not found! \n");

		return -ENOENT;

	}



	//delete direntries and modify fat

	directoryCluster = startCluster;

	ret = fat_clearDirSpace(bpb, lname, directory, &startCluster);

	if (ret < 0) {

		XPRINTF("E: cleanDirSpace failed!\n");

		return ret;

	}

	if (startCluster != directoryCluster) {

		XPRINTF("I: file/dir removed from cluster=%d\n", startCluster);

	}

	return 1;

}





int fat_writeFile(fat_bpb* bpb, fat_dir* fatDir, int* updateClusterIndices, unsigned int filePos, unsigned char* buffer, int size) {

	int ret;

	int i,j;

	int chainSize;

	int nextChain; 

	int startSector;

	int bufSize;

	int sectorSkip;

	int clusterSkip;

	int dataSkip;



	unsigned int bufferPos;

	unsigned int fileCluster;

	unsigned int clusterPos;

	unsigned int endPosFile;

	unsigned int endPosCluster;

	unsigned int lastCluster;



	int clusterChainStart;





	//check wether we have enough clusters allocated

	i = bpb->clusterSize * bpb->sectorSize; //the size (in bytes) of the one cluster

	j = fatDir->size / i;

	if (fatDir->size % i) {

		j++;

	}

	if (j == 0) j = 1; //the file have allways at least one cluster allocated 



	endPosCluster = j * i;

	endPosFile = filePos + size;

	

	*updateClusterIndices = 0;

	

        //allocate additional cluster(s)

	if (endPosFile > endPosCluster) {

		ret = endPosFile - endPosCluster; //additional space needed in bytes

		j = ret / i;  //additional space needed (given in number of clusters)

		if (ret % i) {

			j++;	

		}

		lastCluster = fatDir->lastCluster;

		XPRINTF("I: writeFile: last cluster= %d \n", lastCluster);



		if (lastCluster == 0) return -ENOSPC; // no more free clusters or data invalid

		for (i = 0; i < j; i++) {

			lastCluster = fat_getFreeCluster(bpb, lastCluster);

			if (lastCluster == 0) return -ENOSPC; // no more free clusters

		}

		fatDir->lastCluster = lastCluster;

		*updateClusterIndices = j;

		fat_invalidateLastChainResult(); //prevent to misuse current (now deleted) cbuf



		XPRINTF("I: writeFile: new clusters allocated = %d new lastCluster=%d \n", j, lastCluster);

	}

	XPRINTF("I: write file: filePos=%d  dataSize=%d \n", filePos, size);





	fat_getClusterAtFilePos(bpb, fatDir, filePos, &fileCluster, &clusterPos);

	sectorSkip = (filePos - clusterPos) / bpb->sectorSize;

	clusterSkip = sectorSkip / bpb->clusterSize;

	sectorSkip %= bpb->clusterSize;

	dataSkip  = filePos  % bpb->sectorSize;

	bufferPos = 0;





	XPRINTF("fileCluster = %i,  clusterPos= %i clusterSkip=%i, sectorSkip=%i dataSkip=%i \n",

		fileCluster, clusterPos, clusterSkip, sectorSkip, dataSkip);



	if (fileCluster < 2) {

		return -EFAULT;

	}



	bufSize = SECTOR_SIZE;

	nextChain = 1;

	clusterChainStart = 1;



	while (nextChain && size > 0 ) {

		chainSize = fat_getClusterChain(bpb, fileCluster, cbuf, MAX_DIR_CLUSTER, clusterChainStart);

		clusterChainStart = 0;

		if (chainSize == 0) { //the chain is full, but more chain parts exist

			chainSize = MAX_DIR_CLUSTER;

			fileCluster = cbuf[MAX_DIR_CLUSTER - 1];

		}else { //chain fits in the chain buffer completely - no next chain needed

			nextChain = 0;

		}

		while (clusterSkip >= MAX_DIR_CLUSTER) {

			chainSize = fat_getClusterChain(bpb, fileCluster, cbuf, MAX_DIR_CLUSTER, clusterChainStart);

			clusterChainStart = 0;

			if (chainSize == 0) { //the chain is full, but more chain parts exist

				chainSize = MAX_DIR_CLUSTER;

				fileCluster = cbuf[MAX_DIR_CLUSTER - 1];

			}else { //chain fits in the chain buffer completely - no next chain needed

				nextChain = 0;

			}

			clusterSkip -= MAX_DIR_CLUSTER;

		}



#ifdef DEBUG

		fat_dumpClusterChain(cbuf, chainSize, clusterSkip);

		fat_dumpClusterChain(cbuf, chainSize, 0);

		printf("fileCluster = %i,  clusterPos= %i clusterSkip=%i, sectorSkip=%i dataSkip=%i filePos=%i \n",

		fileCluster, clusterPos, clusterSkip, sectorSkip, dataSkip, filePos);

#endif



		//process the cluster chain (cbuf) and skip leading clusters if needed

		for (i = 0 + clusterSkip; i < chainSize && size > 0; i++) {

			//read cluster and save cluster content

			startSector = fat_cluster2sector(bpb, cbuf[i]);

			//process all sectors of the cluster (and skip leading sectors if needed)

			for (j = 0 + sectorSkip; j < bpb->clusterSize && size > 0; j++) {

				//TODO - do not read when writing to unallocated sectors

				ret = READ_SECTOR(startSector + j, sbuf); 

				if (ret < 0) {

					printf("Read sector failed ! sector=%i\n", sta

⌨️ 快捷键说明

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