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

📄 fat_write.c

📁 索尼公司著名游戏机PS2使用的引导工具文件源代码,这是爱好者自编的工具,可以使用它来引导自己的程序,达到跳过原光驱启动执行自己制作的程序的目的,在windows上可以安装使用ps2的专用开发包,搭建c
💻 C
📖 第 1 页 / 共 5 页
字号:
		dsfn->timeCreate[1] = tmpClk[1];

		dsfn->dateCreate[0] = tmpClk[2];

		dsfn->dateCreate[1] = tmpClk[3];

		dsfn->dateAccess[0] = tmpClk[2];

		dsfn->dateAccess[1] = tmpClk[3];

	}

	//set  date & time of modification

	if (mode & DATE_MODIFY) {

		dsfn->timeWrite[0] = tmpClk[0];

		dsfn->timeWrite[1] = tmpClk[1];

		dsfn->dateWrite[0] = tmpClk[2];

		dsfn->dateWrite[1] = tmpClk[3];

	}

}



/*

  fill the SFN (short filename) direntry

*/

void setSfnEntry(unsigned char* shortName, char directory, unsigned char *buffer, unsigned int cluster) {

        int i,j;

	fat_direntry_sfn* dsfn;



	dsfn = (fat_direntry_sfn*) buffer;

	//name + ext

	for (i = 0; i < 8; i++) dsfn->name[i] = shortName[i];

	for (i = 0; i < 3; i++) dsfn->ext[i]  = shortName[i+8];



	if (directory > 0) {

		dsfn->attr = 16; //directory bit set

	} else {

		dsfn->attr = 32; //ordinary file + archive bit set

	}

	dsfn->reservedNT = 0;

	dsfn->clusterH[0] = (cluster & 0xFF0000) >> 16;

	dsfn->clusterH[1] = (cluster & 0xFF000000) >> 24;

	dsfn->clusterL[0] = (cluster & 0x00FF);

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



	//size is zero - because we don't know the filesize yet

	for (i = 0; i < 4; i++) dsfn->size[i] = 0;



	setSfnDate(dsfn, DATE_CREATE + DATE_MODIFY);

}









/*
 Create short name by squeezing long name into the 8.3 name boundaries
 lname - existing long name
 sname - buffer where to store short name
 returns: 0  if longname completely fits into the 8.3 boundaries
          1  if long name have to be truncated (ie. INFORM~1.TXT
	 <0  if invalid long name detecte
*/
int createShortNameMask(unsigned char* lname, unsigned char* sname) {
	int i;
	int size;
	int j;
	int fit;

	if (lname[0] == '.') {
		return -EINVAL;
	}

	fit = 0;
	//clean short name by putting space	
	for (i = 0; i < 11; i++)  sname[i] = 32; 
	XPRINTF("Clear short name ='%s'\n", sname);

	//detect number of dots and space characters in the long name
	j = 0;
	for (i = 0; lname[i] != 0; i++) {
		if (lname[i] == '.') j++; else
		if (lname[i] == 32 ) j+=2;
	}
	//long name contains no dot or one dot and no space char
	if (j <= 1) fit++;
	//XPRINTF("fit1=%d j=%d\n", fit, j);

	//store name 
	for (i = 0; lname[i] !=0 && lname[i] != '.' && i < 8; i++) {
		sname[i] = toUpperChar(lname[i]);
		//short name must not contain spaces - replace space by underscore
		if (sname[i] == 32) sname[i]='_';
	}
	//check wether last char is '.' and the name is shorter than 8
	if (lname[i] == '.' || lname[i] == 0) {
		fit++;
	}
	//XPRINTF("fit2=%d\n", fit);

	//find the last dot "." - filename extension
	size = strlen((const char*)lname);
	size--;

	for (i = size; i > 0 && lname[i] !='.'; i--);
	if (lname[i] == '.') {
		i++;
		for (j=0; lname[i] != 0 && j < 3; i++, j++) {
			sname[j+8] = toUpperChar(lname[i]);
		}
		//no more than 3 characters of the extension
		if (lname[i] == 0) fit++;
	} else {
		//no dot detected in the long filename
		fit++;
	}
//	XPRINTF("fit3=%d\n", fit);
//	XPRINTF("Long name=%s  Short name=%s \n", lname, sname);

	//all 3 checks passed  - the long name fits in the short name without restrictions
	if (fit == 3) {
		XPRINTF("Short name is loseles!\n");
		return 0;
	}

	//one of the check failed - the short name have to be 'sequenced'
	//do not allow spaces in the short name
	for (i = 0; i < 8;i++) {
		if (sname[i] == 32) sname[i] = '_';
	}
	return 1;	
}

/*

  separate path and filename

  fname - the source (merged) string (input)

  path  - separated path (output)

  name  - separated filename (output)

*/

int separatePathAndName(const char* fname, unsigned char* path, unsigned char* name) {

	int i;

	int lastSeparator;

	int nameIndex;



	lastSeparator = 0;

	nameIndex = 0;



	for (i = 0;  fname[i] != 0; i++) {

		path[i] = fname[i];

		if (fname[i] == '/' || fname[i] == '\\') {

			lastSeparator = i;

			nameIndex = 0;

			

		} else {

			if (nameIndex >= FAT_MAX_NAME-1) {

				return -ENAMETOOLONG;

			}

			name[nameIndex] = fname[i];

			nameIndex++;

		}

	}

	//terminate strings

	path[lastSeparator+1] = 0;

	name[nameIndex] = 0;

	return 1;

}



/*

 get the sequence number from existing direntry name

*/

int getShortNameSequence(unsigned char* name, unsigned char* ext, unsigned char* sname) {

	int i,j;

	unsigned char* tmp;

	unsigned char buf[8];



	//at first: compare extensions

	//if extensions differ then filenames are diffrerent and seq is 0

	tmp = sname+8;

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

		if (ext[i] != tmp[i]) return 0;

	}	



	//at second: find tilde '~' character (search backward from the end)

	for (i = 7; i > 0 && name[i] !='~'; i--);

	

	if (i == 0) return 0;  // tilde char was not found or is at first character

	

	//now compare the names - up to '~' position

	//if names differ then filenames are different;

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

		if (name[j] != sname[j]) return 0;

	}



	//if we get to this point we know that extension and name match

	//now get the sequence number behind the '~'

	for (j = i+1; j<8; j++) buf[j-i-1] = name[j];

	buf[j-i-1] = 0; //terminate



	XPRINTF("found short name sequence number='%s' \n", buf);

	return strtol((const char*)buf, NULL, 10);

}



/*

  set the short name sequence number 

*/

int setShortNameSequence(unsigned char* entry, int maxEntry, unsigned char* sname) {

	char number[8];

	unsigned char *buf;

	int i,j;

	int maxSeq;

	int hit;

	int seq;

	int cont;



	seq = 0;

	maxSeq = 0;

	hit = 0;

	//search the entries for sequence number

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

		seq = (entry[i] & 0xFC) >> 2;

		if (seq && i && (entry[i-1] & 0x03) == 2) { // seq != 0 && i != 0 && prceeding entry is long name

			seq += (entry[i-1] & 0xFC) << 4;

		}



		if (seq > maxSeq) maxSeq = seq; //find max sequence number

		if (seq) hit++; //find any sequence number 

	}	



	//check how many sequence numbers we have found and the highest sequence number.

	//if we get: hit==3 and maxSeq==120 then try to find unassigned sequence number 

	if (hit < maxSeq) {

		cont = 1;		

		for (j = 0; j < maxSeq && cont; j++) {

			//search the entries for sequence number

			for (i = 0; i < maxEntry && cont; i++) {

				seq = (entry[i] & 0xFC) >> 2;

				if (seq && i && (entry[i-1] & 0x03) == 2) { // seq != 0 && i != 0 && prceeding entry is long name

					seq += (entry[i-1] & 0xFC) << 4;

				}

				if (seq==j) cont = 0; //we found the sequence nuber - do not continue

			}

			if (cont == 1) { //the sequence number was missing in the entries

				seq = j;

			}

			cont = 1-cont; //set continue flag according the search result;

		}

	} else {

		seq = maxSeq + 1;

	}



	memset(number, 0, 8);

	sprintf(number, "%d",seq);

	j = strlen(number);

	

	buf = sname + 7  - j;

	buf[0] = '~';

	buf++;

	for (i = 0; i < j; i++) buf[i] = number[i];



	return 0;

}



/*

  find space where to put the direntry

*/

int getDirentryStoreOffset(unsigned char* entry, int entryCount, unsigned char* lname, int* direntrySize ) {

	int i;

	int size;

	int tightIndex;

	int looseIndex;

	int cont;

	int id;

	int slotStart;

	int slotSize;





	//direntry size for long name + 1 additional direntry for short name

	size = getDirentrySize(lname) + 1; 

	XPRINTF("Direntry size=%d\n", size);

	*direntrySize = size;



	//we search for sequence of deleted or empty entries (entry id = 0)

	//1) search the tight slot (that fits completely. ex: size = 3, and slot space is 3 )

	//2) search the suitable (loose) slot (ex: size = 3, slot space is 5)



	slotStart = -1;

	slotSize = 0;

	tightIndex = -1;

	looseIndex = -1;

	cont = 1;

	//search the entries for entry types

	for (i = 0; i < entryCount && cont; i++) {

		id = (entry[i] & 0x03);

		if (id == 0) { //empty entry

			if (slotStart >= 0) {

				slotSize++;

			} else {

				slotStart = i;

				slotSize = 1;

				XPRINTF("*Start slot at index=%d ",slotStart);

			}

		} else { //occupied entry

#ifdef DEBUG

			if (slotStart >=0) {

				XPRINTF("End slot at index=%d  slotSize=%d\n",i, slotSize);

			}

#endif

			if (tightIndex < 0 && slotSize == size) {

				tightIndex = slotStart;

				XPRINTF("!Set tight index= %d\n", tightIndex);

			} 

			if (looseIndex < 0 && slotSize > size) {

				looseIndex = slotStart + slotSize - size;

				XPRINTF("!Set loose index= %d\n", looseIndex);

			}

			if (tightIndex >= 0 && looseIndex >= 0) {

				cont = 0;

			}

			slotStart = -1;

			slotSize = 0;

		}

	}

	XPRINTF("\n");



	// tight index - smaller fragmentation of space, the larger blocks

	//               are left for larger filenames. 

	// loose index - more fragmentation of direntry space, but the direntry 

	//               name has space for future enlargement (of the name).

	//               i.e. no need to reposition the direntry and / or

	//               to allocate additional fat cluster for direntry space.



	// we prefere tight slot if available, othervise we use the loose slot.

	// if there are no tight and no loose slot then we position new direntry

	// at the end of current direntry space

	if (tightIndex >=0) {

		return tightIndex;

	}

	if (looseIndex >=0) {

		return looseIndex;

	}

	//last entry is (most likely) empty - use it

	if ( (entry[entryCount-1]&0x03) == 0) {

		return entryCount - 1;

	}



	return entryCount;



}







/*

  scans current directory entries and fills the info records



  lname        - long filename (to test wether existing entry match the long name) (input)

  sname        - short filename ( dtto ^^ ) (input)

  startCluster - valid start cluster of the directory or 0 if we scan the root directory (input)

  record       - info buffer (output)

  maxRecord    - size of the info buffer to avoid overflow  



  if file/directory already exist (return code 0) then:

  retSector    - contains sector number of the direntry (output)

  retOffset    - contains byte offse of the SFN direntry from start of the sector (output)

  the reason is to speed up modification of the SFN (size of the file)



*/

int fat_fillDirentryInfo(fat_bpb* bpb, unsigned char* lname, unsigned char* sname, char directory, unsigned int* startCluster, unsigned char* record, int maxRecord, unsigned int* retSector, int* retOffset) {

	fat_direntry_sfn* dsfn;

	fat_direntry_lfn* dlfn;

	fat_direntry dir;

	int i, j;

	int dirSector;

	unsigned int startSector;

	unsigned int theSector;

	int cont;

	int ret;

	int dirPos;

	int clusterMod;

	int seq;



	cont = 1;

	clusterMod = bpb->clusterSize - 1;

	//clear name strings

	dir.sname[0] = 0;

	dir.name[0] = 0;



	j = 0;

	if (directory) directory = 0x10;



	fat_getDirentrySectorData(bpb, startCluster, &startSector, &dirSector);



	XPRINTF("dirCluster=%i startSector=%i (%i) dirSector=%i \n", *startCluster, startSector, startSector * Size_Sector, dirSector);



	//go through first directory sector till the max number of directory sectors

	//or stop when no more direntries detected

	for (i = 0; i < dirSector && cont; i++) {

		theSector = startSector + i;

		ret = READ_SECTOR(theSector, sbuf); 

		if (ret < 0) {

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

			return -EIO;

		}

		XPRINTF("read sector ok, scanning sector for direntries...\n");

		

		//get correct sector from cluster chain buffer

		if ((*startCluster != 0) && (i % bpb->clusterSize == clusterMod)) {

			startSector = fat_cluster2sector(bpb, cbuf[(i / bpb->clusterSize) +  1]);

			startSector -= (i+1);

		}

		dirPos = 0;



		// go through start of the sector till the end of sector

		while (cont &&  dirPos < bpb->sectorSize && j< maxRecord) {

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

			dlfn = (fat_direntry_lfn*) (sbuf + dirPos);

			cont = fat_getDirentry(dsfn, dlfn, &dir); //get single directory entry from sector buffer

			switch (cont) { 

				case 1: //short name 

					if (!(dir.attr & 0x08)) { //not volume label

						//file we want to create already exist - return the cluster of the file

						if ((strEqual(dir.sname, lname) == 0) || (strEqual(dir.name, lname) == 0) ) {

							//found directory but requested is file (and vice veresa) 

							if ((dir.attr & 0x10) != directory) {

								if (directory) return -ENOTDIR;

								return -EISDIR;

							}

							XPRINTF("I: entry found! %s, %s = %s\n", dir.name, dir.sname, lname);

							*retSector = theSector;

							*retOffset = dirPos;

							*startCluster = dir.cluster; 

							deSec[deIdx] = theSector;

							deOfs[deIdx] = dirPos;

							deIdx++;

							return 0;

						}

						record[j] = 1;

						seq = getShortNameSequence(dsfn->name, dsfn->ext, sname);

						record[j] += ((seq & 0x3F) << 2);

						if (seq > 63) {   //we need to store seq number in the preceding record

							if (j>0 && (record[j-1] & 0x03) == 2) {

								record[j-1] += ((seq & 0x0FC0) >> 4);

							} else {

								return -EFAULT;

⌨️ 快捷键说明

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