/*
Utility for reading long filenames (WIN'95) ;)
I've used the BOOT SECTOR INFORMATION.So if you wanna change it you
can to make it use BIOS services for getting the specific info...
(The problem exists when the BOOT INFO is deleted in the floppy drive)
So Use INT 25h fer getting the BPB & store all values in the variables
If you experience any problems,I'd be glad if you can give me a call.
If you change the code do let me know !
One good thing is you CAN SEARCH FOR DELETED FILES ALSO USING
THIS UTILITY !!!
29/08/96
Send me EMAIL for all comments at:
[email protected]
۲�� Vatsa ���� Srivatsa Srinivasan.
*/
#define _SAFE 100 //safe memory area
#include <conio.h>
#include <math.h>
#include <alloc.h>
#include <dos.h>
#include <dir.h> //Just fer one function current working directory :((
#include <string.h>
typedef unsigned long ULI_;
typedef unsigned int UI_;
typedef unsigned char UC_;
ULI_ SPC;//Sectors per Cluster
ULI_ NOC;//Number of Clusters
ULI_ BPC;//Bytes per cluster
ULI_ BPS;//Bytes per sector
ULI_ NOF;//Number of FAT
ULI_ SPF;//Sectors per FAT
ULI_ SRD;//Sector root directory
ULI_ NRE;//Number of root directory entries
ULI_ RSB;//Reserved sectors at beggining (This is used when you compress the disk!!)
int drive=0;//A=0,B=1,C=2
struct file
{
UC_ filename[14];
UC_ *long_filename;
UC_ attrib;
UI_ time;
UI_ date;
ULI_ cluster;
ULI_ sector;
ULI_ file_size;
};
struct FileControl
{
char path[MAXPATH]; //disk functions file path without long filenames :((
ULI_ df_file_number;
ULI_ df_sect_at;
ULI_ df_current_off;
ULI_ df_check_FAT;
struct file FI;
};
int get_boot_info()
{
struct fatinfo diskinfo;
UC_ *data;
int flag;
cprintf("\r\nGetting BOOT SECTOR info... ");
drive=getdisk();
getfat(drive+1,&diskinfo);
SPC=diskinfo.fi_sclus; NOC=diskinfo.fi_nclus; BPC=diskinfo.fi_bysec;
data = (char *) calloc(BPS+_SAFE, sizeof(char));
absread(drive,1L,0L,data);
NOF=data[0x10];
SPF=data[0x17]*256L+data[0x16];
RSB=data[0x0F]*256L+data[0x0E];
BPS=data[0x0C]*256L+data[0x0B];
NRE=data[0x12]*256L+data[0x11];
cprintf("DONE :)");
if(RSB!=1) { cprintf("\r\n Probably has a device driver & is compressed.No Probs."); }
free(data);
return 0;
}
UI_ get_ROOT_sector()
{
SRD=(SPF*NOF)+RSB;
return SRD;
}
char *get_path_at(char *path,int at)
{
int t=0,a=0,b=0;
char filename[80];
strcpy(filename,"");
while(path[a++]!='\\');
while(t!=at)
{
b=0;
while(path[a]!='\\' && path[a]!='\0') filename[b++]=path[a++];
while(path[a]=='\\') a++;
t++;
if(path[a]=='\0' && at!=t) { b=0; break;}
}
filename[b]='\0';
return filename;
}
ULI_ clust_to_sect(ULI_ var)
{ return ((var-2)*SPC)+(NRE/16)+(NOF*SPF+RSB); }
ULI_ sect_to_clust(ULI_ var)
{
// if(var<(NRE/16)+(NOF*SPF+1)) return var;
return ((var-(NRE/16)-(NOF*SPF+RSB))/SPC)+2;
}
void load_structure(UC_ *data,struct file *temp,int aa)
{
int t=0,a=0;
data+=aa*32;
while(t<0x08 && data[t]!=' ') temp->filename[a++]=data[t++];
temp->filename[a++]='.';
t=0x08;
while(t<0x0B && data[t]!=' ') temp->filename[a++]=data[t++];
if(temp->filename[a-1]=='.') a--;
temp->filename[a]='\0';
a=0; t=0x0B;
temp->attrib=data[t++]; t=0x16;
temp->time=data[t+1]*256L+data[t]; t+=2;
temp->date=data[t+1]*256L+data[t]; t+=2;
temp->cluster=(data[t+1]*256L);
temp->cluster+=data[t];
t+=2;
temp->sector=clust_to_sect(temp->cluster);
temp->file_size = data[t+3] & 0xff; temp->file_size<<=8;
temp->file_size += data[t+2] & 0xff; temp->file_size<<=8;
temp->file_size += data[t+1] & 0xff; temp->file_size<<=8;
temp->file_size += data[t] & 0xff;
temp->long_filename=0;
}
ULI_ get_link_cluster(ULI_ clust)
{
ULI_ sector=0,os;
ULI_ next;
UC_ *data;
if(NOC>=4087L)
sector=clust/256L+RSB;
else
sector=clust/340L+RSB;
data = (char *) calloc(BPS+_SAFE, sizeof(char));
if(data==0) { cprintf("Not enough memory to read FAT"); exit(1); }
absread(drive,1,sector,data);
if(NOC>=4087L)
{
sector=clust-((sector-RSB)*256L);
sector*=2;
next=data[sector+1]*256L+data[sector];
}
else //Why does DOS have to be so smart? 12 bits ? That's not FAT ;)
{
//This is just an aprox. if u know any other way USE IT!
sector=clust-((sector-1)*341.333333333L);
os=sector*1.5;
next=data[os+1]*256L+data[os];
if(fmod(sector,2)==0)
next&=0x0FFF;
else
next>>=4;
}
free(data);
if(next>0x0FF8 && next<0x0FFF && NOC<4087L) next=clust; //<EOF>
if(next>0x0FFF8 && next<0x0FFFF && NOC>=4087L) next=clust; //<EOF>
if(next==0)
{
cprintf("\r\n The file reports that it occupies a certain area");
cprintf("\r\n but does not show the same in FAT1 ,Run some Disk Scanner FAST");
cprintf("\r\n :(( ... Taking default values");
next=clust+1;
}
return next;
}
struct file *get_first(struct FileControl *FC)
{
int t=1,max_numb=BPS/32;
char present_search[80];
ULI_ cluster;
UC_ *data;
data = (UC_ *) calloc(BPS+_SAFE, sizeof(char));
FC->df_sect_at=get_ROOT_sector();
FC->df_check_FAT=0; FC->df_current_off=0;
if(strcmp(FC->path,"\\")==0) return &FC->FI;
absread(drive,1,FC->df_sect_at,data);
strcpy(present_search,get_path_at(FC->path,t));
for(;;)
{
if(FC->df_current_off>=max_numb)
{
FC->df_check_FAT++;
if(FC->df_check_FAT>=SPC)
{
// cprintf("\r\n Verifying FAT ... ");
if(FC->df_sect_at>=NOF*SPF+RSB && FC->df_sect_at<=NOF*SPF+RSB+NRE/16) FC->df_sect_at++; //This means you're in the Root Directory!
else
FC->df_sect_at=clust_to_sect(get_link_cluster(sect_to_clust(FC->df_sect_at)));
FC->df_check_FAT=0;
// cprintf(" DONE :)");
}
else
FC->df_sect_at++;
absread(drive,1,FC->df_sect_at,data);
FC->df_current_off=0;
}
load_structure(data,&FC->FI,FC->df_current_off);
if(FC->FI.filename[0]=='\0') break;
if(strcmp(present_search,FC->FI.filename)==0)
{
t++;
load_structure(data,&FC->FI,FC->df_current_off);
strcpy(present_search,get_path_at(FC->path,t));
if(present_search[0]=='\0')
{
cprintf("\r\n -- Path wildcard found correct :) --",t);
cprintf("\r\n PATH : %s",FC->path);
FC->df_sect_at=FC->FI.sector; FC->df_current_off=0; FC->df_check_FAT=0;
free(data);
return &FC->FI;
}
FC->df_sect_at=FC->FI.sector; FC->df_current_off=-1; FC->df_check_FAT=0;
absread(drive,1,FC->df_sect_at,data);
}
FC->df_current_off++;
}
cprintf("\r\n -- Unable to trace path :( --");
free(data);
return 0;
}
struct file *get_next(struct FileControl *FC)
{
int max_numb=BPS/32;
ULI_ cluster;
UC_ *data;
// if(FC->FI.long_filename!=NULL) free(FC->FI.long_filename); //deallocate previous allocated memory!
data = (UC_ *) calloc(BPS+_SAFE, sizeof(char));
absread(drive,1,FC->df_sect_at,data);
if(FC->df_current_off>=max_numb)
{
FC->df_check_FAT++;
if(FC->df_check_FAT>=SPC)
{
// cprintf("\r\n Verifying FAT ... ");
if(FC->df_sect_at>=NOF*SPF+RSB && FC->df_sect_at<=NOF*SPF+RSB+NRE/16) FC->df_sect_at++;
else
{
cluster=sect_to_clust(FC->df_sect_at);
cluster=get_link_cluster(cluster);
FC->df_sect_at=clust_to_sect(cluster);
}
FC->df_check_FAT=0;
// cprintf(" DONE :)");
}
else
FC->df_sect_at++;
// cprintf("\r\n Reading.. ");
absread(drive,1,FC->df_sect_at,data);
FC->df_current_off=0;
}
load_structure(data,&FC->FI,FC->df_current_off);
if(FC->FI.filename[0]=='\0') { free(data);return 0;}
FC->df_current_off++;
free(data);
return &FC->FI;
}
struct file *get_long(struct FileControl *FC)
{
int set_1=2,lv=0,lt=0,max_long,k;
ULI_ cluster;
UC_ *data,*long_data;
char *filename;
data = (UC_ *) calloc(BPS+_SAFE, sizeof(char));
if(data==0) { cprintf("\r\n NO_MEM 1"); exit(1); }
while(set_1!=0)
{
absread(drive,1,FC->df_sect_at,data);
if(FC->df_current_off>=BPS/32)
{
FC->df_check_FAT++;
if(FC->df_check_FAT>=SPC)
{
// cprintf("\r\n Verifying FAT ... ");
if(FC->df_sect_at>=NOF*SPF+RSB && FC->df_sect_at<=NOF*SPF+RSB+NRE/16) FC->df_sect_at++;
else
{
cluster=sect_to_clust(FC->df_sect_at);
cluster=get_link_cluster(cluster);
FC->df_sect_at=clust_to_sect(cluster);
}
FC->df_check_FAT=0;
// cprintf(" DONE :)");
}
else
FC->df_sect_at++;
// cprintf("\r\n Reading.. ");
absread(drive,1,FC->df_sect_at,data);
FC->df_current_off=0;
}
load_structure(data,&FC->FI,FC->df_current_off);
if(FC->FI.filename[0]=='\0')
{
free(data);
if(set_1!=2) free(long_data);
return 0;
}
FC->df_current_off++;
if(FC->FI.cluster!=0 && set_1==1)
{
lt=(max_long+1)*32;
lt--;
lv=0;
while(lt>0)
{
lt--;
for(k=0;k<4;k++) { filename[lv]=long_data[lt]; lt-=2; lv++; }
filename[lv]=long_data[lt]; lt-=5; lv++;
for(k=0;k<5;k++) { filename[lv]=long_data[lt]; lt-=2; lv++; }
filename[lv]=long_data[lt]; lt-=4; lv++;
for(k=0;k<2;k++) { filename[lv]=long_data[lt]; lt-=2; lv++; }
}
FC->FI.long_filename=filename;
// free(long_data);
// cprintf("<- DONE! ;) ");
set_1=0;
}
else
if(FC->FI.cluster==0 && FC->FI.attrib==0xF && (set_1==0 || set_1==2) && FC->FI.filename[0]!=229)
{
// cprintf("\r\n Recieving LONG ..... ->");
set_1=1;
lt=(FC->df_current_off-1)*32;
max_long=(data[lt]-'A');
long_data = (UC_ *) calloc((max_long+1)*32L+_SAFE, sizeof(char));
filename = (UC_ *) calloc((max_long+1)*15L+_SAFE, sizeof(char));
if(long_data==0) { cprintf("\r\n NO_MEM 2"); exit(1); }
if(filename==0) { cprintf("\r\n NO_MEM for longfilename"); exit(1); }
}
if(set_1==1)
{
lt=(FC->df_current_off-1)*32;
lt=FC->df_current_off*32-1;
k=0;
while(k<32)
{
long_data[lv]=data[lt];
k++;
lv++; lt--;
}
// cprintf("��");
}
else
if(set_1==2 && ( FC->FI.attrib & 0x08 )==0) break; //Why care about disk volumes ??
}
free(data);
if(set_1!=2) free(long_data);
return &FC->FI;
}
//Cut this if you dont need this.....
//--------------------------------------------------------------------
///*
int to_day(ULI_ date) { date&=0x001F; return date; }
int to_month(ULI_ date) { date&=0x01E0; date>>=5; return date; }
int to_year(ULI_ date) { date&=0xFE00; date>>=9; return date+1980; }
int to_seconds(ULI_ date) { date&=0x001F; return date*2; }//seconds can NEVER be odd!
int to_min(ULI_ date) { date&=0x07E0; date>>=5; return date; }
int to_hour(ULI_ date) { date&=0xF800; date>>=0xB; return date; }
void main ( argc, argv ) // Just an example..
int argc ;
char *argv[] ;
{
struct FileControl FC; //Main structure like ffblk in <dir.h>
ULI_ t=0;
char page=0,scroll=0,*temp;
// cprintf("\r\n Enter Path : ");
// scanf("%s",FC.path);
if(argc==2 || argc==1 )
{
getcwd(FC.path,MAXPATH); temp=FC.path; temp+=2; //Best way to shift text ? Huh ? Power of C !
strcpy(FC.path,temp);
if(argc==2 && (strcmp(argv[1],"/p")==0 || strcmp(argv[1],"/P")==0)) scroll=1;
}
else
{
strcpy(FC.path,argv[1]);
if(argc>2 && (strcmp(argv[2],"\\p")==0 || strcmp(argv[2],"\\P")==0)) scroll=1;
t=0;
while(FC.path[t]!='\0') { FC.path[t]=toupper(FC.path[t]); t++; }
}
t=0;
get_boot_info(); // :(( This you'll have to do at the beg of your prog :((
if(get_first(&FC)!=0)//something like findfirst()
{
while(get_long(&FC)!=0)//something like findnext()
{
if(FC.FI.filename[0]!=229) // Deleted file (Have programmed to get the deleted file too so dont display it)
{
if((FC.FI.attrib&0x10)!=0)
{
textcolor(15);
cprintf("\r\n%ld> %7ld %02d-%02d-%4d %02d:%02d:%02d � %15s ",t
,FC.FI.file_size,to_day(FC.FI.date),to_month(FC.FI.date),to_year(FC.FI.date)
,to_hour(FC.FI.time),to_min(FC.FI.time),to_seconds(FC.FI.time),FC.FI.filename);
}
else
{
textcolor(7);
cprintf("\r\n%ld> %7ld %02d-%02d-%4d %02d:%02d:%02d %15s ",t
,FC.FI.file_size,to_day(FC.FI.date),to_month(FC.FI.date),to_year(FC.FI.date)
,to_hour(FC.FI.time),to_min(FC.FI.time),to_seconds(FC.FI.time),FC.FI.filename);
}
if(FC.FI.long_filename!=0)
cprintf(" � %s",FC.FI.long_filename);
t++;
if(scroll==1) { page++; if(page>20) { getch(); page=0; } }
}
if(FC.FI.long_filename!=NULL)
free(FC.FI.long_filename); //deallocate previous allocated memory for long filenames!
}
textcolor(7);
cprintf("\r\n\n Total Enteries = %ld \r\n",t);
}
}
//*/