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

📄 libfat.c

📁 Support library to access and manipulate FAT12 / FAT16 / FAT32 file systems - Includes a FUSE filesy
💻 C
📖 第 1 页 / 共 5 页
字号:
			// Cluster must be a valid cluster number set up by fat_read_entry.			fprintf(stderr,"offset >= clustersz, but next cluster exist.\n");		}				*Offset = 0;			}	while (count > 0) {		int numbytes;		int newoffset;				numbytes = MIN(byteleftperclus, count);						newoffset = *Offset + numbytes;				off = byte_offset(V, *Cluster, *Offset);		fprintf(stderr,"Cluster: %u, Offset: %u, off: %lld, numbyts:%d\n",*Cluster, *Offset, off, numbytes);		seekres = lseek64(V->blkDevFd,(off64_t)  off , SEEK_SET);		if (seekres != off ) {			perror("lseek() error in read_data");			return -1;		}		res = readn(V->blkDevFd, &(buf[dataread]), (size_t) numbytes);		if (res < 0) {			fprintf(stderr,"readn() error, line:%d\n",__LINE__);			return -1;		}		dataread += res;		count -= res;		i++;				// NB: readn implies it has to read numbytes bytes or fail, so		// if count is now > 0, then we automatically have to jump to next cluster.		//update cluster and offset -- if we reach end of clusterchain, count must have been too large.		if (count > 0) {	// lets fetch next cluster.			DWORD c =  *Cluster;			fat_read_entry(V, c, 0, Cluster);			// lets check if wehave reached the end of clusterchain			if (fat_iseoc(V,*Cluster)) {	//we reached EOC so count is too big. Caller have to check *Cluster by himself				fprintf(stderr,"read_data() error: EOC reached\n");					return(datasize -count);			}			*Offset = 0;			//lets reset byteleftperclus			byteleftperclus = clustersz;		} else {	// count <=0. We are done. lets set *Offset properly			*Offset = newoffset;			if ( *Offset >= clustersz ) {	//it cant actually be greater, just equal				DWORD c =  *Cluster;				fat_read_entry(V, c, 0, Cluster); // if this is the last cluster in the chain, the function will return EOC/0 pair for clus/off				*Offset = 0;					}			return datasize;			}				}	 	return -2;	// we shouldnt reach here}/* Write from the buffer data to the file who own the cluster Cluster, starting at 						*//*  the offset Offset in the cluster Cluster. 								This is low level function. *//* it returns number of bytes written or -1 on error. It does not make any change to Cluster and Offset *//* NB: F can be NULL if we are writing on a directory file												*//* Please NOTE: the function does not make any check on Cluster.										 */int fat_write_data(Volume_t *V, File_t *F, DWORD *Cluster, DWORD *Offset, char *buf, int count ) {#ifdef FATWRITE	int cnt = count;	off64_t off = 0;	int datasize = count;	int datawritten = 0;	int clustersz= V->bpc;	int byteleftperclus;	int res;	off64_t seekres;	int i=0;	DWORD orig_filesz = 0;		if (F != NULL) {		orig_filesz = EFD(F->DirEntry->DIR_FileSize);	}	if (*Offset > clustersz) {		fprintf(stderr,"Offset too big\n");		return -1;	} else if (*Offset == clustersz) {		DWORD c =  *Cluster;		*Offset = 0;		fat_read_entry(V, c, 0, Cluster); // if this is the last cluster in the chain, the function will allocate a new cluster.				if (fat_isfree(V,*Cluster)) { // must be eoc or  a valid cluster number			fprintf(stderr,"fat_write_data wrote on an unlinked cluster\n"); 			return -1; 						/* workaround to avoid to return an invalid *Cluster	*/		// lets check if wehave reached EOC. in this case this function allocate a free cluster to the file even if it does not need it.		} else if (fat_iseoc(V,*Cluster)) {	//we reached EOC. so we have to get a free cluster and link it to the file			DWORD newclus;			int r;				newclus = fat_getFreeCluster(V);			if (newclus == (DWORD) 0) {	// no newclusters available				fprintf(stderr,"getFreeCluster() error. line %d\n",__LINE__); return -1; }				/* lets write newclus into *Cluster in the fat.	*/	//tofix: writen_entry instead of write_entry???			if ((r = fat_writen_entry(V, c, newclus)) != 0) return -1;					/* lets write EOC into newclus in the fat.		*/			if ((r = fat_writen_entry(V, newclus,  fat_eocvalue(V))) != 0) return -1; 								/* lets set *Cluster to newclus					*/ 											*Cluster = newclus;		} else {			// Cluster must be a valid cluster number set up by fat_read_entry.			fprintf(stderr,"offset >= clustersz, but next cluster exist.\n");		}		*Offset = 0;			}	byteleftperclus = clustersz - *Offset;	fprintf(stderr,"off: %u, bytleft %d, cnt: %d\n",*Offset, byteleftperclus,cnt);	while (cnt > 0) {		int numbytes;		int newoffset;				numbytes = MIN(byteleftperclus, cnt);						newoffset = *Offset + numbytes;				off = byte_offset(V, *Cluster, *Offset);		fprintf(stderr,"Cluster: %u, Offset: %u, off: %lld, numbyts:%d, i:%d\n",*Cluster, *Offset, off, numbytes,i);		seekres = lseek64(V->blkDevFd,(off64_t)  off , SEEK_SET);		if (seekres != off ) {			fprintf(stderr,"lseek() error in read_data\n");			return -1;		}		res = writen(V->blkDevFd, &(buf[datawritten]), (size_t) numbytes);		if (res != numbytes) { fprintf(stderr,"writen() error in write data\n"); return -1;	}				if (F != NULL) F->CurAbsOff += res;		datawritten += res;		cnt -= res;		i++;				// NB: readn implies it has to read numbytes bytes or fail, so		// if cnt is now > 0, then we automatically have to jump to next cluster.		//update cluster and offset -- if we reach end of clusterchain, cnt must have been too large.//		fprintf(stderr,"value of cnt: %d\n",cnt);		if (cnt > 0) {	// lets fetch next cluster.			DWORD c =  *Cluster;			fat_read_entry(V, c, 0, Cluster);			fprintf(stderr,"reading value of cluster %u:  %u\n",c, *Cluster);			if (fat_isfree(V,*Cluster)) {				fprintf(stderr,"fat_write_data wrote on an unlinked cluster\n");				return -1;			}			// lets check if wehave reached the end of clusterchain			if (fat_iseoc(V,*Cluster)) {	//we reached EOC. so we have to get a free cluster and link it to the file				DWORD newclus;				int r;								newclus = fat_getFreeCluster(V);				if (newclus == 0) {					if ((F != NULL) && (EFD(F->DirEntry->DIR_FileSize) < F->CurAbsOff)) F->DirEntry->DIR_FileSize = EFD(F->CurAbsOff);					fprintf(stderr,"getFreeCluster() error. line:%d\n",__LINE__); return -1;				}								/* lets write newclus into *Cluster in the fat.	*/	//tofix: writen_entry instead of write_entry???				if ((r = fat_writen_entry(V, c, newclus)) != 0) return -1;								/* lets write EOC into newclus in the fat.		*/				if ((r = fat_writen_entry(V, newclus,  fat_eocvalue(V))) != 0) return -1;				/* lets set *Cluster to newclus					*/ 												*Cluster = newclus;			} else {				// Cluster must be a valid cluster number set up by fat_read_entry.			}						*Offset = 0;			//lets reset byteleftperclus			byteleftperclus = clustersz;		} else {	// cnt <=0. We are done. lets set *Offset properly			DWORD c =  *Cluster;			*Offset = newoffset;						if ( *Offset >= clustersz ) {	//it cant actually be greater, just equal				fat_read_entry(V, c, 0, Cluster); // if this is the last cluster in the chain, the function will allocate a new cluster.								if (fat_isfree(V,*Cluster)) { // must be eoc or  a valid cluster number					fprintf(stderr,"fat_write_data wrote on an unlinked cluster\n"); return -1; }											/* workaround to avoid to return an invalid *Cluster	*/				// lets check if wehave reached EOC. in this case this function allocate a free cluster to the file even if it does not need it.				if (fat_iseoc(V,*Cluster)) {	//we reached EOC. so we have to get a free cluster and link it to the file					// reset cluster value and just left offset value to clustersize					*Cluster = c;				} else {					// Cluster must be a valid cluster number set up by fat_read_entry.					fprintf(stderr,"offset >= clustersz, but next cluster exist.\n");					*Offset = 0;				}			} else { //offset < clustersize					fprintf(stderr,"offset !>= clustersz, so everything is fine and we dont have to allocate a new cluster\n");						}			if ((F != NULL) && (EFD(F->DirEntry->DIR_FileSize) < F->CurAbsOff)) F->DirEntry->DIR_FileSize = EFD(F->CurAbsOff); 			return datasize;			}				}	 #endif /* #ifdef FATWRITE */	return -2;	// we shouldnt reach here}static ssize_t fat_write0data(Volume_t *V, File_t *F, DWORD *Cluster, DWORD *Offset, size_t count) {	int res;	int retval = count;	char *buf = V->zerobuf;		if ((count <= 0)) { fprintf(stderr,"write0 error: count <= 0\n"); return -1; }	 	while (count > 0) {		int size;		size = MIN(ZERO_BFSZ, count);		count -= size;		if ((res = 	fat_write_data(V, F, Cluster, Offset, buf, size )) != size) { 			fprintf(stderr,"write0data error. size: %d, res: %d\n",size, res); return -1; }	}	return retval;}/* 	Update the DirEntry_t of the file F into the volume V			*/int fat_update_file(File_t *F) {#ifdef FATWRITE	int res;	off64_t seekres;	if (F == NULL) return 0;		seekres = lseek64(F->V->blkDevFd,(off64_t)  F->D.direntoff , SEEK_SET);	if (seekres != F->D.direntoff ) {		perror("lseek() error in update file");		return -1;	}	res = writen(F->V->blkDevFd, (char *) F->DirEntry, (size_t) sizeof(DirEntry_t));	if (res < 0) {		perror("writen() error in update file");		return -1;	}#endif /* #ifdef FATWRITE */	return 0;}/* set first cluster */int set_fstclus(Volume_t *V, DirEntry_t *D, DWORD c) {	if (D==NULL) return -1;	c=EFD(c); // c is now little endian	char *src = (char *) &c;	char *dst = (char *) &(D->DIR_FstClusLO);		dst[0] = src[0];	dst[1] = src[1];	if (V->FatType == FAT32) {			dst = (char *) &(D->DIR_FstClusHI);		dst[0] = src[2];		dst[1] = src[3];		}		return 0;}/* get first cluster */DWORD get_fstclus(Volume_t *V, DirEntry_t *D) {	DWORD val = 0;		char *dst = (char *) &val;	char *src = (char *) &(D->DIR_FstClusLO);		dst[0] = src[0];	dst[1] = src[1];	if (V->FatType == FAT32) {		src = (char *) &(D->DIR_FstClusHI);		dst[2] = src[0];		dst[3] = src[1];	}		val=EFD(val);	return val;}static int erase_dirent(DirEnt_t *D) {	BYTE b;	int i;		if (D->last == 0) {		b = FREEENT;	} else {		b = ENDOFDIR;	}			for (i=0; i < D->len; i++) D->entry[i].LDIR_Ord = b;	return 0;}/* find a direntry by sfn name. require a buffer of 11 char containing the sfn name */static int find_direntry_bysfn(Volume_t *V, BYTE *sfnname, DWORD *Cluster, DWORD *Offset) {    int res;    DWORD bkclu, bkoff;	DirEnt_t D;    LfnEntry_t *buffer = D.entry;	    	for (;;) {		bkclu = *Cluster;		bkoff = *Offset;		res = fetch_next_direntry(V, &D, Cluster, Offset);		if (res <= 0)  return -1;	// this is the condition to exit : nothing left to fetch.		/*	checking if this is what we are lookin for		*/				res= utf8_strncmp((char *) sfnname, (char *) ((DirEntry_t *) &(buffer[res -1]))->DIR_Name, 11); // possible because Ascii are utf8				if (res == 0) {	// we won! good.			*Cluster = bkclu;			*Offset = bkoff;			return 0;		}	}    return -2;}/* static routine to generate an lfn chain. utf8name must be null terminated */static int generate_lfn_chain(char *utf8name, LfnEntry_t *buf, BYTE checksum) {	int res;	int len;	int i;	int size;	WORD lfn_name[256];		memset(lfn_name, 0, 256*sizeof(WORD));	len = res = utf8_strlen(utf8name);	fprintf(stderr,"filename: %s, len:%d\n", utf8name, len);	if ((res <= 0) || (res >255)) {		perror("generate lfn chain() error: illegal filename length");		return -1;	}		size = ((len -1) /13) +1;	// it is correct	res = utf8to16(utf8name, lfn_name);	if (res < 0)  {		perror("utf8to16() error: illegal filename length %d");		return -1;	}			// lets memset the buffer to FFFF (padding for lf name	memset(buf,0xFF, (21 * sizeof(LfnEntry_t))); 		// lets begin writing the name, properly setting checksum and other fields to 0;	for(i=0; i <len; i++) {		res = set_lfn_char((LfnEntry_t *) &(buf[(size - 1 - (i / 13))]), lfn_name[i] , i);		if (res != 0) return -1;	}	if ( (len % 13) != 0 ) { //if we dont have to go next entry		res = set_lfn_char((LfnEntry_t *) &(buf[0]), 0x0000 , (len % 13));		if (res != 0) return -1;			}		for(i=1; i <=size; i++) {		buf[size -i].LDIR_Ord = i;		buf[size -i].LDIR_Attr = ATTR_LONG_NAME;		buf[size -i].LDIR_Chksum = checksum;		buf[size -i].LDIR_Type = 0;		buf[size -i].LDIR_FstClusLO = 0;	}		buf[0].LDIR_Ord |= LFN_LASTENTRY;		//lets return number of used entries	return ( size );		// i suppose ((len -1) /13) +1 is wrong. im wrong}/* find n 32byte slots to store a file entry . it sets properly cluster and offset and returns absolute offset */static off64_t fat_find_lfnslots(Volume_t *V, File_t *dir, DWORD *Cluster , DWORD *Offset, int n) {    DWORD oldclus,clus,newclus;	DWORD off=0;	int res;	int found =0;	char *cluster;	int rootdirflag = 0;		if ((dir == NULL) || (dir->rootdir == 1)) rootdirflag =1;		if ((rootdirflag != 1)){		if (!ATTR_ISDIR(dir->DirEntry->DIR_Attr)) {			perror("find lfnslots error: file is not a directory");			return -1;		}		clus = get_fstclus(V, dir->DirEntry);		dir->CurAbsOff = 0;	} else {		if (V->FatType == FAT32) {			clus = 2;		} else clus = 1;	}	if ( fat_iseoc(V,clus) || fat_isfree(V,clus) ) {	// this case should never happen since every directories cointain . and .. 		//we should fetch a new cluster here..			// when they are create so at least 1 cluster.		return -1;		}		oldclus = newclus = clus;	  if ((V->FatType == FAT32) || (rootdirflag !=1)) {	// FAT32 or not rootdir	// now time to allocate space to read clusters;	cluster = alloca(V->bpc);	while (found < n) {		if ((off % V->bpc) == 0) { //fetch new cluster			off = 0;			if ( fat_iseoc(V,newclus) || fat_isfree(V,newclus) ) {				//set properly clus and off according with found, then allocate new cluster, link it and update the file 

⌨️ 快捷键说明

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