Skip to content

Commit

Permalink
Merge pull request joncampbell123#4973 from maxpat78/cmd_dir_patch
Browse files Browse the repository at this point in the history
Fix reported size issues in builtin DIR command
  • Loading branch information
joncampbell123 authored Apr 22, 2024
2 parents ee03a71 + 500871a commit 70106c1
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 45 deletions.
6 changes: 4 additions & 2 deletions include/dos_system.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#define DOS_PATHLENGTH 255u
#define DOS_TEMPSIZE 1024u
#define DOSERR_FUNCTION_NUMBER_INVALID 1

void DOS_SetError(uint16_t code);

enum {
Expand Down Expand Up @@ -314,8 +315,9 @@ class DOS_Drive {
virtual HANDLE CreateOpenFile(char const* const name)=0;
#endif
virtual bool Rename(const char * oldname,const char * newname)=0;
virtual bool AllocationInfo(uint16_t * _bytes_sector,uint8_t * _sectors_cluster,uint16_t * _total_clusters,uint16_t * _free_clusters)=0;
virtual bool AllocationInfo32(uint32_t * _bytes_sector,uint32_t * _sectors_cluster,uint32_t * _total_clusters,uint32_t * _free_clusters) { (void)_bytes_sector; (void)_sectors_cluster; (void)_total_clusters; (void)_free_clusters; return false; }
virtual bool AllocationInfo(uint16_t* _bytes_sector, uint8_t* _sectors_cluster, uint16_t* _total_clusters, uint16_t* _free_clusters) = 0;
virtual bool AllocationInfo32(uint32_t * _bytes_sector,uint32_t * _sectors_cluster,uint32_t * _total_clusters,uint32_t * _free_clusters) { (void)_bytes_sector; (void)_sectors_cluster; (void)_total_clusters; (void)_free_clusters; return false; }
virtual bool AllocationInfo64(uint32_t* _bytes_sector, uint32_t* _sectors_cluster, uint64_t* _total_clusters, uint64_t* _free_clusters) { (void)_bytes_sector; (void)_sectors_cluster; (void)_total_clusters; (void)_free_clusters; return false; }
virtual bool FileExists(const char* name)=0;
virtual bool FileStat(const char* name, FileStat_Block * const stat_block)=0;
virtual uint8_t GetMediaByte(void)=0;
Expand Down
2 changes: 1 addition & 1 deletion src/dos/dos_programs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1175,7 +1175,7 @@ class MOUNT : public Program {
// freesize in kb
sprintf(teststr,"512,1,2880,%d",freesize*1024/(512*1)>2880?2880:freesize*1024/(512*1));
} else {
if (freesize>1919) freesize=1919;
//if (freesize>1919) freesize=1919;
uint16_t numc=type=="cdrom"?1:32;
uint32_t total_size_cyl=32765;
uint32_t tmp=(uint32_t)freesize*1024*1024/(type=="cdrom"?2048*1:512*32);
Expand Down
173 changes: 146 additions & 27 deletions src/dos/drive_local.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2249,36 +2249,155 @@ bool localDrive::Rename(const char * oldname,const char * newname) {
#if !defined(WIN32)
#include <sys/statvfs.h>
#endif
bool localDrive::AllocationInfo(uint16_t * _bytes_sector,uint8_t * _sectors_cluster,uint16_t * _total_clusters,uint16_t * _free_clusters) {
*_bytes_sector=allocation.bytes_sector;
*_sectors_cluster=allocation.sectors_cluster;
*_total_clusters=allocation.total_clusters;
*_free_clusters=allocation.free_clusters;
if ((!allocation.total_clusters && !allocation.free_clusters) || freesizecap) {
bool res=false;

bool localDrive::AllocationInfo64(uint32_t* _bytes_sector, uint32_t* _sectors_cluster, uint64_t* _total_clusters, uint64_t* _free_clusters) {
*_bytes_sector = allocation.bytes_sector;
*_sectors_cluster = allocation.sectors_cluster;
*_total_clusters = allocation.total_clusters;
*_free_clusters = allocation.free_clusters;
if((!allocation.total_clusters && !allocation.free_clusters) || freesizecap) {
bool res = false;
#if defined(WIN32)
long unsigned int dwSectPerClust, dwBytesPerSect, dwFreeClusters, dwTotalClusters;
uint8_t drive=strlen(basedir)>1&&basedir[1]==':'?toupper(basedir[0])-'A'+1:0;
if (drive>26) drive=0;
char root[4]="A:\\";
root[0]='A'+drive-1;
if (basedir[0]=='\\' && basedir[1]=='\\')
res = GetDiskFreeSpace(basedir, &dwSectPerClust, &dwBytesPerSect, &dwFreeClusters, &dwTotalClusters);
DWORD dwSectPerClust, dwBytesPerSect, dwFreeClusters, dwTotalClusters;
uint64_t qwFreeClusters, qwTotalClusters;
uint8_t drive = strlen(basedir) > 1 && basedir[1] == ':' ? toupper(basedir[0]) - 'A' + 1 : 0;
if(drive > 26) drive = 0;
char root[4] = "A:\\";
root[0] = 'A' + drive - 1;
char* diskToQuery;

if(basedir[0] == '\\' && basedir[1] == '\\')
diskToQuery = basedir;
else
res = GetDiskFreeSpace(drive?root:NULL, &dwSectPerClust, &dwBytesPerSect, &dwFreeClusters, &dwTotalClusters);
if (res) {
unsigned long total = dwTotalClusters * dwSectPerClust;
int ratio = total > 2097120 ? 64 : (total > 1048560 ? 32 : (total > 524280 ? 16 : (total > 262140 ? 8 : (total > 131070 ? 4 : (total > 65535 ? 2 : 1))))), ratio2 = ratio * dwBytesPerSect / 512;
*_bytes_sector = 512;
*_sectors_cluster = ratio;
*_total_clusters = total > 4194240? 65535 : (uint16_t)(dwTotalClusters * dwSectPerClust / ratio2);
*_free_clusters = dwFreeClusters ? (total > 4194240? 61440 : (uint16_t)(dwFreeClusters * dwSectPerClust / ratio2)) : 0;
if (rsize) {
totalc=dwTotalClusters * dwSectPerClust / ratio;
freec=dwFreeClusters * dwSectPerClust / ratio;
}
diskToQuery = drive ? root : NULL;

res = GetDiskFreeSpace(diskToQuery, &dwSectPerClust, &dwBytesPerSect, &dwFreeClusters, &dwTotalClusters);
ULARGE_INTEGER FreeBytesAvailableToCaller, TotalNumberOfBytes;
GetDiskFreeSpaceEx(diskToQuery, &FreeBytesAvailableToCaller, &TotalNumberOfBytes, NULL);
qwTotalClusters = TotalNumberOfBytes.QuadPart / (dwSectPerClust * dwBytesPerSect);
qwFreeClusters = FreeBytesAvailableToCaller.QuadPart / (dwSectPerClust * dwBytesPerSect);

*_bytes_sector = dwBytesPerSect;
*_sectors_cluster = dwSectPerClust;
*_total_clusters = qwTotalClusters;
*_free_clusters = qwFreeClusters;

if(res) {
Bitu total = qwTotalClusters * dwSectPerClust;
int ratio = total > 2097120 ? 64 : (total > 1048560 ? 32 : (total > 524280 ? 16 : (total > 262140 ? 8 : (total > 131070 ? 4 : (total > 65535 ? 2 : 1))))), ratio2 = ratio * dwBytesPerSect / 512;
if(rsize) {
totalc = qwTotalClusters * dwSectPerClust / ratio;
freec = qwFreeClusters * dwSectPerClust / ratio;
}
#else
struct statvfs stat;
res = statvfs(basedir, &stat) == 0;
if(res) {
int ratio = stat.f_blocks / 65536, tmp = ratio;
*_bytes_sector = 512;
*_sectors_cluster = stat.f_frsize / 512 > 64 ? 64 : stat.f_frsize / 512;
if(ratio > 1) {
if(ratio * (*_sectors_cluster) > 64) tmp = (*_sectors_cluster + 63) / (*_sectors_cluster);
*_sectors_cluster = ratio * (*_sectors_cluster) > 64 ? 64 : ratio * (*_sectors_cluster);
ratio = tmp;
}
*_total_clusters = stat.f_blocks > 65535 ? 65535 : stat.f_blocks;
*_free_clusters = stat.f_bavail > 61440 ? 61440 : stat.f_bavail;
if(rsize) {
totalc = stat.f_blocks;
freec = stat.f_bavail;
if(ratio > 1) {
totalc /= ratio;
freec /= ratio;
}
}
#endif
if((allocation.total_clusters || allocation.free_clusters) && freesizecap < 3) {
long diff = 0;
if(freesizecap == 2) diff = (freec ? freec : *_free_clusters) - allocation.initfree;
bool g1 = *_bytes_sector * *_sectors_cluster * *_total_clusters > allocation.bytes_sector * allocation.sectors_cluster * allocation.total_clusters;
bool g2 = *_bytes_sector * *_sectors_cluster * *_free_clusters > allocation.bytes_sector * allocation.sectors_cluster * allocation.free_clusters;
if(g1 || g2) {
if(freesizecap == 2) diff *= (*_bytes_sector * *_sectors_cluster) / (allocation.bytes_sector * allocation.sectors_cluster);
*_bytes_sector = allocation.bytes_sector;
*_sectors_cluster = allocation.sectors_cluster;
if(g1) *_total_clusters = allocation.total_clusters;
if(g2) *_free_clusters = allocation.free_clusters;
if(freesizecap == 2) {
if(diff<0 && (-diff)>*_free_clusters)
*_free_clusters = 0;
else
*_free_clusters += (uint16_t)diff;
}
if(*_total_clusters < *_free_clusters) {
if(*_free_clusters > 65525)
*_total_clusters = 65535;
else
*_total_clusters = *_free_clusters + 10;
}
if(rsize) {
if(g1) totalc = *_total_clusters;
if(g2) freec = *_free_clusters;
}
}
}
}
else if(!allocation.total_clusters && !allocation.free_clusters) {
if(allocation.mediaid == 0xF0) {
*_bytes_sector = 512;
*_sectors_cluster = 1;
*_total_clusters = 2880;
*_free_clusters = 2880;
}
else if(allocation.bytes_sector == 2048) {
*_bytes_sector = 2048;
*_sectors_cluster = 1;
*_total_clusters = 65535;
*_free_clusters = 0;
}
else {
// 512*32*32765==~500MB total size
// 512*32*16000==~250MB total free size
*_bytes_sector = 512;
*_sectors_cluster = 32;
*_total_clusters = 32765;
*_free_clusters = 16000;
}
}
}
return true;
}

bool localDrive::AllocationInfo(uint16_t* _bytes_sector, uint8_t* _sectors_cluster, uint16_t* _total_clusters, uint16_t* _free_clusters) {
*_bytes_sector = allocation.bytes_sector;
*_sectors_cluster = allocation.sectors_cluster;
*_total_clusters = allocation.total_clusters;
*_free_clusters = allocation.free_clusters;
if((!allocation.total_clusters && !allocation.free_clusters) || freesizecap) {
bool res = false;
#if defined(WIN32)
long unsigned int dwSectPerClust, dwBytesPerSect, dwFreeClusters, dwTotalClusters;
uint8_t drive = strlen(basedir) > 1 && basedir[1] == ':' ? toupper(basedir[0]) - 'A' + 1 : 0;
if(drive > 26) drive = 0;
char root[4] = "A:\\";
root[0] = 'A' + drive - 1;
if(basedir[0] == '\\' && basedir[1] == '\\')
res = GetDiskFreeSpace(basedir, &dwSectPerClust, &dwBytesPerSect, &dwFreeClusters, &dwTotalClusters);
else
res = GetDiskFreeSpace(drive ? root : NULL, &dwSectPerClust, &dwBytesPerSect, &dwFreeClusters, &dwTotalClusters);
if(res) {
unsigned long total = dwTotalClusters * dwSectPerClust;
int ratio = total > 2097120 ? 64 : (total > 1048560 ? 32 : (total > 524280 ? 16 : (total > 262140 ? 8 : (total > 131070 ? 4 : (total > 65535 ? 2 : 1))))), ratio2 = ratio * dwBytesPerSect / 512;
*_bytes_sector = 512;
*_sectors_cluster = ratio;
*_total_clusters = total > 4194240 ? 65535 : (uint16_t)(dwTotalClusters * dwSectPerClust / ratio2);
*_free_clusters = dwFreeClusters ? (total > 4194240 ? 61440 : (uint16_t)(dwFreeClusters * dwSectPerClust / ratio2)) : 0;
if(rsize) {
totalc = dwTotalClusters * dwSectPerClust / ratio;
freec = dwFreeClusters * dwSectPerClust / ratio;
}
#else
struct statvfs stat;
struct statvfs stat;
res = statvfs(basedir, &stat) == 0;
if (res) {
int ratio = stat.f_blocks / 65536, tmp=ratio;
Expand Down
1 change: 1 addition & 0 deletions src/dos/drives.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ class localDrive : public DOS_Drive {
#endif
bool Rename(const char * oldname,const char * newname) override;
bool AllocationInfo(uint16_t * _bytes_sector,uint8_t * _sectors_cluster,uint16_t * _total_clusters,uint16_t * _free_clusters) override;
bool AllocationInfo64(uint32_t* _bytes_sector, uint32_t* _sectors_cluster, uint64_t* _total_clusters, uint64_t* _free_clusters) override;
bool FileExists(const char* name) override;
bool FileStat(const char* name, FileStat_Block * const stat_block) override;
uint8_t GetMediaByte(void) override;
Expand Down
38 changes: 23 additions & 15 deletions src/shell/shell_cmds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2089,21 +2089,29 @@ void DOS_Shell::CMD_DIR(char * args) {
if (!dirPaused(this, w_size, optP, optW)) {dos.dta(save_dta);return;}
uint8_t drive=dta.GetSearchDrive();
uint64_t free_space=1024u*1024u*100u;
if (Drives[drive]) {
uint32_t bytes_sector32;uint32_t sectors_cluster32;uint32_t total_clusters32;uint32_t free_clusters32;
if ((dos.version.major > 7 || (dos.version.major == 7 && dos.version.minor >= 10)) &&
Drives[drive]->AllocationInfo32(&bytes_sector32,&sectors_cluster32,&total_clusters32,&free_clusters32)) { /* FAT32 aware extended API */
freec=0;
free_space=(uint64_t)bytes_sector32 * (Bitu)sectors_cluster32 * (Bitu)free_clusters32;
} else {
uint16_t bytes_sector;uint8_t sectors_cluster;uint16_t total_clusters;uint16_t free_clusters;
rsize=true;
freec=0;
Drives[drive]->AllocationInfo(&bytes_sector,&sectors_cluster,&total_clusters,&free_clusters);
free_space=(uint64_t)bytes_sector * (Bitu)sectors_cluster * (Bitu)(freec?freec:free_clusters);
rsize=false;
}
}

if(Drives[drive]) {
uint32_t bytes_sector32; uint32_t sectors_cluster32; uint32_t total_clusters32; uint32_t free_clusters32;
uint64_t total_clusters64; uint64_t free_clusters64;
// Since this is the *internal* shell, we want use maximum available query capability at first
if(Drives[drive]->AllocationInfo64(&bytes_sector32, &sectors_cluster32, &total_clusters64, &free_clusters64)) {
freec = 0;
free_space = (uint64_t)bytes_sector32 * (Bitu)sectors_cluster32 * (Bitu)free_clusters64;
}
else if((dos.version.major > 7 || (dos.version.major == 7 && dos.version.minor >= 10)) &&
Drives[drive]->AllocationInfo32(&bytes_sector32, &sectors_cluster32, &total_clusters32, &free_clusters32)) { /* FAT32 aware extended API */
freec = 0;
free_space = (uint64_t)bytes_sector32 * (Bitu)sectors_cluster32 * (Bitu)free_clusters32;
}
else {
uint16_t bytes_sector; uint8_t sectors_cluster; uint16_t total_clusters; uint16_t free_clusters;
rsize = true;
freec = 0;
Drives[drive]->AllocationInfo(&bytes_sector, &sectors_cluster, &total_clusters, &free_clusters);
free_space = (uint64_t)bytes_sector * (Bitu)sectors_cluster * (Bitu)(freec ? freec : free_clusters);
rsize = false;
}
}
#if defined(WIN32) && !(defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR))
if (Network_IsNetworkResource(args)) {
std::string str = MSG_Get("SHELL_CMD_DIR_BYTES_FREE");
Expand Down

0 comments on commit 70106c1

Please sign in to comment.