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

📄 libfat.c

📁 Support library to access and manipulate FAT12 / FAT16 / FAT32 file systems - Includes a FUSE filesy
💻 C
📖 第 1 页 / 共 5 页
字号:
/*OS 	libfat: library to access a fat32 filesystem  	Rev 0.3	aka "Beta version"		Copyright (C) 2006-2007  Paolo Angelelli <angelell@cs.unibo.it>		Acknowledgments to Salvatore Isaja, auctor of fat support for freedos32		since utf8/16 routines are taken from freedos32 unicode module,	Renzo Davoli for bugfixes, big endian support and more.		This software is free software; it can be (re)distributed under the terms 	of the GNU GPL General Public License as published by the Free Software 	Foundation; either version 2 of the License, or any later version.		The Program is distributed in the hope that it will be useful,	but WITHOUT ANY WARRANTY; without even the implied warranty of	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the	GNU General Public License for more details.*//***********************************************  *	LIBFAT.c				*	Current known problems (limitations) :*	- May have problems if the filesistem *	  was accessed before with MS-DOS or *	  something that does not support Long Filenames*	- to be cont'd	=)*	TODO: fix function to create time to support 		timezone.* 	TODO: Refuse to mount if dirty bit is up***********************************************/#include <config.h>#include "libfat.h"#include <stdlib.h>#include <fcntl.h>#include <unistd.h>#include <string.h>#include <linux/unistd.h>#include <errno.h>#include <glib.h>#include <pthread.h>#include <execinfo.h>#include <stdarg.h>#include <dlfcn.h>#include <errno.h>#ifndef POPULATE_FREELIST_BUFSZ#define POPULATE_FREELIST_BUFSZ 8192#endifoff64_t byte_offset(Volume_t *V, DWORD Cluster, DWORD Offset) {	off64_t clus = Cluster;	off64_t off	 = Offset;		if (Cluster == 1) 		if (V->FatType != FAT32) return (V->rootdir16off + off);	/* else error */			return  ( ((clus - 2) * V->bpc64) + V->fdb64 + off );}int fat_isfree(Volume_t *V,DWORD value) {    if (V->FatType == FAT32) {        return FAT32_ISFREE(value);    } else if (V->FatType == FAT16) {        return FAT16_ISFREE(value);    } else {        return FAT12_ISFREE(value);    }    return 0;}int fat_isbad(Volume_t *V,DWORD value) {    if (V->FatType == FAT32) {        return FAT32_ISBAD(value);    } else if (V->FatType == FAT16) {        return FAT16_ISBAD(value);    } else {        return FAT12_ISBAD(value);    }    return 0;}int fat_iseoc(Volume_t *V,DWORD value) {    if (V->FatType == FAT32) {        return FAT32_ISEOC(value);    } else if (V->FatType == FAT16) {        return FAT16_ISEOC(value);    } else {        return FAT12_ISEOC(value);    }    return 0;}int fat_legalclus(Volume_t *V,DWORD value) {    if (V->FatType == FAT32) {        return FAT32_LEGALCLUS(value);    } else if (V->FatType == FAT16) {        return FAT16_LEGALCLUS(value);    } else {        return FAT12_LEGALCLUS(value);    }    return 0;}DWORD fat_eocvalue(Volume_t *V) {    if (V->FatType == FAT32) {        return FAT32_EOC_VALUE;    } else if (V->FatType == FAT16) {        return FAT16_EOC_VALUE;    } else {        return FAT12_EOC_VALUE;    }    return 0;}static ssize_t readn(int fd, void *buf, size_t count) {	int done = 0;	int res;		while (count > 0) {		res = read(fd, (void *) &(((char *) buf)[done]), count);		if (res <= 0) {	// 0 indicates EOF, and it should never happen here.			fprintf(stderr,"read() error. line: %d\n",__LINE__);			return -1;		} else {			done += res;			count -= res;		}	}	return done;	}static ssize_t writen(int fd, const char *buf, size_t count) {	int done = 0;	int res;		while (count > 0) {		res = write(fd, &(buf[done]), count);		if (res < 0) {			perror("write() error");			return -1;		} else {			done += res;			count -= res;		}	}	return done;	}time_t fat_mktime(int s, int m, int h, int d, int mo, int y) {	struct tm t;	memset((char *) &t, 0, sizeof(struct tm));		t.tm_sec=s;         /* seconds */    t.tm_min=m;         /* minutes */    t.tm_hour=h;        /* hours */    t.tm_mday=d;        /* day of the month */    t.tm_mon=mo;         /* month */    t.tm_year=y;        /* year */ 	return mktime(&t);}time_t fat_mktime2(DirEntry_t *D) {	int s=((((BYTE *) &(D->DIR_WrtTime))[0] & 0x1f) * 2);	int m=((((((BYTE *) &(D->DIR_WrtTime))[1]&0x7) << 3) + (((BYTE *) &(D->DIR_WrtTime))[0] >> 5)));	int h=(((BYTE *) &(D->DIR_WrtTime))[1] >> 3);	int d=(((BYTE *) &(D->DIR_WrtDate))[0] & 0x1f);	int mo=((((((BYTE *) &(D->DIR_WrtDate))[1]&0x1) << 3) + (((BYTE *) &(D->DIR_WrtDate))[0] >> 5)));	int y=(( ((BYTE *) &(D->DIR_WrtDate))[1] >> 1) + 80); 	return fat_mktime(s,m,h,d,mo,y);}int fat_fill_time(WORD *Date, WORD *Time, time_t t) {	// works ok.	struct tm time;	WORD date=0;	WORD tim=0;	WORD bmask3=0x07FF;	WORD bmask2=0x01FF;	WORD bmask1=0x001F;		gmtime_r(&t, &time);		date = (WORD) time.tm_mday;	date &= bmask1; // to set 0 first 11 bits;	date |= ((WORD) time.tm_mon) << 5;	date &= bmask2; // to set 0 first 6 bits;	date |= (((WORD) ((time.tm_year + 1900) -1980)) << 9);		tim = (WORD) (time.tm_sec / 2);	tim &= bmask1;	tim |= (((WORD) (time.tm_min)) << 5);	tim &= bmask3;	tim |= (((WORD) (time.tm_hour)) << 11); 		*Time = EFW(tim);	*Date = EFW(date);	return 0;	}/*************************************************************************	Functions to access the FAT										 	*************************************************************************//* FAT32 PRIMITIVES *//* The location of a valid cluster N into the FAT32 FAT       *//* Returns 0 on success, or a negative error code on failure. *//* Called by fat32_read_entry and fat32_write_entry.          *//* Put into Sector the sector number where the entry is, and  *//* into EntryOffset the offset of the entry in the sector     *//* FatNum = number of which fat we want to look into. 0 is 1st*//* N = the cluster we want sector and offset of. first is   2 */#if 0	// Useless atmstatic int fat32_cluster_entry(Volume_t *V, DWORD N, int FatNum,                               DWORD *Sector, DWORD *EntryOffset) {  DWORD FATSz, EntryPerSec32;  WORD bytspersec = EFW(V->Bpb.BPB_BytsPerSec);//  DWORD entry;  if (N > V->DataClusters + 1) return -ENXIO;  FATSz = EFD(V->Bpb.BPB_FATSz32) * bytspersec;//  entry = ( FatNum * FATSz ) + ( EFW(V->Bpb.BPB_ResvdSecCnt) * bytspersec ) + (N * 4);  // printf("---- %u\n",entry);  EntryPerSec32 = EFW(V->Bpb.BPB_BytsPerSec) / 4; /* fat32 entries are 4 bytes long */  *Sector      = ( FatNum * FATSz ) + EFW(V->Bpb.BPB_ResvdSecCnt) + 		    ( N / EntryPerSec32 );  *EntryOffset = ( (N % EntryPerSec32) * 4 );  return 0;}#endif/* The location of a valid cluster N into the FAT32 FAT       *//* Returns the offset of the entry on success, or a negative  *//*									error code on failure.    *//* FatNum = number of which fat we want to look into. 0 is 1st*//* N = the cluster we want sector and offset of. first is   2 */off64_t fat32_cluster_off(Volume_t *V, DWORD N, int FatNum) {  off64_t rsvdbc = V->rsvdbytecnt;  off64_t fatn	= FatNum;  off64_t fatsz = V->fatsz;  off64_t entry = N;  off64_t entrysz = 4;  return ( rsvdbc + ( fatn * fatsz )  + ( entry * entrysz ));}/* Reads the value of the specified cluster entry in a FAT32 FAT.      *//* Returns 0 on success, or a negative error code on failure.          */int fat32_read_entry(Volume_t *V, DWORD N, int FatNum, DWORD *Value) {  int   Res;//  DWORD Sector, EntryOffset;  DWORD Entry;    off64_t fatoffset;  /*	finding position	*/	  if ((fatoffset = fat32_cluster_off(V, N, FatNum)) <= 0) return (int) fatoffset;//  if ((Res = fat_readbuf(V, Sector)) < 0) return Res;/*	lseek(SEEK_SET)	*/   if ( (Res = lseek64(V->blkDevFd, fatoffset, SEEK_SET)) < 0) {    fprintf(stderr,"lseek() error in fat32_read_entry(). N: %u, off: %lld\n",N, fatoffset);    return Res;  }/*	read()		*/  if ( (Res = readn(V->blkDevFd, &Entry, 4)) != 4) {    fprintf(stderr,"readn() error in fat32_read_entry(). N: %u, off: %lld\n",N, fatoffset);    return -1;  }    *Value = EFD(Entry) & 0x0FFFFFFF;  return 0;}#ifdef FATWRITE/* Writes the value of the specified cluster entry in a FAT32 FAT.          *//* Returns 0 on success, or a negative error code on failure.               */int fat32_write_entry(Volume_t *V, DWORD N, int FatNum, DWORD Value) {  int   Res;//  DWORD Sector, EntryOffset;  DWORD val;  off64_t off;  Value &= 0x0FFFFFFF;  if ((Res = fat32_read_entry(V, N, FatNum, &val)) != 0) {  	perror("fat32_write_entry error");  	return -1;  }    val &= 0xF0000000;  Value = Value | val;   /*	finding position	*/  if ((off = fat32_cluster_off(V, N, FatNum)) <= 0) return (int) off;/*	lseek(SEEK_SET)	*/   if ( (Res = lseek64(V->blkDevFd, off, SEEK_SET)) < 0) {    perror("lseek() error in fat32_read_entry()");    return -1;  }/*	write()		*/	Value=EFD(Value);  if ( (Res = writen(V->blkDevFd, (char*) &Value, 4)) != 4) {    perror("writen() error in fat32_read_entry()");    return -1;  }  return 0;}/* Writes the value of the specified cluster entry in all FAT32 FATs of the volume V *//* Returns 0 on success, or a negative error code on failure.               */int fat32_writen_entry(Volume_t *V, DWORD N, DWORD Value) {	int i;	int numfats = V->numfats;	for (i=0; i < numfats; i++) {		if ( fat32_write_entry(V, N, i, Value) != 0) {			perror("fat32_write_entry error in fat32_writen_entry()");			return -1;		}		 	}	return 0;}/* Unlinks (marks as free) all the clusters of the chain starting from *//* cluster Cluster (that must be part of a valid chain) until the EOC. */static int fat32_unlinkn(Volume_t *V, DWORD Cluster) {  int   Res;  DWORD Next;  int i =0;  if ((fat_isfree(V,Cluster)) || (FAT32_ISEOC(Cluster))) return 0;	  if (FAT32_ISBAD(Cluster)) return -1;    do {    /* Read the next entry in the chain */    if ( (Res = fat32_read_entry(V, Cluster, 0, &Next)) != 0 ) { 		fprintf(stderr,"unlinkn() error cycle: %d Line: %d",i, __LINE__);		return -1; 	}    /* Update every FAT in the volume */    if ( (Res = fat32_writen_entry(V, Cluster, 0)) != 0 ) { 		fprintf(stderr,"unlinkn() error cycle: %d Line: %d",i,__LINE__);	  	return -1; 	}    /* Update FSInfo Sector values	*/    V->freecnt++;//    if (Cluster < V->nextfree ) ->nextfree = Cluster;    Cluster = Next; 	i++; }  while (!(FAT32_ISEOC(Next)));  fprintf(stderr,"unkinkn: freecnt: %u, i:%d\n", V->freecnt,i);  return 0;}/* FAT16 PRIMITIVES */static int fat16_read_entry(Volume_t *V, DWORD N, int FatNum, DWORD *Value) {	*Value = EFW(((WORD*) V->fat)[N]);	return 0; }static int fat16_write_entry(Volume_t *V, DWORD N, int FatNum, DWORD Value) {	WORD val;	val = Value;	val = EFW(val);	((WORD*) V->fat)[N] = val;	return 0;}static int fat16_unlinkn(Volume_t *V, DWORD Cluster) {  int   Res;  DWORD Next;  int 	i = 0;	  if ((FAT16_ISFREE(Cluster)) || (FAT16_ISEOC(Cluster))) return 0;	  if (FAT16_ISBAD(Cluster)) return -1;    do {    /* Read the next entry in the chain */    if ( (Res = fat16_read_entry(V, Cluster, 0, &Next)) != 0 ) { 		fprintf(stderr,"unlinkn() error cycle: %d Line: %d",i, __LINE__);		return -1; 	}    /* Update every FAT in the volume */    if ( (Res = fat16_write_entry(V, Cluster, 0,  0)) != 0 ) { 		fprintf(stderr,"unlinkn() error cycle: %d Line: %d",i,__LINE__);	  	return -1; 	}    /* Update FSInfo Sector values	*/    V->freecnt++;//    if (Cluster < V->nextfree ) ->nextfree = Cluster;    Cluster = Next; 	i++; }  while (!(FAT16_ISEOC(Next)));   return 0;}/* FAT12 PRIMITIVES */static int fat12_read_entry(Volume_t *V, DWORD N, int FatNum, DWORD *Value) {

⌨️ 快捷键说明

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