mirror of
https://github.com/joncampbell123/dosbox-x.git
synced 2025-05-10 04:08:57 +08:00
Incorporate Long Filename Support for DOS version 7 [https://github.com/joncampbell123/dosbox-x/issues/1425]
This commit is contained in:
parent
4d8df4fafa
commit
e31a0a8165
@ -106,11 +106,11 @@ typedef struct dir_struct {
|
||||
|
||||
// TODO: offer a config.h option to opt out of Windows widechar functions
|
||||
dir_information* open_directory(const char* dirname);
|
||||
bool read_directory_first(dir_information* dirp, char* entry_name, bool& is_directory);
|
||||
bool read_directory_next(dir_information* dirp, char* entry_name, bool& is_directory);
|
||||
bool read_directory_first(dir_information* dirp, char* entry_name, char* entry_sname, bool& is_directory);
|
||||
bool read_directory_next(dir_information* dirp, char* entry_name, char* entry_sname, bool& is_directory);
|
||||
dir_information* open_directoryw(const wchar_t* dirname);
|
||||
bool read_directory_firstw(dir_information* dirp, wchar_t* entry_name, bool& is_directory);
|
||||
bool read_directory_nextw(dir_information* dirp, wchar_t* entry_name, bool& is_directory);
|
||||
bool read_directory_firstw(dir_information* dirp, wchar_t* entry_name, wchar_t* entry_sname, bool& is_directory);
|
||||
bool read_directory_nextw(dir_information* dirp, wchar_t* entry_name, wchar_t* entry_sname, bool& is_directory);
|
||||
|
||||
#else
|
||||
|
||||
@ -123,8 +123,9 @@ typedef struct dir_struct {
|
||||
} dir_information;
|
||||
|
||||
dir_information* open_directory(const char* dirname);
|
||||
bool read_directory_first(dir_information* dirp, char* entry_name, bool& is_directory);
|
||||
bool read_directory_next(dir_information* dirp, char* entry_name, bool& is_directory);
|
||||
bool read_directory_first(dir_information* dirp, char* entry_name, char* entry_sname, bool& is_directory);
|
||||
bool read_directory_next(dir_information* dirp, char* entry_name, char* entry_sname, bool& is_directory);
|
||||
|
||||
#define open_directoryw open_directory
|
||||
#define read_directory_firstw read_directory_first
|
||||
#define read_directory_nextw read_directory_next
|
||||
|
@ -21,6 +21,7 @@
|
||||
#define DOSBOX_DOS_INC_H
|
||||
|
||||
#include <stddef.h>
|
||||
#define CTBUF 127
|
||||
|
||||
#ifndef DOSBOX_DOS_SYSTEM_H
|
||||
#include "dos_system.h"
|
||||
@ -28,7 +29,6 @@
|
||||
#ifndef DOSBOX_MEM_H
|
||||
#include "mem.h"
|
||||
#endif
|
||||
|
||||
#include <stddef.h> //for offsetof
|
||||
|
||||
#ifdef _MSC_VER
|
||||
@ -36,7 +36,7 @@
|
||||
#endif
|
||||
struct CommandTail{
|
||||
Bit8u count; /* number of bytes returned */
|
||||
char buffer[127]; /* the buffer itself */
|
||||
char buffer[CTBUF]; /* the buffer itself */
|
||||
} GCC_ATTRIBUTE(packed);
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack ()
|
||||
@ -180,6 +180,7 @@ bool DOS_OpenFile(char const * name,Bit8u flags,Bit16u * entry,bool fcb = false)
|
||||
bool DOS_OpenFileExtended(char const * name, Bit16u flags, Bit16u createAttr, Bit16u action, Bit16u *entry, Bit16u* status);
|
||||
bool DOS_CreateFile(char const * name,Bit16u attributes,Bit16u * entry, bool fcb = false);
|
||||
bool DOS_UnlinkFile(char const * const name);
|
||||
bool DOS_GetSFNPath(char const * const path, char *SFNpath, bool LFN);
|
||||
bool DOS_FindFirst(char *search,Bit16u attr,bool fcb_findfirst=false);
|
||||
bool DOS_FindNext(void);
|
||||
bool DOS_Canonicalize(char const * const name,char * const big);
|
||||
@ -192,7 +193,7 @@ bool DOS_MakeName(char const * const name,char * const fullname,Bit8u * drive);
|
||||
Bit8u DOS_GetDefaultDrive(void);
|
||||
void DOS_SetDefaultDrive(Bit8u drive);
|
||||
bool DOS_SetDrive(Bit8u drive);
|
||||
bool DOS_GetCurrentDir(Bit8u drive,char * const buffer);
|
||||
bool DOS_GetCurrentDir(Bit8u drive,char * const buffer, bool LFN);
|
||||
bool DOS_ChangeDir(char const * const dir);
|
||||
bool DOS_MakeDir(char const * const dir);
|
||||
bool DOS_RemoveDir(char const * const dir);
|
||||
@ -200,6 +201,11 @@ bool DOS_Rename(char const * const oldname,char const * const newname);
|
||||
bool DOS_GetFreeDiskSpace(Bit8u drive,Bit16u * bytes,Bit8u * sectors,Bit16u * clusters,Bit16u * free);
|
||||
bool DOS_GetFileAttr(char const * const name,Bit16u * attr);
|
||||
bool DOS_SetFileAttr(char const * const name,Bit16u attr);
|
||||
bool DOS_GetFileAttrEx(char const* const name, struct stat *status, Bit8u hdrive=-1);
|
||||
unsigned long DOS_GetCompressedFileSize(char const* const name);
|
||||
#if defined (WIN32)
|
||||
HANDLE DOS_CreateOpenFile(char const* const name);
|
||||
#endif
|
||||
|
||||
/* IOCTL Stuff */
|
||||
bool DOS_IOCTL(void);
|
||||
@ -285,25 +291,25 @@ static INLINE Bit16u DOS_PackDate(Bit16u year,Bit16u mon,Bit16u day) {
|
||||
#define fopen64 fopen
|
||||
#define ftello64 ftell
|
||||
#define fseeko64 fseek
|
||||
#define fseek_ofs_t off_t
|
||||
#define fseek_ofs_t off_t
|
||||
#elif defined (__HAIKU__)
|
||||
#define fopen64 fopen
|
||||
#define ftello64 ftello
|
||||
#define fseeko64 fseeko
|
||||
#define fseek_ofs_t off_t
|
||||
#define fseek_ofs_t off_t
|
||||
#elif defined (_MSC_VER)
|
||||
#define fopen64 fopen
|
||||
#if (_MSC_VER >= 1400)
|
||||
#define ftello64 _ftelli64
|
||||
#define fseeko64 _fseeki64
|
||||
#define fseek_ofs_t __int64
|
||||
#define fseek_ofs_t __int64
|
||||
#else
|
||||
#define ftello64 ftell
|
||||
#define fseeko64 fseek
|
||||
#define fseek_ofs_t long
|
||||
#define fseek_ofs_t long
|
||||
#endif
|
||||
#else
|
||||
#define fseek_ofs_t long
|
||||
#define fseek_ofs_t long
|
||||
#endif
|
||||
|
||||
/* Dos Error Codes */
|
||||
@ -387,7 +393,9 @@ public:
|
||||
RealPt GetInt22 (void) { return sGet(sPSP,int_22); };
|
||||
void SetFCB1 (RealPt src);
|
||||
void SetFCB2 (RealPt src);
|
||||
void SetCommandTail (RealPt src);
|
||||
void SetCommandTail (RealPt src);
|
||||
void StoreCommandTail (void);
|
||||
void RestoreCommandTail (void);
|
||||
bool SetNumFiles (Bit16u fileNum);
|
||||
Bit16u FindEntryByHandle (Bit8u handle);
|
||||
|
||||
@ -542,12 +550,14 @@ class DOS_DTA:public MemStruct{
|
||||
public:
|
||||
DOS_DTA(RealPt addr) { SetPt(addr); }
|
||||
|
||||
int GetFindData(int fmt,char * finddata);
|
||||
|
||||
void SetupSearch(Bit8u _sdrive,Bit8u _sattr,char * pattern);
|
||||
void SetResult(const char * _name,Bit32u _size,Bit16u _date,Bit16u _time,Bit8u _attr);
|
||||
void SetResult(const char * _name,const char * _lname,Bit32u _size,Bit16u _date,Bit16u _time,Bit8u _attr);
|
||||
|
||||
Bit8u GetSearchDrive(void);
|
||||
void GetSearchParams(Bit8u & attr,char * pattern);
|
||||
void GetResult(char * _name,Bit32u & _size,Bit16u & _date,Bit16u & _time,Bit8u & _attr);
|
||||
void GetSearchParams(Bit8u & _sattr,char * _spattern,bool lfn);
|
||||
void GetResult(char * _name,char * _lname,Bit32u & _size,Bit16u & _date,Bit16u & _time,Bit8u & _attr);
|
||||
|
||||
void SetDirID(Bit16u entry) { sSave(sDTA,dirID,entry); };
|
||||
void SetDirIDCluster(Bit16u entry) { sSave(sDTA,dirCluster,entry); };
|
||||
@ -560,8 +570,8 @@ private:
|
||||
#endif
|
||||
struct sDTA {
|
||||
Bit8u sdrive; /* The Drive the search is taking place */
|
||||
Bit8u sname[8]; /* The Search pattern for the filename */
|
||||
Bit8u sext[3]; /* The Search pattern for the extenstion */
|
||||
Bit8u spname[8]; /* The Search pattern for the filename */
|
||||
Bit8u spext[3]; /* The Search pattern for the extension */
|
||||
Bit8u sattr; /* The Attributes that need to be found */
|
||||
Bit16u dirID; /* custom: dir-search ID for multiple searches at the same time */
|
||||
Bit16u dirCluster; /* custom (drive_fat only): cluster number for multiple searches at the same time */
|
||||
|
@ -33,12 +33,14 @@
|
||||
#ifndef DOSBOX_MEM_H
|
||||
#include "mem.h"
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
|
||||
#define DOS_NAMELENGTH 12
|
||||
#define DOS_NAMELENGTH_ASCII (DOS_NAMELENGTH+1)
|
||||
#define LFN_NAMELENGTH 255
|
||||
#define DOS_FCBNAME 15
|
||||
#define DOS_DIRDEPTH 8
|
||||
#define DOS_PATHLENGTH 80
|
||||
#define DOS_PATHLENGTH 255
|
||||
#define DOS_TEMPSIZE 1024
|
||||
|
||||
enum {
|
||||
@ -176,14 +178,14 @@ public:
|
||||
void SetBaseDir (const char* baseDir, DOS_Drive *drive);
|
||||
void SetDirSort (TDirSort sort) { sortDirType = sort; };
|
||||
bool OpenDir (const char* path, Bit16u& id);
|
||||
bool ReadDir (Bit16u id, char* &result);
|
||||
bool ReadDir (Bit16u id, char* &result, char * &lresult);
|
||||
|
||||
void ExpandName (char* path);
|
||||
char* GetExpandName (const char* path);
|
||||
bool GetShortName (const char* fullname, char* shortname);
|
||||
|
||||
bool FindFirst (char* path, Bit16u& id);
|
||||
bool FindNext (Bit16u id, char* &result);
|
||||
bool FindNext (Bit16u id, char* &result, char* &lresult);
|
||||
|
||||
void CacheOut (const char* path, bool ignoreLastDir = false);
|
||||
void AddEntry (const char* path, bool checkExists = false);
|
||||
@ -227,12 +229,12 @@ private:
|
||||
void CreateShortName (CFileInfo* curDir, CFileInfo* info);
|
||||
Bitu CreateShortNameID (CFileInfo* curDir, const char* name);
|
||||
int CompareShortname (const char* compareName, const char* shortName);
|
||||
bool SetResult (CFileInfo* dir, char * &result, Bitu entryNr);
|
||||
bool SetResult (CFileInfo* dir, char * &result, char * &lresult, Bitu entryNr);
|
||||
bool IsCachedIn (CFileInfo* curDir);
|
||||
CFileInfo* FindDirInfo (const char* path, char* expandedPath);
|
||||
bool RemoveSpaces (char* str);
|
||||
bool OpenDir (CFileInfo* dir, const char* expand, Bit16u& id);
|
||||
void CreateEntry (CFileInfo* dir, const char* name, bool is_directory);
|
||||
void CreateEntry (CFileInfo* dir, const char* name, const char* sname, bool is_directory);
|
||||
void CopyEntry (CFileInfo* dir, CFileInfo* from);
|
||||
Bit16u GetFreeID (CFileInfo* dir);
|
||||
void Clear (void);
|
||||
@ -270,6 +272,11 @@ public:
|
||||
virtual bool FindFirst(const char * _dir,DOS_DTA & dta,bool fcb_findfirst=false)=0;
|
||||
virtual bool FindNext(DOS_DTA & dta)=0;
|
||||
virtual bool GetFileAttr(const char * name,Bit16u * attr)=0;
|
||||
virtual bool GetFileAttrEx(char* name, struct stat *status)=0;
|
||||
virtual unsigned long GetCompressedSize(char* name)=0;
|
||||
#if defined (WIN32)
|
||||
virtual HANDLE CreateOpenFile(char const* const name)=0;
|
||||
#endif
|
||||
virtual bool Rename(const char * oldname,const char * newname)=0;
|
||||
virtual bool AllocationInfo(Bit16u * _bytes_sector,Bit8u * _sectors_cluster,Bit16u * _total_clusters,Bit16u * _free_clusters)=0;
|
||||
virtual bool FileExists(const char* name)=0;
|
||||
@ -284,8 +291,8 @@ public:
|
||||
/* these 4 may only be used by DOS_Drive_Cache because they have special calling conventions */
|
||||
virtual void *opendir(const char *dir) { (void)dir; return NULL; };
|
||||
virtual void closedir(void *handle) { (void)handle; };
|
||||
virtual bool read_directory_first(void *handle, char* entry_name, bool& is_directory) { (void)handle; (void)entry_name; (void)is_directory; return false; };
|
||||
virtual bool read_directory_next(void *handle, char* entry_name, bool& is_directory) { (void)handle; (void)entry_name; (void)is_directory; return false; };
|
||||
virtual bool read_directory_first(void *handle, char* entry_name, char* entry_sname, bool& is_directory) { (void)handle; (void)entry_name; (void)is_directory; return false; };
|
||||
virtual bool read_directory_next(void *handle, char* entry_name, char* entry_sname, bool& is_directory) { (void)handle; (void)entry_name; (void)is_directory; return false; };
|
||||
|
||||
virtual const char * GetInfo(void);
|
||||
char * GetBaseDir(void);
|
||||
|
@ -124,7 +124,7 @@ typedef Bitu (LoopHandler)(void);
|
||||
extern Config* control;
|
||||
extern SVGACards svgaCard;
|
||||
extern MachineType machine;
|
||||
extern bool SDLNetInited;
|
||||
extern bool SDLNetInited, uselfn;
|
||||
extern bool mono_cga;
|
||||
extern bool DEPRECATED mainline_compatible_mapping;
|
||||
extern bool DEPRECATED mainline_compatible_bios_mapping;
|
||||
|
@ -44,7 +44,7 @@ char *rtrim(char *str);
|
||||
char *trim(char * str);
|
||||
char * upcase(char * str);
|
||||
char * lowcase(char * str);
|
||||
|
||||
char * StripArg(char *&cmd);
|
||||
bool ScanCMDBool(char * cmd,char const * const check);
|
||||
char * ScanCMDRemain(char * cmd);
|
||||
char * StripWord(char *&line);
|
||||
|
732
src/dos/dos.cpp
732
src/dos/dos.cpp
@ -85,6 +85,7 @@ bool enable_share_exe_fake = true;
|
||||
int dos_initial_hma_free = 34*1024;
|
||||
int dos_sda_size = 0x560;
|
||||
|
||||
bool uselfn;
|
||||
extern bool int15_wait_force_unmask_irq;
|
||||
|
||||
Bit32u dos_hma_allocator = 0; /* physical memory addr */
|
||||
@ -164,7 +165,7 @@ extern unsigned int ENV_KEEPFREE;// = 83;
|
||||
DOS_Block dos;
|
||||
DOS_InfoBlock dos_infoblock;
|
||||
|
||||
extern bool dos_kernel_disabled;
|
||||
extern bool force, dos_kernel_disabled;
|
||||
|
||||
Bit16u DOS_Block::psp() {
|
||||
if (dos_kernel_disabled) {
|
||||
@ -281,6 +282,23 @@ static inline void overhead() {
|
||||
extern bool date_host_forced;
|
||||
|
||||
static Bitu DOS_21Handler(void);
|
||||
void DOS_Int21_7139(char *name1, char *name2);
|
||||
void DOS_Int21_713a(char *name1, char *name2);
|
||||
void DOS_Int21_713b(char *name1, char *name2);
|
||||
void DOS_Int21_7141(char *name1, char *name2);
|
||||
void DOS_Int21_7143(char *name1, char *name2);
|
||||
void DOS_Int21_7147(char *name1, char *name2);
|
||||
void DOS_Int21_714e(char *name1, char *name2);
|
||||
void DOS_Int21_714f(char *name1, char *name2);
|
||||
void DOS_Int21_7156(char *name1, char *name2);
|
||||
void DOS_Int21_7160(char *name1, char *name2);
|
||||
void DOS_Int21_716c(char *name1, char *name2);
|
||||
void DOS_Int21_71a0(char *name1, char *name2);
|
||||
void DOS_Int21_71a1(char *name1, char *name2);
|
||||
void DOS_Int21_71a6(char *name1, char *name2);
|
||||
void DOS_Int21_71a7(char *name1, char *name2);
|
||||
void DOS_Int21_71a8(char* name1, char* name2);
|
||||
void DOS_Int21_71aa(char* name1, char* name2);
|
||||
Bitu DEBUG_EnableDebugger(void);
|
||||
void CALLBACK_RunRealInt_retcsip(Bit8u intnum,Bitu &cs,Bitu &ip);
|
||||
|
||||
@ -414,6 +432,20 @@ bool dos_program_running = false;
|
||||
|
||||
void XMS_DOS_LocalA20EnableIfNotEnabled(void);
|
||||
|
||||
typedef struct {
|
||||
UINT16 size_of_structure;
|
||||
UINT16 structure_version;
|
||||
UINT32 sectors_per_cluster;
|
||||
UINT32 bytes_per_sector;
|
||||
UINT32 available_clusters_on_drive;
|
||||
UINT32 total_clusters_on_drive;
|
||||
UINT32 available_sectors_on_drive;
|
||||
UINT32 total_sectors_on_drive;
|
||||
UINT32 available_allocation_units;
|
||||
UINT32 total_allocation_units;
|
||||
UINT8 reserved[8];
|
||||
} ext_space_info_t;
|
||||
|
||||
#define DOSNAMEBUF 256
|
||||
static Bitu DOS_21Handler(void) {
|
||||
bool unmask_irq0 = false;
|
||||
@ -1193,16 +1225,27 @@ static Bitu DOS_21Handler(void) {
|
||||
diskio_delay(2048);
|
||||
break;
|
||||
case 0x3d: /* OPEN Open existing file */
|
||||
{
|
||||
unmask_irq0 |= disk_io_unmask_irq0;
|
||||
MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF);
|
||||
force = true;
|
||||
Bit8u oldal=reg_al;
|
||||
if (DOS_OpenFile(name1,reg_al,®_ax)) {
|
||||
force = false;
|
||||
CALLBACK_SCF(false);
|
||||
} else {
|
||||
force = false;
|
||||
if (uselfn&&DOS_OpenFile(name1,oldal,®_ax)) {
|
||||
CALLBACK_SCF(false);
|
||||
break;
|
||||
}
|
||||
reg_ax=dos.errorcode;
|
||||
CALLBACK_SCF(true);
|
||||
}
|
||||
diskio_delay(1024);
|
||||
force = false;
|
||||
break;
|
||||
}
|
||||
case 0x3e: /* CLOSE Close file */
|
||||
unmask_irq0 |= disk_io_unmask_irq0;
|
||||
if (DOS_CloseFile(reg_bx)) {
|
||||
@ -1368,7 +1411,7 @@ static Bitu DOS_21Handler(void) {
|
||||
}
|
||||
break;
|
||||
case 0x47: /* CWD Get current directory */
|
||||
if (DOS_GetCurrentDir(reg_dl,name1)) {
|
||||
if (DOS_GetCurrentDir(reg_dl,name1,false)) {
|
||||
MEM_BlockWrite(SegPhys(ds)+reg_si,name1,(Bitu)(strlen(name1)+1));
|
||||
reg_ax=0x0100;
|
||||
CALLBACK_SCF(false);
|
||||
@ -1864,11 +1907,110 @@ static Bitu DOS_21Handler(void) {
|
||||
LOG(LOG_DOSMISC, LOG_ERROR)("DOS:6F ROM functions not implemented");
|
||||
goto default_fallthrough;
|
||||
case 0x71: /* Unknown probably 4dos detection */
|
||||
reg_ax=0x7100;
|
||||
CALLBACK_SCF(true); //Check this! What needs this ? See default case
|
||||
LOG(LOG_DOSMISC,LOG_NORMAL)("DOS:Windows long file name support call %2X",reg_al);
|
||||
if (!uselfn) {
|
||||
reg_ax=0x7100;
|
||||
CALLBACK_SCF(true); //Check this! What needs this ? See default case
|
||||
break;
|
||||
}
|
||||
switch(reg_al) {
|
||||
case 0x39: /* LFN MKDIR */
|
||||
DOS_Int21_7139(name1, name2);
|
||||
break;
|
||||
case 0x3a: /* LFN RMDIR */
|
||||
DOS_Int21_713a(name1, name2);
|
||||
break;
|
||||
case 0x3b: /* LFN CHDIR */
|
||||
DOS_Int21_713b(name1, name2);
|
||||
break;
|
||||
case 0x41: /* LFN UNLINK */
|
||||
DOS_Int21_7141(name1, name2);
|
||||
break;
|
||||
case 0x43: /* LFN ATTR */
|
||||
DOS_Int21_7143(name1, name2);
|
||||
break;
|
||||
case 0x47: /* LFN PWD */
|
||||
DOS_Int21_7147(name1, name2);
|
||||
break;
|
||||
case 0x4e: /* LFN FindFirst */
|
||||
DOS_Int21_714e(name1, name2);
|
||||
break;
|
||||
case 0x4f: /* LFN FindNext */
|
||||
DOS_Int21_714f(name1, name2);
|
||||
break;
|
||||
case 0x56: /* LFN Rename */
|
||||
DOS_Int21_7156(name1, name2);
|
||||
break;
|
||||
case 0x60: /* LFN GetName */
|
||||
DOS_Int21_7160(name1, name2);
|
||||
break;
|
||||
case 0x6c: /* LFN Create */
|
||||
DOS_Int21_716c(name1, name2);
|
||||
break;
|
||||
case 0xa0: /* LFN VolInfo */
|
||||
DOS_Int21_71a0(name1, name2);
|
||||
break;
|
||||
case 0xa1: /* LFN FileClose */
|
||||
DOS_Int21_71a1(name1, name2);
|
||||
break;
|
||||
case 0xa6: /* LFN GetFileInfoByHandle */
|
||||
DOS_Int21_71a6(name1, name2);
|
||||
break;
|
||||
case 0xa7: /* LFN TimeConv */
|
||||
DOS_Int21_71a7(name1, name2);
|
||||
break;
|
||||
case 0xa8: /* LFN GenSFN */
|
||||
DOS_Int21_71a8(name1, name2);
|
||||
break;
|
||||
case 0xaa: /* LFN Subst */
|
||||
DOS_Int21_71aa(name1, name2);
|
||||
break;
|
||||
case 0xa9: /* LFN Server Create */
|
||||
reg_ax=0x7100; // not implemented yet
|
||||
default:
|
||||
reg_ax=0x7100;
|
||||
CALLBACK_SCF(true); //Check this! What needs this ? See default case
|
||||
}
|
||||
break;
|
||||
case 0xE0:
|
||||
case 0x73:
|
||||
if (reg_al==3)
|
||||
{
|
||||
MEM_StrCopy(SegPhys(ds)+reg_dx,name1,reg_cx);
|
||||
if (name1[1]==':'&&name1[2]=='\\')
|
||||
reg_dl=name1[0]-'A'+1;
|
||||
else {
|
||||
reg_ax=0xffff;
|
||||
CALLBACK_SCF(true);
|
||||
break;
|
||||
}
|
||||
Bit16u bytes_per_sector,total_clusters,free_clusters;
|
||||
Bit8u sectors_per_cluster;
|
||||
if (DOS_GetFreeDiskSpace(reg_dl,&bytes_per_sector,§ors_per_cluster,&total_clusters,&free_clusters))
|
||||
{
|
||||
ext_space_info_t *info = new ext_space_info_t;
|
||||
info->size_of_structure = sizeof(ext_space_info_t);
|
||||
info->structure_version = 0;
|
||||
info->sectors_per_cluster = sectors_per_cluster;
|
||||
info->bytes_per_sector = bytes_per_sector;
|
||||
info->available_clusters_on_drive = free_clusters;
|
||||
info->total_clusters_on_drive = total_clusters;
|
||||
info->available_sectors_on_drive = sectors_per_cluster * free_clusters;
|
||||
info->total_sectors_on_drive = sectors_per_cluster * total_clusters;
|
||||
info->available_allocation_units = free_clusters;
|
||||
info->total_allocation_units = total_clusters;
|
||||
MEM_BlockWrite(SegPhys(es)+reg_di,info,sizeof(ext_space_info_t));
|
||||
delete(info);
|
||||
reg_ax=0;
|
||||
CALLBACK_SCF(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
reg_ax=dos.errorcode;
|
||||
CALLBACK_SCF(true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0xE0:
|
||||
case 0xEF: /* Used in Ancient Art Of War CGA */
|
||||
default:
|
||||
default_fallthrough:
|
||||
@ -2236,7 +2378,6 @@ public:
|
||||
else
|
||||
::disk_data_rate = 3500000; /* Probably an average IDE data rate for early 1990s ISA IDE controllers in PIO mode */
|
||||
}
|
||||
|
||||
dos_in_hma = section->Get_bool("dos in hma");
|
||||
dos_sda_size = section->Get_int("dos sda size");
|
||||
log_dev_con = control->opt_log_con || section->Get_bool("log console");
|
||||
@ -2610,6 +2751,7 @@ public:
|
||||
dos.version.major, dos.version.minor);
|
||||
}
|
||||
}
|
||||
uselfn = dos.version.major>6;
|
||||
|
||||
if (IS_PC98_ARCH) {
|
||||
void PC98_InitDefFuncRow(void);
|
||||
@ -2753,3 +2895,581 @@ void DOS_Init() {
|
||||
for (char drv='A';drv <= 'Z';drv++) DOS_EnableDriveMenu(drv);
|
||||
}
|
||||
|
||||
void DOS_Int21_7139(char *name1, char *name2) {
|
||||
MEM_StrCopy(SegPhys(ds)+reg_dx,name1+1,DOSNAMEBUF);
|
||||
*name1='\"';
|
||||
char *p=name1+strlen(name1);
|
||||
while (*p==' '||*p==0) p--;
|
||||
*(p+1)='\"';
|
||||
*(p+2)=0;
|
||||
if (DOS_MakeDir(name1)) {
|
||||
reg_ax=0;
|
||||
CALLBACK_SCF(false);
|
||||
} else {
|
||||
reg_ax=dos.errorcode;
|
||||
CALLBACK_SCF(true);
|
||||
}
|
||||
}
|
||||
|
||||
void DOS_Int21_713a(char *name1, char *name2) {
|
||||
MEM_StrCopy(SegPhys(ds)+reg_dx,name1+1,DOSNAMEBUF);
|
||||
*name1='\"';
|
||||
char *p=name1+strlen(name1);
|
||||
while (*p==' '||*p==0) p--;
|
||||
*(p+1)='\"';
|
||||
*(p+2)=0;
|
||||
if (DOS_RemoveDir(name1)) {
|
||||
reg_ax=0;
|
||||
CALLBACK_SCF(false);
|
||||
} else {
|
||||
reg_ax=dos.errorcode;
|
||||
CALLBACK_SCF(true);
|
||||
LOG(LOG_MISC,LOG_NORMAL)("Remove dir failed on %s with error %X",name1,dos.errorcode);
|
||||
}
|
||||
}
|
||||
|
||||
void DOS_Int21_713b(char *name1, char *name2) {
|
||||
MEM_StrCopy(SegPhys(ds)+reg_dx,name1+1,DOSNAMEBUF);
|
||||
*name1='\"';
|
||||
char *p=name1+strlen(name1);
|
||||
while (*p==' '||*p==0) p--;
|
||||
*(p+1)='\"';
|
||||
*(p+2)=0;
|
||||
if (DOS_ChangeDir(name1)) {
|
||||
reg_ax=0;
|
||||
CALLBACK_SCF(false);
|
||||
} else {
|
||||
reg_ax=dos.errorcode;
|
||||
CALLBACK_SCF(true);
|
||||
}
|
||||
}
|
||||
|
||||
void DOS_Int21_7141(char *name1, char *name2) {
|
||||
MEM_StrCopy(SegPhys(ds)+reg_dx,name1+1,DOSNAMEBUF);
|
||||
*name1='\"';
|
||||
char *p=name1+strlen(name1);
|
||||
while (*p==' '||*p==0) p--;
|
||||
*(p+1)='\"';
|
||||
*(p+2)=0;
|
||||
if (DOS_UnlinkFile(name1)) {
|
||||
reg_ax=0;
|
||||
CALLBACK_SCF(false);
|
||||
} else {
|
||||
reg_ax=dos.errorcode;
|
||||
CALLBACK_SCF(true);
|
||||
}
|
||||
}
|
||||
|
||||
void DOS_Int21_7143(char *name1, char *name2) {
|
||||
MEM_StrCopy(SegPhys(ds)+reg_dx,name1+1,DOSNAMEBUF);
|
||||
*name1='\"';
|
||||
char *p=name1+strlen(name1);
|
||||
while (*p==' '||*p==0) p--;
|
||||
*(p+1)='\"';
|
||||
*(p+2)=0;
|
||||
switch (reg_bl) {
|
||||
case 0x00: /* Get */
|
||||
{
|
||||
Bit16u attr_val=reg_cx;
|
||||
if (DOS_GetFileAttr(name1,&attr_val)) {
|
||||
reg_cx=attr_val;
|
||||
reg_ax=0;
|
||||
CALLBACK_SCF(false);
|
||||
} else {
|
||||
CALLBACK_SCF(true);
|
||||
reg_ax=dos.errorcode;
|
||||
}
|
||||
break;
|
||||
};
|
||||
case 0x01: /* Set */
|
||||
if (DOS_SetFileAttr(name1,reg_cx)) {
|
||||
reg_ax=0;
|
||||
CALLBACK_SCF(false);
|
||||
} else {
|
||||
CALLBACK_SCF(true);
|
||||
reg_ax=dos.errorcode;
|
||||
}
|
||||
break;
|
||||
case 0x02: /* Get compressed file size */
|
||||
{
|
||||
reg_ax=0;
|
||||
reg_dx=0;
|
||||
unsigned long size = DOS_GetCompressedFileSize(name1);
|
||||
if (size >= 0) {
|
||||
#if defined (WIN32)
|
||||
reg_ax = LOWORD(size);
|
||||
reg_dx = HIWORD(size);
|
||||
#endif
|
||||
CALLBACK_SCF(false);
|
||||
} else {
|
||||
CALLBACK_SCF(true);
|
||||
reg_ax=dos.errorcode;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x03:
|
||||
case 0x05:
|
||||
case 0x07:
|
||||
{
|
||||
#if defined (WIN32)
|
||||
HANDLE hFile = DOS_CreateOpenFile(name1);
|
||||
if (hFile != INVALID_HANDLE_VALUE) {
|
||||
time_t clock = time(NULL), ttime;
|
||||
struct tm *t = localtime(&clock);
|
||||
FILETIME time;
|
||||
t->tm_isdst = -1;
|
||||
t->tm_sec = (((int)reg_cx) << 1) & 0x3e;
|
||||
t->tm_min = (((int)reg_cx) >> 5) & 0x3f;
|
||||
t->tm_hour = (((int)reg_cx) >> 11) & 0x1f;
|
||||
t->tm_mday = (int)(reg_di) & 0x1f;
|
||||
t->tm_mon = ((int)(reg_di >> 5) & 0x0f) - 1;
|
||||
t->tm_year = ((int)(reg_di >> 9) & 0x7f) + 80;
|
||||
ttime=mktime(t);
|
||||
LONGLONG ll = Int32x32To64(ttime, 10000000) + 116444736000000000 + (reg_bl==0x07?reg_si*100000:0);
|
||||
time.dwLowDateTime = (DWORD) ll;
|
||||
time.dwHighDateTime = (DWORD) (ll >> 32);
|
||||
if (!SetFileTime(hFile, reg_bl==0x07?&time:NULL,reg_bl==0x05?&time:NULL,reg_bl==0x03?&time:NULL)) {
|
||||
CloseHandle(hFile);
|
||||
CALLBACK_SCF(true);
|
||||
reg_ax=dos.errorcode;
|
||||
break;
|
||||
}
|
||||
CloseHandle(hFile);
|
||||
reg_ax=0;
|
||||
CALLBACK_SCF(false);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
CALLBACK_SCF(true);
|
||||
reg_ax=dos.errorcode;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x04:
|
||||
case 0x06:
|
||||
case 0x08:
|
||||
struct stat status;
|
||||
if (DOS_GetFileAttrEx(name1, &status)) {
|
||||
struct tm * ltime;
|
||||
time_t ttime=reg_bl==0x04?status.st_mtime:reg_bl==0x06?status.st_atime:status.st_ctime;
|
||||
if ((ltime=localtime(&ttime))!=0) {
|
||||
reg_cx=DOS_PackTime((Bit16u)ltime->tm_hour,(Bit16u)ltime->tm_min,(Bit16u)ltime->tm_sec);
|
||||
reg_di=DOS_PackDate((Bit16u)(ltime->tm_year+1900),(Bit16u)(ltime->tm_mon+1),(Bit16u)ltime->tm_mday);
|
||||
}
|
||||
if (reg_bl==0x08)
|
||||
reg_si = 0;
|
||||
reg_ax=0;
|
||||
CALLBACK_SCF(false);
|
||||
} else {
|
||||
CALLBACK_SCF(true);
|
||||
reg_ax=dos.errorcode;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
E_Exit("DOS:Illegal LFN Attr call %2X",reg_bl);
|
||||
}
|
||||
}
|
||||
|
||||
void DOS_Int21_7147(char *name1, char *name2) {
|
||||
DOS_PSP psp(dos.psp());
|
||||
psp.StoreCommandTail();
|
||||
if (DOS_GetCurrentDir(reg_dl,name1,true)) {
|
||||
MEM_BlockWrite(SegPhys(ds)+reg_si,name1,(Bitu)(strlen(name1)+1));
|
||||
psp.RestoreCommandTail();
|
||||
reg_ax=0;
|
||||
CALLBACK_SCF(false);
|
||||
} else {
|
||||
reg_ax=dos.errorcode;
|
||||
CALLBACK_SCF(true);
|
||||
}
|
||||
}
|
||||
|
||||
void DOS_Int21_714e(char *name1, char *name2) {
|
||||
MEM_StrCopy(SegPhys(ds)+reg_dx,name1+1,DOSNAMEBUF);
|
||||
*name1='\"';
|
||||
char *p=name1+strlen(name1);
|
||||
while (*p==' '||*p==0) p--;
|
||||
*(p+1)='\"';
|
||||
*(p+2)=0;
|
||||
if (!DOS_GetSFNPath(name1,name2,false)) {
|
||||
reg_ax=dos.errorcode;
|
||||
CALLBACK_SCF(true);
|
||||
return;
|
||||
}
|
||||
Bit16u entry;
|
||||
Bit8u i,handle=DOS_FILES;
|
||||
for (i=1;i<DOS_FILES;i++) {
|
||||
if (!Files[i]) {
|
||||
handle=i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (handle==DOS_FILES) {
|
||||
reg_ax=DOSERR_TOO_MANY_OPEN_FILES;
|
||||
CALLBACK_SCF(true);
|
||||
return;
|
||||
}
|
||||
bool b=DOS_FindFirst(name2,reg_cx,handle);
|
||||
int error=dos.errorcode;
|
||||
Bit16u attribute = 0;
|
||||
if (!b&&DOS_GetFileAttr(name2, &attribute) && (attribute&DOS_ATTR_DIRECTORY)) {
|
||||
strcat(name2,"\\*.*");
|
||||
b=DOS_FindFirst(name2,reg_cx,handle);
|
||||
error=dos.errorcode;
|
||||
}
|
||||
if (b) {
|
||||
DOS_PSP psp(dos.psp());
|
||||
entry = psp.FindFreeFileEntry();
|
||||
if (entry==0xff) {
|
||||
reg_ax=DOSERR_TOO_MANY_OPEN_FILES;
|
||||
CALLBACK_SCF(true);
|
||||
return;
|
||||
}
|
||||
if (handle>=DOS_DEVICES||!Devices[handle])
|
||||
{
|
||||
int m=0;
|
||||
for (int i=1;i<DOS_DEVICES;i++)
|
||||
if (Devices[i]) m=i;
|
||||
Files[handle]=new DOS_Device(*Devices[m]);
|
||||
}
|
||||
else
|
||||
Files[handle]=new DOS_Device(*Devices[handle]);
|
||||
Files[handle]->AddRef();
|
||||
psp.SetFileHandle(entry,handle);
|
||||
reg_ax=handle;
|
||||
DOS_DTA dta(dos.dta());
|
||||
char finddata[CROSS_LEN];
|
||||
MEM_BlockWrite(SegPhys(es)+reg_di,finddata,dta.GetFindData((int)reg_si,finddata));
|
||||
CALLBACK_SCF(false);
|
||||
} else {
|
||||
reg_ax=dos.errorcode;
|
||||
CALLBACK_SCF(true);
|
||||
}
|
||||
}
|
||||
|
||||
void DOS_Int21_714f(char *name1, char *name2) {
|
||||
Bit8u handle=(Bit8u)reg_bx;
|
||||
if (!handle || handle>=DOS_FILES || !Files[handle]) {
|
||||
reg_ax=DOSERR_INVALID_HANDLE;
|
||||
CALLBACK_SCF(true);
|
||||
return;
|
||||
}
|
||||
if (DOS_FindNext()) {
|
||||
DOS_DTA dta(dos.dta());
|
||||
char finddata[CROSS_LEN];
|
||||
MEM_BlockWrite(SegPhys(es)+reg_di,finddata,dta.GetFindData((int)reg_si,finddata));
|
||||
CALLBACK_SCF(false);
|
||||
reg_ax=0x4f00+handle;
|
||||
} else {
|
||||
reg_ax=dos.errorcode;
|
||||
CALLBACK_SCF(true);
|
||||
}
|
||||
}
|
||||
|
||||
void DOS_Int21_7156(char *name1, char *name2) {
|
||||
MEM_StrCopy(SegPhys(ds)+reg_dx,name1+1,DOSNAMEBUF);
|
||||
*name1='\"';
|
||||
char *p=name1+strlen(name1);
|
||||
while (*p==' '||*p==0) p--;
|
||||
*(p+1)='\"';
|
||||
*(p+2)=0;
|
||||
MEM_StrCopy(SegPhys(es)+reg_di,name2+1,DOSNAMEBUF);
|
||||
*name2='\"';
|
||||
p=name2+strlen(name2);
|
||||
while (*p==' '||*p==0) p--;
|
||||
*(p+1)='\"';
|
||||
*(p+2)=0;
|
||||
if (DOS_Rename(name1,name2)) {
|
||||
reg_ax=0;
|
||||
CALLBACK_SCF(false);
|
||||
} else {
|
||||
reg_ax=dos.errorcode;
|
||||
CALLBACK_SCF(true);
|
||||
}
|
||||
}
|
||||
void DOS_Int21_7160(char *name1, char *name2) {
|
||||
MEM_StrCopy(SegPhys(ds)+reg_si,name1+1,DOSNAMEBUF);
|
||||
*name1='\"';
|
||||
char *p=name1+strlen(name1);
|
||||
while (*p==' '||*p==0) p--;
|
||||
*(p+1)='\"';
|
||||
*(p+2)=0;
|
||||
if (DOS_Canonicalize(name1,name2)) {
|
||||
strcpy(name1,"\"");
|
||||
strcat(name1,name2);
|
||||
strcat(name1,"\"");
|
||||
switch(reg_cl) {
|
||||
case 0: // Canonoical path name
|
||||
strcpy(name2,name1);
|
||||
MEM_BlockWrite(SegPhys(es)+reg_di,name2,(Bitu)(strlen(name2)+1));
|
||||
reg_ax=0;
|
||||
CALLBACK_SCF(false);
|
||||
break;
|
||||
case 1: // SFN path name
|
||||
if (DOS_GetSFNPath(name1,name2,false)) {
|
||||
MEM_BlockWrite(SegPhys(es)+reg_di,name2,(Bitu)(strlen(name2)+1));
|
||||
reg_ax=0;
|
||||
CALLBACK_SCF(false);
|
||||
} else {
|
||||
reg_ax=2;
|
||||
CALLBACK_SCF(true);
|
||||
}
|
||||
break;
|
||||
case 2: // LFN path name
|
||||
if (DOS_GetSFNPath(name1,name2,true)) {
|
||||
MEM_BlockWrite(SegPhys(es)+reg_di,name2,(Bitu)(strlen(name2)+1));
|
||||
reg_ax=0;
|
||||
CALLBACK_SCF(false);
|
||||
} else {
|
||||
reg_ax=2;
|
||||
CALLBACK_SCF(true);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
E_Exit("DOS:Illegal LFN GetName call %2X",reg_cl);
|
||||
}
|
||||
} else {
|
||||
reg_ax=dos.errorcode;
|
||||
CALLBACK_SCF(true);
|
||||
}
|
||||
}
|
||||
|
||||
void DOS_Int21_716c(char *name1, char *name2) {
|
||||
MEM_StrCopy(SegPhys(ds)+reg_si,name1+1,DOSNAMEBUF);
|
||||
*name1='\"';
|
||||
char *p=name1+strlen(name1);
|
||||
while (*p==' '||*p==0) p--;
|
||||
*(p+1)='\"';
|
||||
*(p+2)=0;
|
||||
if (DOS_OpenFileExtended(name1,reg_bx,reg_cx,reg_dx,®_ax,®_cx)) {
|
||||
CALLBACK_SCF(false);
|
||||
} else {
|
||||
reg_ax=dos.errorcode;
|
||||
CALLBACK_SCF(true);
|
||||
}
|
||||
}
|
||||
|
||||
void DOS_Int21_71a0(char *name1, char *name2) {
|
||||
MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF);
|
||||
if (DOS_Canonicalize(name1,name2)) {
|
||||
if (reg_cx > 3)
|
||||
MEM_BlockWrite(SegPhys(es)+reg_di,"FAT",4);
|
||||
reg_ax=0;
|
||||
reg_bx=0x4006;
|
||||
reg_cx=0xff;
|
||||
reg_dx=0x104;
|
||||
CALLBACK_SCF(false);
|
||||
} else {
|
||||
reg_ax=dos.errorcode;
|
||||
CALLBACK_SCF(true);
|
||||
}
|
||||
}
|
||||
|
||||
void DOS_Int21_71a1(char *name1, char *name2) {
|
||||
Bit8u handle=(Bit8u)reg_bx;
|
||||
if (!handle || handle>=DOS_FILES || !Files[handle]) {
|
||||
reg_ax=DOSERR_INVALID_HANDLE;
|
||||
CALLBACK_SCF(true);
|
||||
return;
|
||||
}
|
||||
DOS_PSP psp(dos.psp());
|
||||
Bit16u entry=psp.FindEntryByHandle(handle);
|
||||
if (entry>0&&entry!=0xff) psp.SetFileHandle(entry,0xff);
|
||||
if (entry>0&&Files[handle]->RemoveRef()<=0) {
|
||||
delete Files[handle];
|
||||
Files[handle]=0;
|
||||
}
|
||||
reg_ax=0;
|
||||
CALLBACK_SCF(false);
|
||||
}
|
||||
|
||||
void DOS_Int21_71a6(char *name1, char *name2) {
|
||||
char buf[64];
|
||||
unsigned long serial_number=0,st=0,cdate,ctime,adate,atime,mdate,mtime;
|
||||
Bit8u entry=(Bit8u)reg_bx, handle;
|
||||
if (entry>=DOS_FILES) {
|
||||
reg_ax=DOSERR_INVALID_HANDLE;
|
||||
CALLBACK_SCF(true);
|
||||
return;
|
||||
}
|
||||
DOS_PSP psp(dos.psp());
|
||||
for (int i=0;i<=DOS_FILES;i++)
|
||||
if (Files[i] && psp.FindEntryByHandle(i)==entry)
|
||||
handle=i;
|
||||
if (handle < DOS_FILES && Files[handle] && Files[handle]->name!=NULL) {
|
||||
char volume[] = "A:\\";
|
||||
volume[0]+=Files[handle]->GetDrive();
|
||||
#if defined (WIN32)
|
||||
GetVolumeInformation(volume, NULL, 0, &serial_number, NULL, NULL, NULL, 0);
|
||||
#endif
|
||||
struct stat status;
|
||||
if (DOS_GetFileAttrEx(Files[handle]->name, &status, Files[handle]->GetDrive())) {
|
||||
time_t ttime;
|
||||
struct tm * ltime;
|
||||
ttime=status.st_ctime;
|
||||
if ((ltime=localtime(&ttime))!=0) {
|
||||
ctime=DOS_PackTime((Bit16u)ltime->tm_hour,(Bit16u)ltime->tm_min,(Bit16u)ltime->tm_sec);
|
||||
cdate=DOS_PackDate((Bit16u)(ltime->tm_year+1900),(Bit16u)(ltime->tm_mon+1),(Bit16u)ltime->tm_mday);
|
||||
}
|
||||
ttime=status.st_atime;
|
||||
if ((ltime=localtime(&ttime))!=0) {
|
||||
atime=DOS_PackTime((Bit16u)ltime->tm_hour,(Bit16u)ltime->tm_min,(Bit16u)ltime->tm_sec);
|
||||
adate=DOS_PackDate((Bit16u)(ltime->tm_year+1900),(Bit16u)(ltime->tm_mon+1),(Bit16u)ltime->tm_mday);
|
||||
}
|
||||
ttime=status.st_mtime;
|
||||
if ((ltime=localtime(&ttime))!=0) {
|
||||
mtime=DOS_PackTime((Bit16u)ltime->tm_hour,(Bit16u)ltime->tm_min,(Bit16u)ltime->tm_sec);
|
||||
mdate=DOS_PackDate((Bit16u)(ltime->tm_year+1900),(Bit16u)(ltime->tm_mon+1),(Bit16u)ltime->tm_mday);
|
||||
}
|
||||
sprintf(buf,"%-4s%-4s%-4s%-4s%-4s%-4s%-4s%-4s%-4s%-4s%-4s%-4s%-4s",&st,&ctime,&cdate,&atime,&adate,&mtime,&mdate,&serial_number,&st,&st,&st,&st,&handle);
|
||||
for (int i=32;i<36;i++) buf[i]=0;
|
||||
buf[36]=(char)((Bit32u)status.st_size%256);
|
||||
buf[37]=(char)(((Bit32u)status.st_size%65536)/256);
|
||||
buf[38]=(char)(((Bit32u)status.st_size%16777216)/65536);
|
||||
buf[39]=(char)((Bit32u)status.st_size/16777216);
|
||||
buf[40]=(char)status.st_nlink;
|
||||
for (int i=41;i<47;i++) buf[i]=0;
|
||||
buf[52]=0;
|
||||
MEM_BlockWrite(SegPhys(ds)+reg_dx,buf,53);
|
||||
reg_ax=0;
|
||||
CALLBACK_SCF(false);
|
||||
} else {
|
||||
reg_ax=dos.errorcode;
|
||||
CALLBACK_SCF(true);
|
||||
}
|
||||
} else {
|
||||
reg_ax=dos.errorcode;
|
||||
CALLBACK_SCF(true);
|
||||
}
|
||||
}
|
||||
|
||||
void DOS_Int21_71a7(char *name1, char *name2) {
|
||||
switch (reg_bl) {
|
||||
case 0x00:
|
||||
reg_cl=mem_readb(SegPhys(ds)+reg_si); //not yet a proper implementation,
|
||||
reg_ch=mem_readb(SegPhys(ds)+reg_si+1); //but MS-DOS 7 and 4DOS DIR should
|
||||
reg_dl=mem_readb(SegPhys(ds)+reg_si+4); //show date/time correctly now
|
||||
reg_dh=mem_readb(SegPhys(ds)+reg_si+5);
|
||||
reg_bh=0;
|
||||
reg_ax=0;
|
||||
CALLBACK_SCF(false);
|
||||
break;
|
||||
case 0x01:
|
||||
mem_writeb(SegPhys(es)+reg_di,reg_cl);
|
||||
mem_writeb(SegPhys(es)+reg_di+1,reg_ch);
|
||||
mem_writeb(SegPhys(es)+reg_di+4,reg_dl);
|
||||
mem_writeb(SegPhys(es)+reg_di+5,reg_dh);
|
||||
reg_ax=0;
|
||||
CALLBACK_SCF(false);
|
||||
break;
|
||||
default:
|
||||
E_Exit("DOS:Illegal LFN TimeConv call %2X",reg_bl);
|
||||
}
|
||||
}
|
||||
|
||||
void DOS_Int21_71a8(char* name1, char* name2) {
|
||||
if (reg_dh == 0 || reg_dh == 1) {
|
||||
MEM_StrCopy(SegPhys(ds)+reg_si,name1,DOSNAMEBUF);
|
||||
int i,j=0;
|
||||
char c[13],*s=strrchr(name1,'.');
|
||||
for (i=0;i<8;j++) {
|
||||
if (name1[j] == 0 || s-name1 <= j) break;
|
||||
if (name1[j] == '.') continue;
|
||||
sprintf(c,"%s%c",c,toupper(name1[j]));
|
||||
i++;
|
||||
}
|
||||
if (s != NULL) {
|
||||
s++;
|
||||
if (s != 0 && reg_dh == 1) strcat(c,".");
|
||||
for (i=0;i<3;i++) {
|
||||
if (*(s+i) == 0) break;
|
||||
sprintf(c,"%s%c",c,toupper(*(s+i)));
|
||||
}
|
||||
}
|
||||
MEM_BlockWrite(SegPhys(es)+reg_di,c,strlen(c)+1);
|
||||
reg_ax=0;
|
||||
CALLBACK_SCF(false);
|
||||
} else {
|
||||
reg_ax=1;
|
||||
CALLBACK_SCF(true);
|
||||
}
|
||||
}
|
||||
|
||||
void DOS_Int21_71aa(char* name1, char* name2) {
|
||||
if (reg_bh>-1 && reg_bh<3 && (reg_bl<1 || reg_bl>26)) {
|
||||
reg_ax = DOSERR_INVALID_DRIVE;
|
||||
CALLBACK_SCF(true);
|
||||
return;
|
||||
}
|
||||
switch (reg_bh) {
|
||||
case 0:
|
||||
{
|
||||
Bit8u drive=reg_bl-1;
|
||||
if (drive==DOS_GetDefaultDrive() || Drives[drive] || drive==25) {
|
||||
reg_ax = DOSERR_INVALID_DRIVE;
|
||||
CALLBACK_SCF(true);
|
||||
} else {
|
||||
MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF);
|
||||
char mountstring[DOS_PATHLENGTH+CROSS_LEN+20];
|
||||
strcpy(mountstring,"MOUNT ");
|
||||
char temp_str[3] = { 0,0,0 };
|
||||
temp_str[0]=(char)('A'+reg_bl-1);
|
||||
temp_str[1]=' ';
|
||||
strcat(mountstring,temp_str);
|
||||
strcat(mountstring,name1);
|
||||
strcat(mountstring," >nul");
|
||||
DOS_Shell temp;
|
||||
temp.ParseLine(mountstring);
|
||||
if (Drives[drive]) {
|
||||
reg_ax=0;
|
||||
CALLBACK_SCF(false);
|
||||
} else {
|
||||
reg_ax=DOSERR_PATH_NOT_FOUND;
|
||||
CALLBACK_SCF(true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
Bit8u drive=reg_bl-1;
|
||||
if (drive==DOS_GetDefaultDrive() || !Drives[drive] || drive==25) {
|
||||
reg_ax = DOSERR_INVALID_DRIVE;
|
||||
CALLBACK_SCF(true);
|
||||
} else {
|
||||
char mountstring[DOS_PATHLENGTH+CROSS_LEN+20];
|
||||
strcpy(mountstring,"MOUNT -u ");
|
||||
char temp_str[2] = { 0,0 };
|
||||
temp_str[0]=(char)('A'+reg_bl-1);
|
||||
strcat(mountstring,temp_str);
|
||||
strcat(mountstring," >nul");
|
||||
DOS_Shell temp;
|
||||
temp.ParseLine(mountstring);
|
||||
if (!Drives[drive]) {
|
||||
reg_ax =0;
|
||||
CALLBACK_SCF(false);
|
||||
} else {
|
||||
reg_ax=5;
|
||||
CALLBACK_SCF(true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
Bit8u drive=reg_bl>0?reg_bl-1:DOS_GetDefaultDrive();
|
||||
if (Drives[drive]&&!strncmp(Drives[drive]->GetInfo(),"local directory ",16)) {
|
||||
strcpy(name1,Drives[drive]->GetInfo()+16);
|
||||
MEM_BlockWrite(SegPhys(ds)+reg_dx,name1,(Bitu)(strlen(name1)+1));
|
||||
reg_ax=0;
|
||||
CALLBACK_SCF(false);
|
||||
} else {
|
||||
reg_ax=3;
|
||||
CALLBACK_SCF(true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
E_Exit("DOS:Illegal LFN Subst call %2X",reg_bl);
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,18 @@
|
||||
#include "dos_inc.h"
|
||||
#include "support.h"
|
||||
|
||||
char sname[LFN_NAMELENGTH+1],storect[CTBUF];
|
||||
struct finddata {
|
||||
Bit8u attr;
|
||||
Bit8u fres1[19];
|
||||
Bit32u mtime;
|
||||
Bit32u mdate;
|
||||
Bit32u hsize;
|
||||
Bit32u size;
|
||||
Bit8u fres2[8];
|
||||
char lname[260];
|
||||
char sname[14];
|
||||
} fd;
|
||||
|
||||
void DOS_ParamBlock::Clear(void) {
|
||||
memset(&exec,0,sizeof(exec));
|
||||
@ -331,13 +343,23 @@ void DOS_PSP::RestoreVectors(void) {
|
||||
|
||||
void DOS_PSP::SetCommandTail(RealPt src) {
|
||||
if (src) { // valid source
|
||||
MEM_BlockCopy(pt+offsetof(sPSP,cmdtail),Real2Phys(src),128);
|
||||
MEM_BlockCopy(pt+offsetof(sPSP,cmdtail),Real2Phys(src),CTBUF+1);
|
||||
} else { // empty
|
||||
sSave(sPSP,cmdtail.count,0x00);
|
||||
mem_writeb(pt+offsetof(sPSP,cmdtail.buffer),0x0d);
|
||||
}
|
||||
}
|
||||
|
||||
void DOS_PSP::StoreCommandTail() {
|
||||
int len=mem_strlen(pt+offsetof(sPSP,cmdtail.buffer));
|
||||
MEM_StrCopy(pt+offsetof(sPSP,cmdtail.buffer),storect,len>CTBUF?CTBUF:len);
|
||||
}
|
||||
|
||||
void DOS_PSP::RestoreCommandTail() {
|
||||
mem_writeb(pt+offsetof(sPSP,cmdtail.count),strlen(storect)>0?strlen(storect)-1:0);
|
||||
MEM_BlockWrite(pt+offsetof(sPSP,cmdtail.buffer),storect,strlen(storect));
|
||||
}
|
||||
|
||||
void DOS_PSP::SetFCB1(RealPt src) {
|
||||
if (src) MEM_BlockCopy(PhysMake(seg,offsetof(sPSP,fcb1)),Real2Phys(src),16);
|
||||
}
|
||||
@ -370,52 +392,87 @@ bool DOS_PSP::SetNumFiles(Bit16u fileNum) {
|
||||
void DOS_DTA::SetupSearch(Bit8u _sdrive,Bit8u _sattr,char * pattern) {
|
||||
sSave(sDTA,sdrive,_sdrive);
|
||||
sSave(sDTA,sattr,_sattr);
|
||||
/* Fill with spaces */
|
||||
Bit8u i;
|
||||
for (i=0;i<11;i++) mem_writeb(pt+offsetof(sDTA,sname)+i,' ');
|
||||
char * find_ext;
|
||||
find_ext=strchr(pattern,'.');
|
||||
if (find_ext) {
|
||||
Bitu size=(Bitu)(find_ext-pattern);
|
||||
|
||||
/* Fill with char 0 */
|
||||
int i;
|
||||
for (i=0;i<LFN_NAMELENGTH;i++) {
|
||||
if (pattern[i]==0) break;
|
||||
sname[i]=pattern[i];
|
||||
}
|
||||
while (i<=LFN_NAMELENGTH) sname[i++]=0;
|
||||
for (i=0;i<11;i++) mem_writeb(pt+offsetof(sDTA,spname)+i,0);
|
||||
|
||||
char * find_ext;
|
||||
find_ext=strchr(pattern,'.');
|
||||
if (find_ext) {
|
||||
Bitu size=(Bitu)(find_ext-pattern);
|
||||
if (size>8) size=8;
|
||||
MEM_BlockWrite(pt+offsetof(sDTA,sname),pattern,size);
|
||||
find_ext++;
|
||||
MEM_BlockWrite(pt+offsetof(sDTA,sext),find_ext,(strlen(find_ext)>3) ? 3 : (Bitu)strlen(find_ext));
|
||||
MEM_BlockWrite(pt+offsetof(sDTA,spname),pattern,size);
|
||||
find_ext++;
|
||||
MEM_BlockWrite(pt+offsetof(sDTA,spext),find_ext,(strlen(find_ext)>3) ? 3 : (Bitu)strlen(find_ext));
|
||||
} else {
|
||||
MEM_BlockWrite(pt+offsetof(sDTA,sname),pattern,(strlen(pattern) > 8) ? 8 : (Bitu)strlen(pattern));
|
||||
MEM_BlockWrite(pt+offsetof(sDTA,spname),pattern,(strlen(pattern) > 8) ? 8 : (Bitu)strlen(pattern));
|
||||
}
|
||||
}
|
||||
|
||||
void DOS_DTA::SetResult(const char * _name,Bit32u _size,Bit16u _date,Bit16u _time,Bit8u _attr) {
|
||||
void DOS_DTA::SetResult(const char * _name, const char * _lname, Bit32u _size,Bit16u _date,Bit16u _time,Bit8u _attr) {
|
||||
MEM_BlockWrite(pt+offsetof(sDTA,name),(void *)_name,strlen(_name)+1);
|
||||
sSave(sDTA,size,_size);
|
||||
sSave(sDTA,date,_date);
|
||||
sSave(sDTA,time,_time);
|
||||
sSave(sDTA,attr,_attr);
|
||||
fd.hsize=0;
|
||||
fd.size=_size;
|
||||
fd.mdate=_date;
|
||||
fd.mtime=_time;
|
||||
fd.attr=_attr;
|
||||
strcpy(fd.lname,_lname);
|
||||
strcpy(fd.sname,_name);
|
||||
if (!strcmp(fd.lname,fd.sname)) fd.sname[0]=0;
|
||||
}
|
||||
|
||||
|
||||
void DOS_DTA::GetResult(char * _name,Bit32u & _size,Bit16u & _date,Bit16u & _time,Bit8u & _attr) {
|
||||
void DOS_DTA::GetResult(char * _name, char * _lname,Bit32u & _size,Bit16u & _date,Bit16u & _time,Bit8u & _attr) {
|
||||
MEM_BlockRead(pt+offsetof(sDTA,name),_name,DOS_NAMELENGTH_ASCII);
|
||||
strcpy(_lname,fd.lname);
|
||||
_size=sGet(sDTA,size);
|
||||
_date=(Bit16u)sGet(sDTA,date);
|
||||
_time=(Bit16u)sGet(sDTA,time);
|
||||
_attr=(Bit8u)sGet(sDTA,attr);
|
||||
}
|
||||
|
||||
int DOS_DTA::GetFindData(int fmt, char * fdstr) {
|
||||
if (fmt==1)
|
||||
sprintf(fdstr,"%-1s%-19s%-2s%-2s%-4s%-4s%-4s%-8s%-260s%-14s",&fd.attr,&fd.fres1,&fd.mtime,&fd.mdate,&fd.mtime,&fd.hsize,&fd.size,&fd.fres2,&fd.lname,&fd.sname);
|
||||
else
|
||||
sprintf(fdstr,"%-1s%-19s%-4s%-4s%-4s%-4s%-8s%-260s%-14s",&fd.attr,&fd.fres1,&fd.mtime,&fd.mdate,&fd.hsize,&fd.size,&fd.fres2,&fd.lname,&fd.sname);
|
||||
for (int i=0;i<4;i++) fdstr[28+i]=0;
|
||||
fdstr[32]=(char)fd.size%256;
|
||||
fdstr[33]=(char)((fd.size%65536)/256);
|
||||
fdstr[34]=(char)((fd.size%16777216)/65536);
|
||||
fdstr[35]=(char)(fd.size/16777216);
|
||||
fdstr[44+strlen(fd.lname)]=0;
|
||||
fdstr[304+strlen(fd.sname)]=0;
|
||||
return (sizeof(fd));
|
||||
}
|
||||
|
||||
Bit8u DOS_DTA::GetSearchDrive(void) {
|
||||
return (Bit8u)sGet(sDTA,sdrive);
|
||||
}
|
||||
|
||||
void DOS_DTA::GetSearchParams(Bit8u & attr,char * pattern) {
|
||||
void DOS_DTA::GetSearchParams(Bit8u & attr,char * pattern, bool lfn) {
|
||||
attr=(Bit8u)sGet(sDTA,sattr);
|
||||
char temp[11];
|
||||
MEM_BlockRead(pt+offsetof(sDTA,sname),temp,11);
|
||||
memcpy(pattern,temp,8);
|
||||
pattern[8]='.';
|
||||
memcpy(&pattern[9],&temp[8],3);
|
||||
pattern[12]=0;
|
||||
|
||||
if (lfn) {
|
||||
memcpy(pattern,sname,LFN_NAMELENGTH);
|
||||
pattern[LFN_NAMELENGTH]=0;
|
||||
} else {
|
||||
char temp[11];
|
||||
MEM_BlockRead(pt+offsetof(sDTA,spname),temp,11);
|
||||
for (int i=0;i<13;i++) pattern[i]=0;
|
||||
memcpy(pattern,temp,8);
|
||||
pattern[strlen(pattern)]='.';
|
||||
memcpy(&pattern[strlen(pattern)],&temp[8],3);
|
||||
}
|
||||
}
|
||||
|
||||
DOS_FCB::DOS_FCB(Bit16u seg,Bit16u off,bool allow_extended) {
|
||||
|
@ -46,6 +46,8 @@ extern bool log_fileio;
|
||||
Bitu DOS_FILES = 127;
|
||||
DOS_File ** Files = NULL;
|
||||
DOS_Drive * Drives[DOS_DRIVES] = {NULL};
|
||||
bool force = false;
|
||||
int sdrive;
|
||||
|
||||
bool shiftjis_lead_byte(int c);
|
||||
|
||||
@ -68,12 +70,29 @@ bool DOS_MakeName(char const * const name,char * const fullname,Bit8u * drive) {
|
||||
DOS_SetError(DOSERR_FILE_NOT_FOUND);
|
||||
return false;
|
||||
}
|
||||
const char * name_int = name;
|
||||
char names[LFN_NAMELENGTH];
|
||||
strcpy(names,name);
|
||||
char * name_int = names;
|
||||
if (strlen(names)==14 && name_int[1]==':' && name_int[2]!='\\' && name_int[9]==' ' && name_int[10]=='.') {
|
||||
for (unsigned int i=0;i<strlen(names);i++)
|
||||
if (i<10 && name_int[i]==32) {
|
||||
name_int[i]='.';
|
||||
name_int[i+1]=name_int[11]==32?0:toupper(name_int[11]);
|
||||
name_int[i+2]=name_int[12]==32?0:toupper(name_int[12]);
|
||||
name_int[i+3]=name_int[13]==32?0:toupper(name_int[13]);
|
||||
name_int[i+4]=0;
|
||||
break;
|
||||
} else if (i<10) name_int[i]=toupper(name_int[i]);
|
||||
}
|
||||
char tempdir[DOS_PATHLENGTH];
|
||||
char upname[DOS_PATHLENGTH];
|
||||
Bitu r,w;
|
||||
*drive = DOS_GetDefaultDrive();
|
||||
Bitu r,w, q=0;
|
||||
/* First get the drive */
|
||||
*drive = DOS_GetDefaultDrive();
|
||||
while (name_int[0]=='"') {
|
||||
q++;
|
||||
name_int++;
|
||||
}
|
||||
if (name_int[1]==':') {
|
||||
*drive=(name_int[0] | 0x20)-'a';
|
||||
name_int+=2;
|
||||
@ -85,9 +104,14 @@ bool DOS_MakeName(char const * const name,char * const fullname,Bit8u * drive) {
|
||||
r=0;w=0;
|
||||
while (r<DOS_PATHLENGTH && name_int[r]!=0) {
|
||||
Bit8u c=(Bit8u)name_int[r++];
|
||||
if ((c>='a') && (c<='z')) c-=32;
|
||||
else if (c==' ') continue; /* should be separator */
|
||||
else if (c=='/') c='\\';
|
||||
if (c=='/') c='\\';
|
||||
else if (c=='"') {q++;continue;}
|
||||
else if (uselfn&&!force) {
|
||||
if (c==' ' && q/2*2 == q) continue;
|
||||
} else {
|
||||
if ((c>='a') && (c<='z')) c-=32;
|
||||
else if (c==' ') continue; /* should be separator */
|
||||
}
|
||||
upname[w++]=(char)c;
|
||||
if (IS_PC98_ARCH && shiftjis_lead_byte(c) && r<DOS_PATHLENGTH) {
|
||||
/* The trailing byte is NOT ASCII and SHOULD NOT be converted to uppercase like ASCII */
|
||||
@ -153,22 +177,24 @@ bool DOS_MakeName(char const * const name,char * const fullname,Bit8u * drive) {
|
||||
lastdir=(Bit32u)strlen(fullname);
|
||||
|
||||
if (lastdir!=0) strcat(fullname,"\\");
|
||||
char * ext=strchr(tempdir,'.');
|
||||
if (ext) {
|
||||
if(strchr(ext+1,'.')) {
|
||||
//another dot in the extension =>file not found
|
||||
//Or path not found depending on wether
|
||||
//we are still in dir check stage or file stage
|
||||
if(stop)
|
||||
DOS_SetError(DOSERR_FILE_NOT_FOUND);
|
||||
else
|
||||
DOS_SetError(DOSERR_PATH_NOT_FOUND);
|
||||
return false;
|
||||
}
|
||||
|
||||
ext[4] = 0;
|
||||
if((strlen(tempdir) - strlen(ext)) > 8) memmove(tempdir + 8, ext, 5);
|
||||
} else tempdir[8]=0;
|
||||
if (!uselfn||force) {
|
||||
char * ext=strchr(tempdir,'.');
|
||||
if (ext) {
|
||||
if(strchr(ext+1,'.')) {
|
||||
//another dot in the extension =>file not found
|
||||
//Or path not found depending on wether
|
||||
//we are still in dir check stage or file stage
|
||||
if(stop)
|
||||
DOS_SetError(DOSERR_FILE_NOT_FOUND);
|
||||
else
|
||||
DOS_SetError(DOSERR_PATH_NOT_FOUND);
|
||||
return false;
|
||||
}
|
||||
|
||||
ext[4] = 0;
|
||||
if((strlen(tempdir) - strlen(ext)) > 8) memmove(tempdir + 8, ext, 5);
|
||||
} else tempdir[8]=0;
|
||||
}
|
||||
|
||||
if (strlen(fullname)+strlen(tempdir)>=DOS_PATHLENGTH) {
|
||||
DOS_SetError(DOSERR_PATH_NOT_FOUND);return false;
|
||||
@ -184,14 +210,86 @@ bool DOS_MakeName(char const * const name,char * const fullname,Bit8u * drive) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DOS_GetCurrentDir(Bit8u drive,char * const buffer) {
|
||||
bool DOS_GetSFNPath(char const * const path,char * SFNPath,bool LFN) {
|
||||
char dir_current[DOS_PATHLENGTH + 1], pdir[LFN_NAMELENGTH], *p;
|
||||
Bit8u drive;char fulldir[DOS_PATHLENGTH],LFNPath[CROSS_LEN];
|
||||
char name[DOS_NAMELENGTH_ASCII], lname[LFN_NAMELENGTH];
|
||||
int w=0;
|
||||
DOS_DTA dta(dos.dta());
|
||||
Bit32u size;Bit16u date;Bit16u time;Bit8u attr;
|
||||
if (!DOS_MakeName(path,fulldir,&drive)) return false;
|
||||
sprintf(SFNPath,"%c:\\",drive+'A');
|
||||
strcpy(LFNPath,SFNPath);
|
||||
strcpy(dir_current,Drives[drive]->curdir);
|
||||
Drives[drive]->curdir,"";
|
||||
p = fulldir;
|
||||
if (*p==0) return true;
|
||||
for (char *s = strchr(p,'\\'); s != NULL; s = strchr(p,'\\')) {
|
||||
*s = 0;
|
||||
if (SFNPath[strlen(SFNPath)-1]=='\\')
|
||||
sprintf(pdir,"\"%s%s\"",SFNPath,p);
|
||||
else
|
||||
sprintf(pdir,"\"%s\\%s\"",SFNPath,p);
|
||||
if (!strrchr(p,'*') && !strrchr(p,'?')) {
|
||||
*s = '\\';
|
||||
p = s + 1;
|
||||
if (DOS_FindFirst(pdir,0xffff & DOS_ATTR_DIRECTORY & ~DOS_ATTR_VOLUME,false)) {
|
||||
dta.GetResult(name,lname,size,date,time,attr);
|
||||
strcat(SFNPath,name);
|
||||
strcat(LFNPath,lname);
|
||||
Drives[drive]->curdir,SFNPath+3;
|
||||
strcat(SFNPath,"\\");
|
||||
strcat(LFNPath,"\\");
|
||||
}
|
||||
else {
|
||||
return false;}
|
||||
} else {
|
||||
strcat(SFNPath,p);
|
||||
strcat(LFNPath,p);
|
||||
strcat(SFNPath,"\\");
|
||||
strcat(LFNPath,"\\");
|
||||
*s = '\\';
|
||||
p = s + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (p != 0) {
|
||||
sprintf(pdir,"\"%s%s\"",SFNPath,p);
|
||||
if (!strrchr(p,'*')&&!strrchr(p,'?')&&DOS_FindFirst(pdir,0xffff & ~DOS_ATTR_VOLUME,false)) {
|
||||
dta.GetResult(name,lname,size,date,time,attr);
|
||||
strcat(SFNPath,name);
|
||||
strcat(LFNPath,lname);
|
||||
} else {
|
||||
strcat(SFNPath,p);
|
||||
strcat(LFNPath,p);
|
||||
}
|
||||
}
|
||||
Drives[drive]->curdir,dir_current;
|
||||
if (LFN) strcpy(SFNPath,LFNPath);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DOS_GetCurrentDir(Bit8u drive,char * const buffer, bool LFN) {
|
||||
if (drive==0) drive=DOS_GetDefaultDrive();
|
||||
else drive--;
|
||||
if ((drive>=DOS_DRIVES) || (!Drives[drive])) {
|
||||
DOS_SetError(DOSERR_INVALID_DRIVE);
|
||||
return false;
|
||||
}
|
||||
strcpy(buffer,Drives[drive]->curdir);
|
||||
if (LFN && uselfn) {
|
||||
char cdir[DOS_PATHLENGTH],ldir[DOS_PATHLENGTH];
|
||||
if (strchr(Drives[drive]->curdir,' '))
|
||||
sprintf(cdir,"\"%c:\\%s\"",drive+'A',Drives[drive]->curdir);
|
||||
else
|
||||
sprintf(cdir,"%c:\\%s",drive+'A',Drives[drive]->curdir);
|
||||
if (!DOS_GetSFNPath(cdir,ldir,true))
|
||||
return false;
|
||||
strcpy(buffer,ldir+3);
|
||||
if (DOS_GetSFNPath(cdir,ldir,false))
|
||||
strcpy(Drives[drive]->curdir,ldir+3);
|
||||
} else {
|
||||
strcpy(buffer,Drives[drive]->curdir);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -250,9 +348,10 @@ bool DOS_RemoveDir(char const * const dir) {
|
||||
return false;
|
||||
}
|
||||
/* See if it's current directory */
|
||||
char currdir[DOS_PATHLENGTH]= { 0 };
|
||||
DOS_GetCurrentDir(drive + 1 ,currdir);
|
||||
if(strcmp(currdir,fulldir) == 0) {
|
||||
char currdir[DOS_PATHLENGTH]= { 0 }, lcurrdir[DOS_PATHLENGTH]= { 0 };
|
||||
DOS_GetCurrentDir(drive + 1 ,currdir, false);
|
||||
DOS_GetCurrentDir(drive + 1 ,lcurrdir, true);
|
||||
if(strcasecmp(currdir,fulldir) == 0 || uselfn && strcasecmp(lcurrdir,fulldir) == 0) {
|
||||
DOS_SetError(DOSERR_REMOVE_CURRENT_DIRECTORY);
|
||||
return false;
|
||||
}
|
||||
@ -327,13 +426,14 @@ bool DOS_FindFirst(char * search,Bit16u attr,bool fcb_findfirst) {
|
||||
strcpy(dir,fullsearch);
|
||||
}
|
||||
|
||||
sdrive=drive;
|
||||
dta.SetupSearch(drive,(Bit8u)attr,pattern);
|
||||
|
||||
if(device) {
|
||||
find_last = strrchr(pattern,'.');
|
||||
if(find_last) *find_last = 0;
|
||||
//TODO use current date and time
|
||||
dta.SetResult(pattern,0,0,0,DOS_ATTR_DEVICE);
|
||||
dta.SetResult(pattern,pattern,0,0,0,DOS_ATTR_DEVICE);
|
||||
LOG(LOG_DOSMISC,LOG_WARN)("finding device %s",pattern);
|
||||
return true;
|
||||
}
|
||||
@ -346,6 +446,7 @@ bool DOS_FindFirst(char * search,Bit16u attr,bool fcb_findfirst) {
|
||||
bool DOS_FindNext(void) {
|
||||
DOS_DTA dta(dos.dta());
|
||||
Bit8u i = dta.GetSearchDrive();
|
||||
if(uselfn && i >= DOS_DRIVES || !Drives[i]) i=sdrive;
|
||||
if(i >= DOS_DRIVES || !Drives[i]) {
|
||||
/* Corrupt search. */
|
||||
LOG(LOG_FILES,LOG_ERROR)("Corrupt search!!!!");
|
||||
@ -553,6 +654,7 @@ bool DOS_CreateFile(char const * name,Bit16u attributes,Bit16u * entry,bool fcb)
|
||||
Files[handle]->AddRef();
|
||||
Files[handle]->drive = drive;
|
||||
if (!fcb) psp.SetFileHandle(*entry,handle);
|
||||
Drives[drive]->EmptyCache();
|
||||
return true;
|
||||
} else {
|
||||
if(!PathExists(name)) DOS_SetError(DOSERR_PATH_NOT_FOUND);
|
||||
@ -608,7 +710,7 @@ bool DOS_OpenFile(char const * name,Bit8u flags,Bit16u * entry,bool fcb) {
|
||||
if (device) {
|
||||
Files[handle]=new DOS_Device(*Devices[devnum]);
|
||||
} else {
|
||||
exists=Drives[drive]->FileOpen(&Files[handle],fullname,flags);
|
||||
exists=Drives[drive]->FileOpen(&Files[handle],fullname,flags) || Drives[drive]->FileOpen(&Files[handle],upcase(fullname),flags);
|
||||
if (exists) Files[handle]->SetDrive(drive);
|
||||
}
|
||||
if (exists || device ) {
|
||||
@ -709,6 +811,38 @@ bool DOS_GetFileAttr(char const * const name,Bit16u * attr) {
|
||||
}
|
||||
}
|
||||
|
||||
bool DOS_GetFileAttrEx(char const* const name, struct stat *status, Bit8u hdrive)
|
||||
{
|
||||
char fullname[DOS_PATHLENGTH];
|
||||
Bit8u drive;
|
||||
bool usehdrive=hdrive>=0&&hdrive<DOS_FILES;
|
||||
if (usehdrive)
|
||||
strcpy(fullname,name);
|
||||
else if (!DOS_MakeName(name, fullname, &drive))
|
||||
return false;
|
||||
return Drives[usehdrive?hdrive:drive]->GetFileAttrEx(fullname, status);
|
||||
}
|
||||
|
||||
unsigned long DOS_GetCompressedFileSize(char const* const name)
|
||||
{
|
||||
char fullname[DOS_PATHLENGTH];
|
||||
Bit8u drive;
|
||||
if (!DOS_MakeName(name, fullname, &drive))
|
||||
return false;
|
||||
return Drives[drive]->GetCompressedSize(fullname);
|
||||
}
|
||||
|
||||
#if defined (WIN32)
|
||||
HANDLE DOS_CreateOpenFile(char const* const name)
|
||||
{
|
||||
char fullname[DOS_PATHLENGTH];
|
||||
Bit8u drive;
|
||||
if (!DOS_MakeName(name, fullname, &drive))
|
||||
return INVALID_HANDLE_VALUE;
|
||||
return Drives[drive]->CreateOpenFile(fullname);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool DOS_SetFileAttr(char const * const name,Bit16u /*attr*/)
|
||||
// this function does not change the file attributs
|
||||
// it just does some tests if file is available
|
||||
@ -1030,9 +1164,10 @@ static void DTAExtendName(char * const name,char * const filename,char * const e
|
||||
|
||||
static void SaveFindResult(DOS_FCB & find_fcb) {
|
||||
DOS_DTA find_dta(dos.tables.tempdta);
|
||||
char name[DOS_NAMELENGTH_ASCII];Bit32u size;Bit16u date;Bit16u time;Bit8u attr;Bit8u drive;
|
||||
char name[DOS_NAMELENGTH_ASCII],lname[LFN_NAMELENGTH];
|
||||
Bit32u size;Bit16u date;Bit16u time;Bit8u attr;Bit8u drive;
|
||||
char file_name[9];char ext[4];
|
||||
find_dta.GetResult(name,size,date,time,attr);
|
||||
find_dta.GetResult(name,lname,size,date,time,attr);
|
||||
drive=find_fcb.GetDrive()+1;
|
||||
Bit8u find_attr = DOS_ATTR_ARCHIVE;
|
||||
find_fcb.GetAttr(find_attr); /* Gets search attributes if extended */
|
||||
@ -1078,9 +1213,9 @@ bool DOS_FCBOpen(Bit16u seg,Bit16u offset) {
|
||||
if (!DOS_FCBFindFirst(seg,offset)) return false;
|
||||
DOS_DTA find_dta(dos.tables.tempdta);
|
||||
DOS_FCB find_fcb(RealSeg(dos.tables.tempdta),RealOff(dos.tables.tempdta));
|
||||
char name[DOS_NAMELENGTH_ASCII],file_name[9],ext[4];
|
||||
char name[DOS_NAMELENGTH_ASCII],lname[LFN_NAMELENGTH],file_name[9],ext[4];
|
||||
Bit32u size;Bit16u date,time;Bit8u attr;
|
||||
find_dta.GetResult(name,size,date,time,attr);
|
||||
find_dta.GetResult(name,lname,size,date,time,attr);
|
||||
DTAExtendName(name,file_name,ext);
|
||||
find_fcb.SetName(fcb.GetDrive()+1,file_name,ext);
|
||||
find_fcb.GetName(shortname);
|
||||
|
@ -93,6 +93,7 @@ extern RealPt DOS_DriveDataListHead; // INT 2Fh AX=0803h DRIVER.SYS drive
|
||||
|
||||
// INT 2F
|
||||
static bool DOS_MultiplexFunctions(void) {
|
||||
char name[256];
|
||||
switch (reg_ax) {
|
||||
case 0x0800: /* DRIVER.SYS function */
|
||||
case 0x0801: /* DRIVER.SYS function */
|
||||
@ -205,6 +206,22 @@ static bool DOS_MultiplexFunctions(void) {
|
||||
|
||||
}
|
||||
return true;
|
||||
case 0x1300:
|
||||
case 0x1302:
|
||||
reg_ax=0;
|
||||
return true;
|
||||
case 0x1612:
|
||||
reg_ax=0;
|
||||
name[0]=1;
|
||||
name[1]=0;
|
||||
MEM_BlockWrite(SegPhys(es)+reg_bx,name,0x20);
|
||||
return true;
|
||||
case 0x1613: /* Get SYSTEM.DAT path */
|
||||
strcpy(name,"C:\\WINDOWS\\SYSTEM.DAT");
|
||||
MEM_BlockWrite(SegPhys(es)+reg_di,name,(Bitu)(strlen(name)+1));
|
||||
reg_ax=0;
|
||||
reg_cx=strlen(name);
|
||||
return true;
|
||||
case 0x1600: /* Windows enhanced mode installation check */
|
||||
// Leave AX as 0x1600, indicating that neither Windows 3.x enhanced mode, Windows/386 2.x
|
||||
// nor Windows 95 are running, nor is XMS version 1 driver installed
|
||||
@ -315,6 +332,70 @@ static bool DOS_MultiplexFunctions(void) {
|
||||
case 0x168f: /* Close awareness crap */
|
||||
/* Removing warning */
|
||||
return true;
|
||||
#ifdef WIN32
|
||||
case 0x1700:
|
||||
reg_al = 1;
|
||||
reg_ah = 1;
|
||||
return true;
|
||||
case 0x1701:
|
||||
reg_ax=OpenClipboard(NULL)?1:0;
|
||||
return true;
|
||||
case 0x1702:
|
||||
reg_ax=0;
|
||||
if (OpenClipboard(NULL))
|
||||
{
|
||||
reg_ax=EmptyClipboard()?1:0;
|
||||
CloseClipboard();
|
||||
}
|
||||
return true;
|
||||
case 0x1703:
|
||||
reg_ax=0;
|
||||
if ((reg_dx==1||reg_dx==7)&&OpenClipboard(NULL))
|
||||
{
|
||||
char *text, *buffer;
|
||||
text = new char[reg_cx];
|
||||
MEM_StrCopy(SegPhys(es)+reg_bx,text,reg_cx);
|
||||
*(text+reg_cx-1)=0;
|
||||
HGLOBAL clipbuffer;
|
||||
EmptyClipboard();
|
||||
clipbuffer = GlobalAlloc(GMEM_DDESHARE, strlen(text)+1);
|
||||
buffer = (char*)GlobalLock(clipbuffer);
|
||||
strcpy(buffer, text);
|
||||
delete[] text;
|
||||
GlobalUnlock(clipbuffer);
|
||||
SetClipboardData(reg_dx==1?CF_TEXT:CF_OEMTEXT,clipbuffer);
|
||||
reg_ax++;
|
||||
CloseClipboard();
|
||||
}
|
||||
return true;
|
||||
case 0x1704:
|
||||
reg_ax=0;
|
||||
if ((reg_dx==1||reg_dx==7)&&OpenClipboard(NULL))
|
||||
{
|
||||
if (HANDLE text = GetClipboardData(reg_dx==1?CF_TEXT:CF_OEMTEXT))
|
||||
{
|
||||
reg_ax=(Bit16u)strlen((char *)text)+1;
|
||||
reg_dx=(Bit16u)((strlen((char *)text)+1)/65536);
|
||||
}
|
||||
CloseClipboard();
|
||||
}
|
||||
return true;
|
||||
case 0x1705:
|
||||
reg_ax=0;
|
||||
if ((reg_dx==1||reg_dx==7)&&OpenClipboard(NULL))
|
||||
{
|
||||
if (HANDLE text = GetClipboardData(reg_dx==1?CF_TEXT:CF_OEMTEXT))
|
||||
{
|
||||
MEM_BlockWrite(SegPhys(es)+reg_bx,text,(Bitu)(strlen((char *)text)+1));
|
||||
reg_ax++;
|
||||
}
|
||||
CloseClipboard();
|
||||
}
|
||||
return true;
|
||||
case 0x1708:
|
||||
reg_ax=CloseClipboard()?1:0;
|
||||
return true;
|
||||
#endif
|
||||
case 0x1a00: /* ANSI.SYS installation check (MS-DOS 4.0 or higher) */
|
||||
if (IS_PC98_ARCH) {
|
||||
/* NTS: PC-98 MS-DOS has ANSI handling directly within the kernel HOWEVER it does NOT
|
||||
@ -397,6 +478,17 @@ static bool DOS_MultiplexFunctions(void) {
|
||||
case 0x4a11: { /* Microsoft DoubleSpace (DBLSPACE.BIN) API */
|
||||
LOG(LOG_MISC,LOG_DEBUG)("Unhandled DBLSPACE call AX=%04x BX=%04x CX=%04x DX=%04x BP=%04x",reg_ax,reg_bx,reg_cx,reg_dx,reg_bp);
|
||||
} return true;
|
||||
case 0x4a16: /* Open bootlog */
|
||||
return true;
|
||||
case 0x4a17: /* Write bootlog */
|
||||
MEM_StrCopy(SegPhys(ds)+reg_dx,name,255);
|
||||
LOG(LOG_DOSMISC,LOG_NORMAL)("BOOTLOG: %s\n",name);
|
||||
return true;
|
||||
case 0x4a33: /* Check MS-DOS Version 7 */
|
||||
if (dos.version.major > 6) {
|
||||
reg_ax=0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -171,7 +171,8 @@ void MenuUnmountDrive(char drv) {
|
||||
class MOUNT : public Program {
|
||||
public:
|
||||
void ListMounts(void) {
|
||||
char name[DOS_NAMELENGTH_ASCII];Bit32u size;Bit16u date;Bit16u time;Bit8u attr;
|
||||
char name[DOS_NAMELENGTH_ASCII],lname[LFN_NAMELENGTH];
|
||||
Bit32u size;Bit16u date;Bit16u time;Bit8u attr;
|
||||
/* Command uses dta so set it to our internal dta */
|
||||
RealPt save_dta = dos.dta();
|
||||
dos.dta(dos.tables.tempdta);
|
||||
@ -187,7 +188,7 @@ public:
|
||||
char root[7] = {(char)('A'+d),':','\\','*','.','*',0};
|
||||
bool ret = DOS_FindFirst(root,DOS_ATTR_VOLUME);
|
||||
if (ret) {
|
||||
dta.GetResult(name,size,date,time,attr);
|
||||
dta.GetResult(name,lname,size,date,time,attr);
|
||||
DOS_FindNext(); //Mark entry as invalid
|
||||
} else name[0] = 0;
|
||||
|
||||
|
@ -133,8 +133,8 @@ void DOS_Drive_Cache::SetBaseDir(const char* baseDir, DOS_Drive *drive) {
|
||||
strcpy(basePath,baseDir);
|
||||
this->drive = drive;
|
||||
if (OpenDir(baseDir,id)) {
|
||||
char* result = 0;
|
||||
ReadDir(id,result);
|
||||
char* result = 0, *lresult = 0;
|
||||
ReadDir(id,result,lresult);
|
||||
}
|
||||
// Get Volume Label
|
||||
#if defined (WIN32) || defined (OS2)
|
||||
@ -214,7 +214,9 @@ void DOS_Drive_Cache::AddEntry(const char* path, bool checkExists) {
|
||||
if (GetLongName(dir,file)>=0) return;
|
||||
}
|
||||
|
||||
CreateEntry(dir,file,false);
|
||||
char sfile[DOS_NAMELENGTH];
|
||||
sfile[0]=0;
|
||||
CreateEntry(dir,file,sfile,false);
|
||||
|
||||
Bits index = GetLongName(dir,file);
|
||||
if (index>=0) {
|
||||
@ -604,9 +606,9 @@ DOS_Drive_Cache::CFileInfo* DOS_Drive_Cache::FindDirInfo(const char* path, char*
|
||||
strcpy(work,basePath);
|
||||
if (OpenDir(curDir,work,id)) {
|
||||
char buffer[CROSS_LEN];
|
||||
char* result = 0;
|
||||
char *result = 0, *lresult = 0;
|
||||
strcpy(buffer,dirPath);
|
||||
ReadDir(id,result);
|
||||
ReadDir(id,result,lresult);
|
||||
strcpy(dirPath,buffer);
|
||||
if (dirSearch[id]) {
|
||||
dirSearch[id]->id = MAX_OPENDIRS;
|
||||
@ -639,9 +641,9 @@ DOS_Drive_Cache::CFileInfo* DOS_Drive_Cache::FindDirInfo(const char* path, char*
|
||||
if (!IsCachedIn(curDir)) {
|
||||
if (OpenDir(curDir,expandedPath,id)) {
|
||||
char buffer[CROSS_LEN];
|
||||
char* result = 0;
|
||||
char *result = 0, *lresult = 0;
|
||||
strcpy(buffer,dirPath);
|
||||
ReadDir(id,result);
|
||||
ReadDir(id,result,lresult);
|
||||
strcpy(dirPath,buffer);
|
||||
if (dirSearch[id]) {
|
||||
dirSearch[id]->id = MAX_OPENDIRS;
|
||||
@ -702,14 +704,15 @@ bool DOS_Drive_Cache::OpenDir(CFileInfo* dir, const char* expand, Bit16u& id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void DOS_Drive_Cache::CreateEntry(CFileInfo* dir, const char* name, bool is_directory) {
|
||||
void DOS_Drive_Cache::CreateEntry(CFileInfo* dir, const char* name, const char* sname, bool is_directory) {
|
||||
CFileInfo* info = new CFileInfo;
|
||||
strcpy(info->orgname, name);
|
||||
strcpy(info->shortname, sname);
|
||||
strcpy(info->orgname, name);
|
||||
info->shortNr = 0;
|
||||
info->isDir = is_directory;
|
||||
|
||||
// Check for long filenames...
|
||||
CreateShortName(dir, info);
|
||||
if (sname[0]==0) CreateShortName(dir, info);
|
||||
|
||||
|
||||
// keep list sorted (so GetLongName works correctly, used by CreateShortName in this routine)
|
||||
@ -740,15 +743,15 @@ void DOS_Drive_Cache::CreateEntry(CFileInfo* dir, const char* name, bool is_dire
|
||||
void DOS_Drive_Cache::CopyEntry(CFileInfo* dir, CFileInfo* from) {
|
||||
CFileInfo* info = new CFileInfo;
|
||||
// just copy things into new fileinfo
|
||||
strcpy(info->orgname, from->orgname);
|
||||
strcpy(info->shortname, from->shortname);
|
||||
strcpy(info->orgname, from->orgname);
|
||||
strcpy(info->shortname, from->shortname);
|
||||
info->shortNr = from->shortNr;
|
||||
info->isDir = from->isDir;
|
||||
|
||||
dir->fileList.push_back(info);
|
||||
}
|
||||
|
||||
bool DOS_Drive_Cache::ReadDir(Bit16u id, char* &result) {
|
||||
bool DOS_Drive_Cache::ReadDir(Bit16u id, char* &result, char * &lresult) {
|
||||
// shouldnt happen...
|
||||
if (id>=MAX_OPENDIRS) return false;
|
||||
|
||||
@ -763,12 +766,12 @@ bool DOS_Drive_Cache::ReadDir(Bit16u id, char* &result) {
|
||||
return false;
|
||||
}
|
||||
// Read complete directory
|
||||
char dir_name[CROSS_LEN];
|
||||
char dir_name[CROSS_LEN], dir_sname[DOS_NAMELENGTH+1];
|
||||
bool is_directory;
|
||||
if (drive->read_directory_first(dirp, dir_name, is_directory)) {
|
||||
CreateEntry(dirSearch[id], dir_name, is_directory);
|
||||
while (drive->read_directory_next(dirp, dir_name, is_directory)) {
|
||||
CreateEntry(dirSearch[id], dir_name, is_directory);
|
||||
if (drive->read_directory_first(dirp, dir_name, dir_sname, is_directory)) {
|
||||
CreateEntry(dirSearch[id], dir_name, dir_sname, is_directory);
|
||||
while (drive->read_directory_next(dirp, dir_name, dir_sname, is_directory)) {
|
||||
CreateEntry(dirSearch[id], dir_name, dir_sname, is_directory);
|
||||
}
|
||||
}
|
||||
|
||||
@ -785,7 +788,7 @@ bool DOS_Drive_Cache::ReadDir(Bit16u id, char* &result) {
|
||||
LOG_DEBUG(buffer);
|
||||
};*/
|
||||
}
|
||||
if (SetResult(dirSearch[id], result, dirSearch[id]->nextEntry)) return true;
|
||||
if (SetResult(dirSearch[id], result, lresult, dirSearch[id]->nextEntry)) return true;
|
||||
if (dirSearch[id]) {
|
||||
dirSearch[id]->id = MAX_OPENDIRS;
|
||||
dirSearch[id] = 0;
|
||||
@ -793,15 +796,19 @@ bool DOS_Drive_Cache::ReadDir(Bit16u id, char* &result) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DOS_Drive_Cache::SetResult(CFileInfo* dir, char* &result, Bitu entryNr)
|
||||
bool DOS_Drive_Cache::SetResult(CFileInfo* dir, char* &result, char* &lresult, Bitu entryNr)
|
||||
{
|
||||
static char res[CROSS_LEN] = { 0 };
|
||||
static char lres[CROSS_LEN] = { 0 };
|
||||
|
||||
result = res;
|
||||
lresult = lres;
|
||||
|
||||
if (entryNr>=dir->fileList.size()) return false;
|
||||
CFileInfo* info = dir->fileList[entryNr];
|
||||
// copy filename, short version
|
||||
strcpy(res,info->shortname);
|
||||
strcpy(lres,info->orgname);
|
||||
// Set to next Entry
|
||||
dir->nextEntry = entryNr+1;
|
||||
return true;
|
||||
@ -860,13 +867,13 @@ bool DOS_Drive_Cache::FindFirst(char* path, Bit16u& id) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DOS_Drive_Cache::FindNext(Bit16u id, char* &result) {
|
||||
bool DOS_Drive_Cache::FindNext(Bit16u id, char* &result, char* &lresult) {
|
||||
// out of range ?
|
||||
if ((id>=MAX_OPENDIRS) || !dirFindFirst[id]) {
|
||||
LOG(LOG_MISC,LOG_ERROR)("DIRCACHE: FindFirst/Next failure : ID out of range: %04X",id);
|
||||
return false;
|
||||
}
|
||||
if (!SetResult(dirFindFirst[id], result, dirFindFirst[id]->nextEntry)) {
|
||||
if (!SetResult(dirFindFirst[id], result, lresult, dirFindFirst[id]->nextEntry)) {
|
||||
// free slot
|
||||
DeleteFileInfo(dirFindFirst[id]); dirFindFirst[id] = 0;
|
||||
return false;
|
||||
|
@ -625,8 +625,9 @@ bool fatDrive::getFileDirEntry(char const * const filename, direntry * useEntry,
|
||||
if(!FindNextInternal(currentClust, *imgDTA, &foundEntry)) break;
|
||||
else {
|
||||
//Found something. See if it's a directory (findfirst always finds regular files)
|
||||
char find_name[DOS_NAMELENGTH_ASCII];Bit16u find_date,find_time;Bit32u find_size;Bit8u find_attr;
|
||||
imgDTA->GetResult(find_name,find_size,find_date,find_time,find_attr);
|
||||
char find_name[DOS_NAMELENGTH_ASCII],lfind_name[LFN_NAMELENGTH];
|
||||
Bit16u find_date,find_time;Bit32u find_size;Bit8u find_attr;
|
||||
imgDTA->GetResult(find_name,lfind_name,find_size,find_date,find_time,find_attr);
|
||||
if(!(find_attr & DOS_ATTR_DIRECTORY)) break;
|
||||
}
|
||||
|
||||
@ -668,8 +669,9 @@ bool fatDrive::getDirClustNum(const char *dir, Bit32u *clustNum, bool parDir) {
|
||||
if(!FindNextInternal(currentClust, *imgDTA, &foundEntry)) {
|
||||
return false;
|
||||
} else {
|
||||
char find_name[DOS_NAMELENGTH_ASCII];Bit16u find_date,find_time;Bit32u find_size;Bit8u find_attr;
|
||||
imgDTA->GetResult(find_name,find_size,find_date,find_time,find_attr);
|
||||
char find_name[DOS_NAMELENGTH_ASCII],lfind_name[LFN_NAMELENGTH];
|
||||
Bit16u find_date,find_time;Bit32u find_size;Bit8u find_attr;
|
||||
imgDTA->GetResult(find_name,lfind_name,find_size,find_date,find_time,find_attr);
|
||||
if(!(find_attr &DOS_ATTR_DIRECTORY)) return false;
|
||||
}
|
||||
currentClust = foundEntry.loFirstClust;
|
||||
@ -1677,15 +1679,16 @@ bool fatDrive::FindNextInternal(Bit32u dirClustNumber, DOS_DTA &dta, direntry *f
|
||||
Bit32u tmpsector;
|
||||
Bit8u attrs;
|
||||
Bit16u dirPos;
|
||||
char srch_pattern[DOS_NAMELENGTH_ASCII];
|
||||
char srch_pattern[CROSS_LEN];
|
||||
char find_name[DOS_NAMELENGTH_ASCII];
|
||||
char lfind_name[LFN_NAMELENGTH+1];
|
||||
char extension[4];
|
||||
|
||||
size_t dirent_per_sector = getSectSize() / sizeof(direntry);
|
||||
assert(dirent_per_sector <= MAX_DIRENTS_PER_SECTOR);
|
||||
assert((dirent_per_sector * sizeof(direntry)) <= SECTOR_SIZE_MAX);
|
||||
|
||||
dta.GetSearchParams(attrs, srch_pattern);
|
||||
dta.GetSearchParams(attrs, srch_pattern,false);
|
||||
dirPos = dta.GetDirID();
|
||||
|
||||
nextfile:
|
||||
@ -1720,20 +1723,25 @@ nextfile:
|
||||
}
|
||||
memset(find_name,0,DOS_NAMELENGTH_ASCII);
|
||||
memset(extension,0,4);
|
||||
memset(lfind_name,0,LFN_NAMELENGTH);
|
||||
memcpy(find_name,§buf[entryoffset].entryname[0],8);
|
||||
memcpy(extension,§buf[entryoffset].entryname[8],3);
|
||||
memcpy(lfind_name,§buf[entryoffset].entryname[0],8);
|
||||
|
||||
if (!(sectbuf[entryoffset].attrib & DOS_ATTR_VOLUME)) {
|
||||
trimString(&find_name[0]);
|
||||
trimString(&extension[0]);
|
||||
trimString(&lfind_name[0]);
|
||||
}
|
||||
|
||||
//if(!(sectbuf[entryoffset].attrib & DOS_ATTR_DIRECTORY))
|
||||
if (extension[0]!=0) {
|
||||
if (!(sectbuf[entryoffset].attrib & DOS_ATTR_VOLUME))
|
||||
if (!(sectbuf[entryoffset].attrib & DOS_ATTR_VOLUME)) {
|
||||
strcat(find_name, ".");
|
||||
|
||||
strcat(lfind_name, ".");
|
||||
}
|
||||
strcat(find_name, extension);
|
||||
strcat(lfind_name, extension);
|
||||
}
|
||||
|
||||
if (sectbuf[entryoffset].attrib & DOS_ATTR_VOLUME)
|
||||
@ -1751,11 +1759,11 @@ nextfile:
|
||||
|
||||
|
||||
/* Compare name to search pattern */
|
||||
if(!WildFileCmp(find_name,srch_pattern)) goto nextfile;
|
||||
if(!WildFileCmp(find_name,srch_pattern)&&!LWildFileCmp(lfind_name,srch_pattern)) goto nextfile;
|
||||
|
||||
//dta.SetResult(find_name, sectbuf[entryoffset].entrysize, sectbuf[entryoffset].crtDate, sectbuf[entryoffset].crtTime, sectbuf[entryoffset].attrib);
|
||||
|
||||
dta.SetResult(find_name, sectbuf[entryoffset].entrysize, sectbuf[entryoffset].modDate, sectbuf[entryoffset].modTime, sectbuf[entryoffset].attrib);
|
||||
dta.SetResult(find_name, lfind_name, sectbuf[entryoffset].entrysize, sectbuf[entryoffset].modDate, sectbuf[entryoffset].modTime, sectbuf[entryoffset].attrib);
|
||||
|
||||
memcpy(foundEntry, §buf[entryoffset], sizeof(direntry));
|
||||
|
||||
@ -1798,6 +1806,21 @@ bool fatDrive::GetFileAttr(const char *name, Bit16u *attr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool fatDrive::GetFileAttrEx(char* name, struct stat *status) {
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned long fatDrive::GetCompressedSize(char* name) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined (WIN32)
|
||||
HANDLE fatDrive::CreateOpenFile(const char* name) {
|
||||
DOS_SetError(1);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool fatDrive::directoryBrowse(Bit32u dirClustNumber, direntry *useEntry, Bit32s entNum, Bit32s start/*=0*/) {
|
||||
direntry sectbuf[MAX_DIRENTS_PER_SECTOR]; /* 16 directory entries per 512 byte sector */
|
||||
Bit32u entryoffset = 0; /* Index offset within sector */
|
||||
|
@ -28,6 +28,8 @@
|
||||
#define FLAGS1 ((iso) ? de.fileFlags : de.timeZone)
|
||||
#define FLAGS2 ((iso) ? de->fileFlags : de->timeZone)
|
||||
|
||||
char fullname[LFN_NAMELENGTH];
|
||||
|
||||
using namespace std;
|
||||
|
||||
class isoFile : public DOS_File {
|
||||
@ -280,16 +282,16 @@ bool isoDrive::FindFirst(const char *dir, DOS_DTA &dta, bool fcb_findfirst) {
|
||||
dta.SetDirID((Bit16u)dirIterator);
|
||||
|
||||
Bit8u attr;
|
||||
char pattern[ISO_MAXPATHNAME];
|
||||
dta.GetSearchParams(attr, pattern);
|
||||
char pattern[CROSS_LEN];
|
||||
dta.GetSearchParams(attr, pattern, true);
|
||||
|
||||
if (attr == DOS_ATTR_VOLUME) {
|
||||
dta.SetResult(discLabel, 0, 0, 0, DOS_ATTR_VOLUME);
|
||||
dta.SetResult(discLabel, discLabel, 0, 0, 0, DOS_ATTR_VOLUME);
|
||||
return true;
|
||||
} else if ((attr & DOS_ATTR_VOLUME) && isRoot && !fcb_findfirst) {
|
||||
if (WildFileCmp(discLabel,pattern)) {
|
||||
// Get Volume Label (DOS_ATTR_VOLUME) and only in basedir and if it matches the searchstring
|
||||
dta.SetResult(discLabel, 0, 0, 0, DOS_ATTR_VOLUME);
|
||||
dta.SetResult(discLabel, discLabel, 0, 0, 0, DOS_ATTR_VOLUME);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -299,8 +301,8 @@ bool isoDrive::FindFirst(const char *dir, DOS_DTA &dta, bool fcb_findfirst) {
|
||||
|
||||
bool isoDrive::FindNext(DOS_DTA &dta) {
|
||||
Bit8u attr;
|
||||
char pattern[DOS_NAMELENGTH_ASCII];
|
||||
dta.GetSearchParams(attr, pattern);
|
||||
char pattern[CROSS_LEN], findName[DOS_NAMELENGTH_ASCII], lfindName[ISO_MAXPATHNAME];
|
||||
dta.GetSearchParams(attr, pattern, true);
|
||||
|
||||
int dirIterator = dta.GetDirID();
|
||||
bool isRoot = dirIterators[dirIterator].root;
|
||||
@ -312,7 +314,12 @@ bool isoDrive::FindNext(DOS_DTA &dta) {
|
||||
else findAttr |= DOS_ATTR_ARCHIVE;
|
||||
if (IS_HIDDEN(FLAGS1)) findAttr |= DOS_ATTR_HIDDEN;
|
||||
|
||||
if (!IS_ASSOC(FLAGS1) && !(isRoot && de.ident[0]=='.') && WildFileCmp((char*)de.ident, pattern)
|
||||
if (strcmp((char*)de.ident,(char*)fullname))
|
||||
strcpy(lfindName,fullname);
|
||||
else
|
||||
GetLongName((char*)de.ident,lfindName);
|
||||
|
||||
if (!IS_ASSOC(FLAGS1) && !(isRoot && de.ident[0]=='.') && (WildFileCmp((char*)de.ident, pattern) || LWildFileCmp(lfindName, pattern))
|
||||
&& !(~attr & findAttr & (DOS_ATTR_DIRECTORY | DOS_ATTR_HIDDEN | DOS_ATTR_SYSTEM))) {
|
||||
|
||||
/* file is okay, setup everything to be copied in DTA Block */
|
||||
@ -325,7 +332,7 @@ bool isoDrive::FindNext(DOS_DTA &dta) {
|
||||
Bit32u findSize = DATA_LENGTH(de);
|
||||
Bit16u findDate = DOS_PackDate(1900 + de.dateYear, de.dateMonth, de.dateDay);
|
||||
Bit16u findTime = DOS_PackTime(de.timeHour, de.timeMin, de.timeSec);
|
||||
dta.SetResult(findName, findSize, findDate, findTime, findAttr);
|
||||
dta.SetResult(findName, lfindName, findSize, findDate, findTime, findAttr);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -353,6 +360,21 @@ bool isoDrive::GetFileAttr(const char *name, Bit16u *attr) {
|
||||
return success;
|
||||
}
|
||||
|
||||
bool isoDrive::GetFileAttrEx(char* name, struct stat *status) {
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned long isoDrive::GetCompressedSize(char* name) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined (WIN32)
|
||||
HANDLE isoDrive::CreateOpenFile(const char* name) {
|
||||
DOS_SetError(1);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool isoDrive::AllocationInfo(Bit16u *bytes_sector, Bit8u *sectors_cluster, Bit16u *total_clusters, Bit16u *free_clusters) {
|
||||
*bytes_sector = 2048;
|
||||
*sectors_cluster = 1; // cluster size for cdroms ?
|
||||
@ -547,7 +569,7 @@ bool isoDrive :: lookup(isoDirEntry *de, const char *path) {
|
||||
*de = this->rootEntry;
|
||||
if (!strcmp(path, "")) return true;
|
||||
|
||||
char isoPath[ISO_MAXPATHNAME];
|
||||
char isoPath[ISO_MAXPATHNAME], longname[ISO_MAXPATHNAME];
|
||||
safe_strncpy(isoPath, path, ISO_MAXPATHNAME);
|
||||
strreplace(isoPath, '\\', '/');
|
||||
|
||||
@ -567,7 +589,8 @@ bool isoDrive :: lookup(isoDirEntry *de, const char *path) {
|
||||
// look for the current path element
|
||||
int dirIterator = GetDirIterator(de);
|
||||
while (!found && GetNextDirEntry(dirIterator, de)) {
|
||||
if (!IS_ASSOC(FLAGS2) && (0 == strncasecmp((char*) de->ident, name, ISO_MAX_FILENAME_LENGTH))) {
|
||||
GetLongName((char*)de->ident,longname);
|
||||
if (!IS_ASSOC(FLAGS2) && (0 == strncasecmp((char*) de->ident, name, ISO_MAX_FILENAME_LENGTH)) ||0 == strncasecmp((char*) longname, name, ISO_MAXPATHNAME)) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
@ -584,3 +607,18 @@ void isoDrive :: MediaChange() {
|
||||
IDE_ATAPI_MediaChangeNotify(toupper(driveLetter) - 'A'); /* ewwww */
|
||||
}
|
||||
|
||||
void isoDrive :: GetLongName(char *ident, char *lfindName) {
|
||||
char *c=ident+strlen(ident);
|
||||
int i,j=222-strlen(ident)-6;
|
||||
for (i=5;i<j;i++) {
|
||||
if (*(c+i)=='N'&&*(c+i+1)=='M'&&*(c+i+2)>0&&*(c+i+3)==1&&*(c+i+4)==0&&*(c+i+5)>0)
|
||||
break;
|
||||
}
|
||||
if (i<j&&strcmp(ident,".")&&strcmp(ident,"..")) {
|
||||
strncpy(lfindName,c+i+5,*(c+i+2)-5);
|
||||
lfindName[*(c+i+2)-5]=0;
|
||||
} else
|
||||
strcpy(lfindName,ident);
|
||||
}
|
||||
|
||||
|
||||
|
@ -541,6 +541,9 @@ bool localDrive::GetSystemFilename(char *sysName, char const * const dosName) {
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined (WIN32)
|
||||
#include <Shellapi.h>
|
||||
#endif
|
||||
bool localDrive::FileUnlink(const char * name) {
|
||||
if (readonly) {
|
||||
DOS_SetError(DOSERR_WRITE_PROTECTED);
|
||||
@ -563,6 +566,20 @@ bool localDrive::FileUnlink(const char * name) {
|
||||
|
||||
if (ht_unlink(host_name)) {
|
||||
//Unlink failed for some reason try finding it.
|
||||
#if defined (WIN32)
|
||||
if (uselfn&&strlen(fullname)>1&&!strcmp(fullname+strlen(fullname)-2,"\\*")||strlen(fullname)>3&&!strcmp(fullname+strlen(fullname)-4,"\\*.*"))
|
||||
{
|
||||
SHFILEOPSTRUCT op={0};
|
||||
op.wFunc = FO_DELETE;
|
||||
fullname[strlen(fullname)+1]=0;
|
||||
op.pFrom = fullname;
|
||||
op.pTo = NULL;
|
||||
op.fFlags = FOF_FILESONLY | FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI | 0x1000;
|
||||
int err=SHFileOperation(&op);
|
||||
if (err) DOS_SetError(err);
|
||||
return !err;
|
||||
}
|
||||
#endif
|
||||
ht_stat_t buffer;
|
||||
if(ht_stat(host_name,&buffer)) return false; // File not found.
|
||||
|
||||
@ -606,6 +623,7 @@ bool localDrive::FindFirst(const char * _dir,DOS_DTA & dta,bool fcb_findfirst) {
|
||||
strcat(tempDir,_dir);
|
||||
CROSS_FILENAME(tempDir);
|
||||
|
||||
for (unsigned int i=0;i<strlen(tempDir);i++) tempDir[i]=toupper(tempDir[i]);
|
||||
if (nocachedir) EmptyCache();
|
||||
|
||||
if (allocation.mediaid==0xF0 ) {
|
||||
@ -627,12 +645,12 @@ bool localDrive::FindFirst(const char * _dir,DOS_DTA & dta,bool fcb_findfirst) {
|
||||
dta.SetDirID(id);
|
||||
|
||||
Bit8u sAttr;
|
||||
dta.GetSearchParams(sAttr,tempDir);
|
||||
dta.GetSearchParams(sAttr,tempDir,true);
|
||||
|
||||
if (this->isRemote() && this->isRemovable()) {
|
||||
// cdroms behave a bit different than regular drives
|
||||
if (sAttr == DOS_ATTR_VOLUME) {
|
||||
dta.SetResult(dirCache.GetLabel(),0,0,0,DOS_ATTR_VOLUME);
|
||||
dta.SetResult(dirCache.GetLabel(),dirCache.GetLabel(),0,0,0,DOS_ATTR_VOLUME);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
@ -644,13 +662,13 @@ bool localDrive::FindFirst(const char * _dir,DOS_DTA & dta,bool fcb_findfirst) {
|
||||
DOS_SetError(DOSERR_NO_MORE_FILES);
|
||||
return false;
|
||||
}
|
||||
dta.SetResult(dirCache.GetLabel(),0,0,0,DOS_ATTR_VOLUME);
|
||||
dta.SetResult(dirCache.GetLabel(),dirCache.GetLabel(),0,0,0,DOS_ATTR_VOLUME);
|
||||
return true;
|
||||
} else if ((sAttr & DOS_ATTR_VOLUME) && (*_dir == 0) && !fcb_findfirst) {
|
||||
//should check for a valid leading directory instead of 0
|
||||
//exists==true if the volume label matches the searchmask and the path is valid
|
||||
if (WildFileCmp(dirCache.GetLabel(),tempDir)) {
|
||||
dta.SetResult(dirCache.GetLabel(),0,0,0,DOS_ATTR_VOLUME);
|
||||
dta.SetResult(dirCache.GetLabel(),dirCache.GetLabel(),0,0,0,DOS_ATTR_VOLUME);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -662,31 +680,35 @@ char * shiftjis_upcase(char * str);
|
||||
|
||||
bool localDrive::FindNext(DOS_DTA & dta) {
|
||||
|
||||
char * dir_ent;
|
||||
char * dir_ent, *ldir_ent;
|
||||
ht_stat_t stat_block;
|
||||
char full_name[CROSS_LEN];
|
||||
char dir_entcopy[CROSS_LEN];
|
||||
char full_name[CROSS_LEN], lfull_name[LFN_NAMELENGTH+1];
|
||||
char dir_entcopy[CROSS_LEN], ldir_entcopy[CROSS_LEN];
|
||||
|
||||
Bit8u srch_attr;char srch_pattern[DOS_NAMELENGTH_ASCII];
|
||||
Bit8u srch_attr;char srch_pattern[LFN_NAMELENGTH];
|
||||
Bit8u find_attr;
|
||||
|
||||
dta.GetSearchParams(srch_attr,srch_pattern);
|
||||
dta.GetSearchParams(srch_attr,srch_pattern,true);
|
||||
Bit16u id = dta.GetDirID();
|
||||
|
||||
again:
|
||||
if (!dirCache.FindNext(id,dir_ent)) {
|
||||
if (!dirCache.FindNext(id,dir_ent,ldir_ent)) {
|
||||
DOS_SetError(DOSERR_NO_MORE_FILES);
|
||||
return false;
|
||||
}
|
||||
if(!WildFileCmp(dir_ent,srch_pattern)) goto again;
|
||||
if(!WildFileCmp(dir_ent,srch_pattern)&&!LWildFileCmp(ldir_ent,srch_pattern)) goto again;
|
||||
|
||||
strcpy(full_name,srchInfo[id].srch_dir);
|
||||
strcat(full_name,dir_ent);
|
||||
|
||||
strcpy(lfull_name,srchInfo[id].srch_dir);
|
||||
strcat(lfull_name,ldir_ent);
|
||||
|
||||
//GetExpandName might indirectly destroy dir_ent (by caching in a new directory
|
||||
//and due to its design dir_ent might be lost.)
|
||||
//Copying dir_ent first
|
||||
strcpy(dir_entcopy,dir_ent);
|
||||
strcpy(ldir_entcopy,ldir_ent);
|
||||
|
||||
char *temp_name = dirCache.GetExpandName(full_name);
|
||||
|
||||
@ -706,7 +728,8 @@ again:
|
||||
if (~srch_attr & find_attr & (DOS_ATTR_DIRECTORY | DOS_ATTR_HIDDEN | DOS_ATTR_SYSTEM)) goto again;
|
||||
|
||||
/*file is okay, setup everything to be copied in DTA Block */
|
||||
char find_name[DOS_NAMELENGTH_ASCII];Bit16u find_date,find_time;Bit32u find_size;
|
||||
char find_name[DOS_NAMELENGTH_ASCII], lfind_name[LFN_NAMELENGTH+1];
|
||||
Bit16u find_date,find_time;Bit32u find_size;
|
||||
|
||||
if(strlen(dir_entcopy)<DOS_NAMELENGTH_ASCII){
|
||||
strcpy(find_name,dir_entcopy);
|
||||
@ -714,7 +737,9 @@ again:
|
||||
shiftjis_upcase(find_name);
|
||||
else
|
||||
upcase(find_name);
|
||||
}
|
||||
}
|
||||
strcpy(lfind_name,ldir_entcopy);
|
||||
lfind_name[LFN_NAMELENGTH]=0;
|
||||
|
||||
find_size=(Bit32u) stat_block.st_size;
|
||||
struct tm *time;
|
||||
@ -725,7 +750,7 @@ again:
|
||||
find_time=6;
|
||||
find_date=4;
|
||||
}
|
||||
dta.SetResult(find_name,find_size,find_date,find_time,find_attr);
|
||||
dta.SetResult(find_name,lfind_name,find_size,find_date,find_time,find_attr);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -756,6 +781,55 @@ bool localDrive::GetFileAttr(const char * name,Bit16u * attr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool localDrive::GetFileAttrEx(char* name, struct stat *status) {
|
||||
char newname[CROSS_LEN];
|
||||
strcpy(newname,basedir);
|
||||
strcat(newname,name);
|
||||
CROSS_FILENAME(newname);
|
||||
dirCache.ExpandName(newname);
|
||||
return !stat(newname,status);
|
||||
}
|
||||
|
||||
unsigned long localDrive::GetCompressedSize(char* name) {
|
||||
#if !defined (WIN32)
|
||||
return 0;
|
||||
#else
|
||||
char newname[CROSS_LEN];
|
||||
strcpy(newname,basedir);
|
||||
strcat(newname,name);
|
||||
CROSS_FILENAME(newname);
|
||||
dirCache.ExpandName(newname);
|
||||
DWORD size = GetCompressedFileSize(newname, NULL);
|
||||
if (size != INVALID_FILE_SIZE) {
|
||||
if (size != 0 && size == GetFileSize(newname, NULL)) {
|
||||
DWORD sectors_per_cluster, bytes_per_sector, free_clusters, total_clusters;
|
||||
if (GetDiskFreeSpace(newname, §ors_per_cluster, &bytes_per_sector, &free_clusters, &total_clusters)) {
|
||||
size = ((size - 1) | (sectors_per_cluster * bytes_per_sector - 1)) + 1;
|
||||
}
|
||||
}
|
||||
return size;
|
||||
} else {
|
||||
DOS_SetError((Bit16u)GetLastError());
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined (WIN32)
|
||||
HANDLE localDrive::CreateOpenFile(const char* name) {
|
||||
char newname[CROSS_LEN];
|
||||
strcpy(newname,basedir);
|
||||
strcat(newname,name);
|
||||
CROSS_FILENAME(newname);
|
||||
dirCache.ExpandName(newname);
|
||||
HANDLE handle=CreateFile(newname, FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||
if (handle==INVALID_HANDLE_VALUE)
|
||||
DOS_SetError((Bit16u)GetLastError());
|
||||
return handle;
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool localDrive::MakeDir(const char * dir) {
|
||||
if (nocachedir) EmptyCache();
|
||||
|
||||
@ -996,43 +1070,53 @@ void localDrive::closedir(void *handle) {
|
||||
close_directory((dir_information*)handle);
|
||||
}
|
||||
|
||||
bool localDrive::read_directory_first(void *handle, char* entry_name, bool& is_directory) {
|
||||
host_cnv_char_t tmp[MAX_PATH+1];
|
||||
bool localDrive::read_directory_first(void *handle, char* entry_name, char* entry_sname, bool& is_directory) {
|
||||
host_cnv_char_t tmp[MAX_PATH+1], stmp[MAX_PATH+1];
|
||||
|
||||
if (::read_directory_firstw((dir_information*)handle, tmp, is_directory)) {
|
||||
if (::read_directory_firstw((dir_information*)handle, tmp, stmp, is_directory)) {
|
||||
// guest to host code page translation
|
||||
char *n_temp_name = CodePageHostToGuest(tmp);
|
||||
if (n_temp_name == NULL) {
|
||||
char *n_stemp_name = CodePageHostToGuest(stmp);
|
||||
if (n_stemp_name == NULL) {
|
||||
#ifdef host_cnv_use_wchar
|
||||
LOG_MSG("%s: Filename '%ls' from host is non-representable on the guest filesystem through code page conversion",__FUNCTION__,tmp);
|
||||
LOG_MSG("%s: Filename '%ls' from host is non-representable on the guest filesystem through code page conversion",__FUNCTION__,stmp);
|
||||
#else
|
||||
LOG_MSG("%s: Filename '%s' from host is non-representable on the guest filesystem through code page conversion",__FUNCTION__,tmp);
|
||||
LOG_MSG("%s: Filename '%s' from host is non-representable on the guest filesystem through code page conversion",__FUNCTION__,stmp);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
strcpy(entry_name,n_temp_name);
|
||||
#if defined(WIN32)
|
||||
wcstombs(entry_name, tmp, MAX_PATH);
|
||||
#else
|
||||
strcpy(entry_name,tmp);
|
||||
#endif
|
||||
strcpy(entry_sname,n_stemp_name);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool localDrive::read_directory_next(void *handle, char* entry_name, bool& is_directory) {
|
||||
host_cnv_char_t tmp[MAX_PATH+1];
|
||||
bool localDrive::read_directory_next(void *handle, char* entry_name, char* entry_sname, bool& is_directory) {
|
||||
host_cnv_char_t tmp[MAX_PATH+1], stmp[MAX_PATH+1];
|
||||
|
||||
next:
|
||||
if (::read_directory_nextw((dir_information*)handle, tmp, is_directory)) {
|
||||
if (::read_directory_nextw((dir_information*)handle, tmp, stmp, is_directory)) {
|
||||
// guest to host code page translation
|
||||
char *n_temp_name = CodePageHostToGuest(tmp);
|
||||
if (n_temp_name == NULL) {
|
||||
char *n_stemp_name = CodePageHostToGuest(stmp);
|
||||
if (n_stemp_name == NULL) {
|
||||
#ifdef host_cnv_use_wchar
|
||||
LOG_MSG("%s: Filename '%ls' from host is non-representable on the guest filesystem through code page conversion",__FUNCTION__,tmp);
|
||||
LOG_MSG("%s: Filename '%ls' from host is non-representable on the guest filesystem through code page conversion",__FUNCTION__,stmp);
|
||||
#else
|
||||
LOG_MSG("%s: Filename '%s' from host is non-representable on the guest filesystem through code page conversion",__FUNCTION__,tmp);
|
||||
LOG_MSG("%s: Filename '%s' from host is non-representable on the guest filesystem through code page conversion",__FUNCTION__,stmp);
|
||||
#endif
|
||||
goto next;
|
||||
}
|
||||
strcpy(entry_name,n_temp_name);
|
||||
#if defined(WIN32)
|
||||
wcstombs(entry_name, tmp, MAX_PATH);
|
||||
#else
|
||||
strcpy(entry_name,tmp);
|
||||
#endif
|
||||
strcpy(entry_sname,n_stemp_name);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1337,6 +1421,20 @@ bool cdromDrive::GetFileAttr(const char * name,Bit16u * attr) {
|
||||
return result;
|
||||
}
|
||||
|
||||
bool cdromDrive::GetFileAttrEx(char* name, struct stat *status) {
|
||||
return localDrive::GetFileAttrEx(name,status);
|
||||
}
|
||||
|
||||
unsigned long cdromDrive::GetCompressedSize(char* name) {
|
||||
return localDrive::GetCompressedSize(name);
|
||||
}
|
||||
|
||||
#if defined (WIN32)
|
||||
HANDLE cdromDrive::CreateOpenFile(const char* name) {
|
||||
return localDrive::CreateOpenFile(name);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool cdromDrive::FindFirst(const char * _dir,DOS_DTA & dta,bool /*fcb_findfirst*/) {
|
||||
// If media has changed, reInit drivecache.
|
||||
if (MSCDEX_HasMediaChanged(subUnit)) {
|
||||
|
@ -28,6 +28,7 @@
|
||||
|
||||
struct VFILE_Block {
|
||||
const char * name;
|
||||
const char * lname;
|
||||
Bit8u * data;
|
||||
Bit32u size;
|
||||
Bit16u date;
|
||||
@ -55,6 +56,7 @@ void VFILE_RegisterBuiltinFileBlob(const struct BuiltinFileBlob &b) {
|
||||
void VFILE_Register(const char * name,Bit8u * data,Bit32u size) {
|
||||
VFILE_Block * new_file=new VFILE_Block;
|
||||
new_file->name=name;
|
||||
new_file->lname=name;
|
||||
new_file->data=data;
|
||||
new_file->size=size;
|
||||
new_file->date=DOS_PackDate(2002,10,1);
|
||||
@ -225,14 +227,14 @@ bool Virtual_Drive::FileExists(const char* name){
|
||||
bool Virtual_Drive::FindFirst(const char * _dir,DOS_DTA & dta,bool fcb_findfirst) {
|
||||
(void)_dir;//UNUSED
|
||||
search_file=first_file;
|
||||
Bit8u attr;char pattern[DOS_NAMELENGTH_ASCII];
|
||||
dta.GetSearchParams(attr,pattern);
|
||||
Bit8u attr;char pattern[CROSS_LEN];
|
||||
dta.GetSearchParams(attr,pattern,true);
|
||||
if (attr == DOS_ATTR_VOLUME) {
|
||||
dta.SetResult(GetLabel(),0,0,0,DOS_ATTR_VOLUME);
|
||||
dta.SetResult(GetLabel(),GetLabel(),0,0,0,DOS_ATTR_VOLUME);
|
||||
return true;
|
||||
} else if ((attr & DOS_ATTR_VOLUME) && !fcb_findfirst) {
|
||||
if (WildFileCmp(GetLabel(),pattern)) {
|
||||
dta.SetResult(GetLabel(),0,0,0,DOS_ATTR_VOLUME);
|
||||
dta.SetResult(GetLabel(),GetLabel(),0,0,0,DOS_ATTR_VOLUME);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -240,11 +242,11 @@ bool Virtual_Drive::FindFirst(const char * _dir,DOS_DTA & dta,bool fcb_findfirst
|
||||
}
|
||||
|
||||
bool Virtual_Drive::FindNext(DOS_DTA & dta) {
|
||||
Bit8u attr;char pattern[DOS_NAMELENGTH_ASCII];
|
||||
dta.GetSearchParams(attr,pattern);
|
||||
Bit8u attr;char pattern[CROSS_LEN];
|
||||
dta.GetSearchParams(attr,pattern,true);
|
||||
while (search_file) {
|
||||
if (WildFileCmp(search_file->name,pattern)) {
|
||||
dta.SetResult(search_file->name,search_file->size,search_file->date,search_file->time,DOS_ATTR_ARCHIVE);
|
||||
dta.SetResult(search_file->name,search_file->lname,search_file->size,search_file->date,search_file->time,DOS_ATTR_ARCHIVE);
|
||||
search_file=search_file->next;
|
||||
return true;
|
||||
}
|
||||
@ -266,6 +268,21 @@ bool Virtual_Drive::GetFileAttr(const char * name,Bit16u * attr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Virtual_Drive::GetFileAttrEx(char* name, struct stat *status) {
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned long Virtual_Drive::GetCompressedSize(char* name) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined (WIN32)
|
||||
HANDLE Virtual_Drive::CreateOpenFile(const char* name) {
|
||||
DOS_SetError(1);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool Virtual_Drive::Rename(const char * oldname,const char * newname) {
|
||||
(void)oldname;//UNUSED
|
||||
(void)newname;//UNUSED
|
||||
|
@ -29,15 +29,21 @@ bool WildFileCmp(const char * file, const char * wild)
|
||||
{
|
||||
char file_name[9];
|
||||
char file_ext[4];
|
||||
char wild_name[9];
|
||||
char wild_ext[4];
|
||||
char wild_name[10];
|
||||
char wild_ext[5];
|
||||
const char * find_ext;
|
||||
Bitu r;
|
||||
|
||||
strcpy(file_name," ");
|
||||
strcpy(file_ext," ");
|
||||
strcpy(wild_name," ");
|
||||
strcpy(wild_ext," ");
|
||||
for (r=0;r<9;r++) {
|
||||
file_name[r]=0;
|
||||
wild_name[r]=0;
|
||||
}
|
||||
wild_name[9]=0;
|
||||
for (r=0;r<4;r++) {
|
||||
file_ext[r]=0;
|
||||
wild_ext[r]=0;
|
||||
}
|
||||
wild_ext[4]=0;
|
||||
|
||||
find_ext=strrchr(file,'.');
|
||||
if (find_ext) {
|
||||
@ -53,12 +59,12 @@ bool WildFileCmp(const char * file, const char * wild)
|
||||
find_ext=strrchr(wild,'.');
|
||||
if (find_ext) {
|
||||
Bitu size=(Bitu)(find_ext-wild);
|
||||
if (size>8) size=8;
|
||||
if (size>9) size=9;
|
||||
memcpy(wild_name,wild,size);
|
||||
find_ext++;
|
||||
memcpy(wild_ext,find_ext,(strlen(find_ext)>3) ? 3 : strlen(find_ext));
|
||||
memcpy(wild_ext,find_ext,(strlen(find_ext)>4) ? 4 : strlen(find_ext));
|
||||
} else {
|
||||
memcpy(wild_name,wild,(strlen(wild) > 8) ? 8 : strlen(wild));
|
||||
memcpy(wild_name,wild,(strlen(wild) > 9) ? 9 : strlen(wild));
|
||||
}
|
||||
upcase(wild_name);upcase(wild_ext);
|
||||
/* Names are right do some checking */
|
||||
@ -68,6 +74,7 @@ bool WildFileCmp(const char * file, const char * wild)
|
||||
if (wild_name[r]!='?' && wild_name[r]!=file_name[r]) return false;
|
||||
r++;
|
||||
}
|
||||
if (wild_name[r]&&wild_name[r]!='*') return false;
|
||||
checkext:
|
||||
r=0;
|
||||
while (r<3) {
|
||||
@ -75,9 +82,78 @@ checkext:
|
||||
if (wild_ext[r]!='?' && wild_ext[r]!=file_ext[r]) return false;
|
||||
r++;
|
||||
}
|
||||
if (wild_ext[r]&&wild_ext[r]!='*') return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LWildFileCmp(const char * file, const char * wild)
|
||||
{
|
||||
if (!uselfn) return false;
|
||||
char file_name[256];
|
||||
char file_ext[256];
|
||||
char wild_name[256];
|
||||
char wild_ext[256];
|
||||
const char * find_ext;
|
||||
Bitu r;
|
||||
|
||||
for (r=0;r<256;r++) {
|
||||
file_name[r]=0;
|
||||
wild_name[r]=0;
|
||||
}
|
||||
for (r=0;r<256;r++) {
|
||||
file_ext[r]=0;
|
||||
wild_ext[r]=0;
|
||||
}
|
||||
|
||||
Bitu size,elen;
|
||||
find_ext=strrchr(file,'.');
|
||||
if (find_ext) {
|
||||
size=(Bitu)(find_ext-file);
|
||||
if (size>255) size=255;
|
||||
memcpy(file_name,file,size);
|
||||
find_ext++;
|
||||
elen=strlen(find_ext);
|
||||
memcpy(file_ext,find_ext,(strlen(find_ext)>255) ? 255 : strlen(find_ext));
|
||||
} else {
|
||||
size=strlen(file);
|
||||
elen=0;
|
||||
memcpy(file_name,file,(strlen(file) > 255) ? 255 : strlen(file));
|
||||
}
|
||||
upcase(file_name);upcase(file_ext);
|
||||
char nwild[LFN_NAMELENGTH+2];
|
||||
strcpy(nwild,wild);
|
||||
if (strrchr(nwild,'*')&&strrchr(nwild,'.')==NULL) strcat(nwild,".*");
|
||||
find_ext=strrchr(nwild,'.');
|
||||
if (find_ext) {
|
||||
Bitu size=(Bitu)(find_ext-nwild);
|
||||
if (size>255) size=255;
|
||||
memcpy(wild_name,nwild,size);
|
||||
find_ext++;
|
||||
memcpy(wild_ext,find_ext,(strlen(find_ext)>255) ? 255 : strlen(find_ext));
|
||||
} else {
|
||||
memcpy(wild_name,nwild,(strlen(nwild) > 255) ? 255 : strlen(nwild));
|
||||
}
|
||||
upcase(wild_name);upcase(wild_ext);
|
||||
/* Names are right do some checking */
|
||||
r=0;
|
||||
while (r<size) {
|
||||
if (wild_name[r]=='*') goto checkext;
|
||||
if (wild_name[r]!='?' && wild_name[r]!=file_name[r]) return false;
|
||||
r++;
|
||||
}
|
||||
if (wild_name[r]&&wild_name[r]!='*') return false;
|
||||
checkext:
|
||||
r=0;
|
||||
while (r<elen) {
|
||||
if (wild_ext[r]=='*') return true;
|
||||
if (wild_ext[r]!='?' && wild_ext[r]!=file_ext[r]) return false;
|
||||
r++;
|
||||
}
|
||||
if (wild_ext[r]&&wild_ext[r]!='*') return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Set_Label(char const * const input, char * const output, bool cdrom) {
|
||||
/* I don't know what MSCDEX.EXE does but don't put dots in the 11-char volume label for non-CD-ROM drives */
|
||||
if (!cdrom) {
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "shell.h" /* for DOS_Shell */
|
||||
|
||||
bool WildFileCmp(const char * file, const char * wild);
|
||||
bool LWildFileCmp(const char * file, const char * wild);
|
||||
void Set_Label(char const * const input, char * const output, bool cdrom);
|
||||
|
||||
class DriveManager {
|
||||
@ -66,6 +67,11 @@ public:
|
||||
virtual bool FindFirst(const char * _dir,DOS_DTA & dta,bool fcb_findfirst=false);
|
||||
virtual bool FindNext(DOS_DTA & dta);
|
||||
virtual bool GetFileAttr(const char * name,Bit16u * attr);
|
||||
virtual bool GetFileAttrEx(char* name, struct stat *status);
|
||||
virtual unsigned long GetCompressedSize(char* name);
|
||||
#if defined (WIN32)
|
||||
virtual HANDLE CreateOpenFile(char const* const name);
|
||||
#endif
|
||||
virtual bool Rename(const char * oldname,const char * newname);
|
||||
virtual bool AllocationInfo(Bit16u * _bytes_sector,Bit8u * _sectors_cluster,Bit16u * _total_clusters,Bit16u * _free_clusters);
|
||||
virtual bool FileExists(const char* name);
|
||||
@ -78,8 +84,8 @@ public:
|
||||
virtual void SetLabel(const char *label, bool iscdrom, bool updatable) { dirCache.SetLabel(label,iscdrom,updatable); };
|
||||
virtual void *opendir(const char *name);
|
||||
virtual void closedir(void *handle);
|
||||
virtual bool read_directory_first(void *handle, char* entry_name, bool& is_directory);
|
||||
virtual bool read_directory_next(void *handle, char* entry_name, bool& is_directory);
|
||||
virtual bool read_directory_first(void *handle, char* entry_name, char* entry_sname, bool& is_directory);
|
||||
virtual bool read_directory_next(void *handle, char* entry_name, char* entry_sname, bool& is_directory);
|
||||
|
||||
virtual void EmptyCache(void) { dirCache.EmptyCache(); };
|
||||
virtual void MediaChange() {};
|
||||
@ -218,6 +224,11 @@ public:
|
||||
virtual bool FindFirst(const char * _dir,DOS_DTA & dta,bool fcb_findfirst=false);
|
||||
virtual bool FindNext(DOS_DTA & dta);
|
||||
virtual bool GetFileAttr(const char * name,Bit16u * attr);
|
||||
virtual bool GetFileAttrEx(char* name, struct stat *status);
|
||||
virtual unsigned long GetCompressedSize(char* name);
|
||||
#if defined (WIN32)
|
||||
virtual HANDLE CreateOpenFile(char const* const name);
|
||||
#endif
|
||||
virtual bool Rename(const char * oldname,const char * newname);
|
||||
virtual bool AllocationInfo(Bit16u * _bytes_sector,Bit8u * _sectors_cluster,Bit16u * _total_clusters,Bit16u * _free_clusters);
|
||||
virtual bool FileExists(const char* name);
|
||||
@ -314,6 +325,11 @@ public:
|
||||
virtual bool MakeDir(const char * dir);
|
||||
virtual bool Rename(const char * oldname,const char * newname);
|
||||
virtual bool GetFileAttr(const char * name,Bit16u * attr);
|
||||
virtual bool GetFileAttrEx(char* name, struct stat *status);
|
||||
virtual unsigned long GetCompressedSize(char* name);
|
||||
#if defined (WIN32)
|
||||
virtual HANDLE CreateOpenFile(char const* const name);
|
||||
#endif
|
||||
virtual bool FindFirst(const char * _dir,DOS_DTA & dta,bool fcb_findfirst=false);
|
||||
virtual void SetDir(const char* path);
|
||||
virtual bool isRemote(void);
|
||||
@ -434,6 +450,11 @@ public:
|
||||
virtual bool FindFirst(const char *dir, DOS_DTA &dta, bool fcb_findfirst);
|
||||
virtual bool FindNext(DOS_DTA &dta);
|
||||
virtual bool GetFileAttr(const char *name, Bit16u *attr);
|
||||
virtual bool GetFileAttrEx(char* name, struct stat *status);
|
||||
virtual unsigned long GetCompressedSize(char* name);
|
||||
#if defined (WIN32)
|
||||
virtual HANDLE CreateOpenFile(char const* const name);
|
||||
#endif
|
||||
virtual bool Rename(const char * oldname,const char * newname);
|
||||
virtual bool AllocationInfo(Bit16u *bytes_sector, Bit8u *sectors_cluster, Bit16u *total_clusters, Bit16u *free_clusters);
|
||||
virtual bool FileExists(const char *name);
|
||||
@ -457,6 +478,7 @@ private:
|
||||
bool GetNextDirEntry(const int dirIteratorHandle, isoDirEntry* de);
|
||||
void FreeDirIterator(const int dirIterator);
|
||||
bool ReadCachedSector(Bit8u** buffer, const Bit32u sector);
|
||||
void GetLongName(char *ident, char *lfindName);
|
||||
|
||||
struct DirIterator {
|
||||
bool valid;
|
||||
@ -498,6 +520,11 @@ public:
|
||||
bool FindFirst(const char * _dir,DOS_DTA & dta,bool fcb_findfirst);
|
||||
bool FindNext(DOS_DTA & dta);
|
||||
bool GetFileAttr(const char * name,Bit16u * attr);
|
||||
bool GetFileAttrEx(char* name, struct stat *status);
|
||||
unsigned long GetCompressedSize(char* name);
|
||||
#if defined (WIN32)
|
||||
HANDLE CreateOpenFile(char const* const name);
|
||||
#endif
|
||||
bool Rename(const char * oldname,const char * newname);
|
||||
bool AllocationInfo(Bit16u * _bytes_sector,Bit8u * _sectors_cluster,Bit16u * _total_clusters,Bit16u * _free_clusters);
|
||||
bool FileExists(const char* name);
|
||||
|
@ -514,9 +514,9 @@ std::string GetCaptureFilePath(const char * type,const char * ext) {
|
||||
lowcase(file_start);
|
||||
strcat(file_start,"_");
|
||||
bool is_directory;
|
||||
char tempname[CROSS_LEN];
|
||||
bool testRead = read_directory_first(dir, tempname, is_directory );
|
||||
for ( ; testRead; testRead = read_directory_next(dir, tempname, is_directory) ) {
|
||||
char tempname[CROSS_LEN], sname[12];
|
||||
bool testRead = read_directory_first(dir, tempname, sname, is_directory );
|
||||
for ( ; testRead; testRead = read_directory_next(dir, tempname, sname, is_directory) ) {
|
||||
char * test=strstr(tempname,ext);
|
||||
if (!test || strlen(test)!=strlen(ext))
|
||||
continue;
|
||||
@ -556,8 +556,9 @@ FILE * OpenCaptureFile(const char * type,const char * ext) {
|
||||
strcat(file_start,"_");
|
||||
bool is_directory;
|
||||
char tempname[CROSS_LEN];
|
||||
bool testRead = read_directory_first(dir, tempname, is_directory );
|
||||
for ( ; testRead; testRead = read_directory_next(dir, tempname, is_directory) ) {
|
||||
bool testRead = read_directory_first(dir, tempname, tempname, is_directory );
|
||||
for ( ; testRead; testRead = read_directory_next(dir, tempname, tempname, is_directory) ) {
|
||||
// didn't adapt this for long file names
|
||||
char * test=strstr(tempname,ext);
|
||||
if (!test || strlen(test)!=strlen(ext))
|
||||
continue;
|
||||
|
@ -208,7 +208,7 @@ dir_information* open_directory(const char* dirname) {
|
||||
return (_access(dirname,0) ? NULL : &dir);
|
||||
}
|
||||
|
||||
bool read_directory_firstw(dir_information* dirp, wchar_t* entry_name, bool& is_directory) {
|
||||
bool read_directory_firstw(dir_information* dirp, wchar_t* entry_name, wchar_t* entry_sname, bool& is_directory) {
|
||||
if (!dirp->wide) return false;
|
||||
|
||||
// TODO: offer a config.h option to opt out of Windows widechar functions
|
||||
@ -219,6 +219,7 @@ bool read_directory_firstw(dir_information* dirp, wchar_t* entry_name, bool& is_
|
||||
|
||||
// TODO: offer a config.h option to opt out of Windows widechar functions
|
||||
wcsncpy(entry_name,dirp->search_data.w.cFileName,(MAX_PATH<CROSS_LEN)?MAX_PATH:CROSS_LEN);
|
||||
wcsncpy(entry_sname,dirp->search_data.w.cAlternateFileName,13);
|
||||
|
||||
if (dirp->search_data.w.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) is_directory = true;
|
||||
else is_directory = false;
|
||||
@ -226,7 +227,7 @@ bool read_directory_firstw(dir_information* dirp, wchar_t* entry_name, bool& is_
|
||||
return true;
|
||||
}
|
||||
|
||||
bool read_directory_nextw(dir_information* dirp, wchar_t* entry_name, bool& is_directory) {
|
||||
bool read_directory_nextw(dir_information* dirp, wchar_t* entry_name, wchar_t* entry_sname, bool& is_directory) {
|
||||
if (!dirp->wide) return false;
|
||||
|
||||
// TODO: offer a config.h option to opt out of Windows widechar functions
|
||||
@ -235,6 +236,7 @@ bool read_directory_nextw(dir_information* dirp, wchar_t* entry_name, bool& is_d
|
||||
|
||||
// TODO: offer a config.h option to opt out of Windows widechar functions
|
||||
wcsncpy(entry_name,dirp->search_data.w.cFileName,(MAX_PATH<CROSS_LEN)?MAX_PATH:CROSS_LEN);
|
||||
wcsncpy(entry_sname,dirp->search_data.w.cAlternateFileName,13);
|
||||
|
||||
if (dirp->search_data.w.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) is_directory = true;
|
||||
else is_directory = false;
|
||||
@ -242,7 +244,7 @@ bool read_directory_nextw(dir_information* dirp, wchar_t* entry_name, bool& is_d
|
||||
return true;
|
||||
}
|
||||
|
||||
bool read_directory_first(dir_information* dirp, char* entry_name, bool& is_directory) {
|
||||
bool read_directory_first(dir_information* dirp, char* entry_name, char* entry_sname, bool& is_directory) {
|
||||
if (!dirp) return false;
|
||||
if (dirp->wide) return false;
|
||||
|
||||
@ -254,14 +256,15 @@ bool read_directory_first(dir_information* dirp, char* entry_name, bool& is_dire
|
||||
|
||||
// TODO: offer a config.h option to opt out of Windows widechar functions
|
||||
safe_strncpy(entry_name,dirp->search_data.a.cFileName,(MAX_PATH<CROSS_LEN)?MAX_PATH:CROSS_LEN);
|
||||
|
||||
safe_strncpy(entry_sname,dirp->search_data.a.cAlternateFileName,13);
|
||||
|
||||
if (dirp->search_data.a.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) is_directory = true;
|
||||
else is_directory = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool read_directory_next(dir_information* dirp, char* entry_name, bool& is_directory) {
|
||||
bool read_directory_next(dir_information* dirp, char* entry_name, char* entry_sname, bool& is_directory) {
|
||||
if (!dirp) return false;
|
||||
if (dirp->wide) return false;
|
||||
|
||||
@ -271,6 +274,7 @@ bool read_directory_next(dir_information* dirp, char* entry_name, bool& is_direc
|
||||
|
||||
// TODO: offer a config.h option to opt out of Windows widechar functions
|
||||
safe_strncpy(entry_name,dirp->search_data.a.cFileName,(MAX_PATH<CROSS_LEN)?MAX_PATH:CROSS_LEN);
|
||||
safe_strncpy(entry_sname,dirp->search_data.a.cAlternateFileName,13);
|
||||
|
||||
if (dirp->search_data.a.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) is_directory = true;
|
||||
else is_directory = false;
|
||||
@ -294,7 +298,7 @@ dir_information* open_directory(const char* dirname) {
|
||||
return dir.dir?&dir:NULL;
|
||||
}
|
||||
|
||||
bool read_directory_first(dir_information* dirp, char* entry_name, bool& is_directory) {
|
||||
bool read_directory_first(dir_information* dirp, char* entry_name, char* entry_sname, bool& is_directory) {
|
||||
if (!dirp) return false;
|
||||
struct dirent* dentry = readdir(dirp->dir);
|
||||
if (dentry==NULL) {
|
||||
@ -303,6 +307,7 @@ bool read_directory_first(dir_information* dirp, char* entry_name, bool& is_dire
|
||||
|
||||
// safe_strncpy(entry_name,dentry->d_name,(FILENAME_MAX<MAX_PATH)?FILENAME_MAX:MAX_PATH); // [include stdio.h], maybe pathconf()
|
||||
safe_strncpy(entry_name,dentry->d_name,CROSS_LEN);
|
||||
entry_sname[0]=0;
|
||||
|
||||
#ifdef DIRENT_HAS_D_TYPE
|
||||
if(dentry->d_type == DT_DIR) {
|
||||
@ -326,7 +331,7 @@ bool read_directory_first(dir_information* dirp, char* entry_name, bool& is_dire
|
||||
return true;
|
||||
}
|
||||
|
||||
bool read_directory_next(dir_information* dirp, char* entry_name, bool& is_directory) {
|
||||
bool read_directory_next(dir_information* dirp, char* entry_name, char* entry_sname, bool& is_directory) {
|
||||
if (!dirp) return false;
|
||||
struct dirent* dentry = readdir(dirp->dir);
|
||||
if (dentry==NULL) {
|
||||
@ -335,6 +340,8 @@ bool read_directory_next(dir_information* dirp, char* entry_name, bool& is_direc
|
||||
|
||||
// safe_strncpy(entry_name,dentry->d_name,(FILENAME_MAX<MAX_PATH)?FILENAME_MAX:MAX_PATH); // [include stdio.h], maybe pathconf()
|
||||
safe_strncpy(entry_name,dentry->d_name,CROSS_LEN);
|
||||
entry_sname[0]=0;
|
||||
|
||||
|
||||
#ifdef DIRENT_HAS_D_TYPE
|
||||
if(dentry->d_type == DT_DIR) {
|
||||
|
@ -150,9 +150,9 @@ Program::Program() {
|
||||
while (mem_readb(envscan)) envscan+=(PhysPt)(mem_strlen(envscan)+1);
|
||||
envscan+=3;
|
||||
CommandTail tail;
|
||||
MEM_BlockRead(PhysMake(dos.psp(),128),&tail,128);
|
||||
if (tail.count<127) tail.buffer[tail.count]=0;
|
||||
else tail.buffer[126]=0;
|
||||
MEM_BlockRead(PhysMake(dos.psp(),CTBUF+1),&tail,CTBUF+1);
|
||||
if (tail.count<CTBUF) tail.buffer[tail.count]=0;
|
||||
else tail.buffer[CTBUF-1]=0;
|
||||
char filename[256+1];
|
||||
MEM_StrCopy(envscan,filename,256);
|
||||
cmd = new CommandLine(filename,tail.buffer);
|
||||
|
@ -77,7 +77,8 @@ char *ltrim(char *str) {
|
||||
char *rtrim(char *str) {
|
||||
char *p;
|
||||
p = strchr(str, '\0');
|
||||
while (--p >= str && isspace(*reinterpret_cast<unsigned char*>(p))) {}
|
||||
while (--p >= str && *reinterpret_cast<unsigned char*>(p) != '\f' && isspace(*reinterpret_cast<unsigned char*>(p))) {};
|
||||
|
||||
p[1] = '\0';
|
||||
return str;
|
||||
}
|
||||
@ -145,6 +146,24 @@ char * StripWord(char *&line) {
|
||||
return begin;
|
||||
}
|
||||
|
||||
char * StripArg(char *&line) {
|
||||
char * scan=line;
|
||||
int q=0;
|
||||
scan=ltrim(scan);
|
||||
char * begin=scan;
|
||||
for (char c = *scan ;(c = *scan);scan++) {
|
||||
if (*scan=='"') {
|
||||
q++;
|
||||
} else if (q/2*2==q && isspace(*reinterpret_cast<unsigned char*>(&c))) {
|
||||
*scan++=0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
line=scan;
|
||||
return begin;
|
||||
}
|
||||
|
||||
|
||||
Bits ConvDecWord(char * word) {
|
||||
bool negative=false;Bitu ret=0;
|
||||
if (*word=='-') {
|
||||
|
@ -635,9 +635,9 @@ static Bitu INT2E_Handler(void) {
|
||||
|
||||
/* Read and fix up command string */
|
||||
CommandTail tail;
|
||||
MEM_BlockRead(PhysMake(dos.psp(),128),&tail,128);
|
||||
if (tail.count<127) tail.buffer[tail.count]=0;
|
||||
else tail.buffer[126]=0;
|
||||
MEM_BlockRead(PhysMake(dos.psp(),CTBUF+1),&tail,CTBUF+1);
|
||||
if (tail.count<CTBUF) tail.buffer[tail.count]=0;
|
||||
else tail.buffer[CTBUF-1]=0;
|
||||
char* crlf=strpbrk(tail.buffer,"\r\n");
|
||||
if (crlf) *crlf=0;
|
||||
|
||||
@ -686,7 +686,7 @@ void SHELL_Init() {
|
||||
MSG_Add("SHELL_MISSING_PARAMETER","Required parameter missing.\n");
|
||||
MSG_Add("SHELL_CMD_CHDIR_ERROR","Unable to change to: %s.\n");
|
||||
MSG_Add("SHELL_CMD_CHDIR_HINT","Hint: To change to different drive type \033[31m%c:\033[0m\n");
|
||||
MSG_Add("SHELL_CMD_CHDIR_HINT_2","directoryname is longer than 8 characters and/or contains spaces.\nTry \033[31mcd %s\033[0m\n");
|
||||
MSG_Add("SHELL_CMD_CHDIR_HINT_2","directoryname contains unquoted spaces.\nTry \033[31mcd %s\033[0m or properly quote them with quotation marks.\n");
|
||||
MSG_Add("SHELL_CMD_CHDIR_HINT_3","You are still on drive Z:, change to a mounted drive with \033[31mC:\033[0m.\n");
|
||||
MSG_Add("SHELL_CMD_DATE_HELP","Displays or changes the internal date.\n");
|
||||
MSG_Add("SHELL_CMD_DATE_ERROR","The specified date is not correct.\n");
|
||||
@ -707,6 +707,7 @@ void SHELL_Init() {
|
||||
" /H: Synchronize with host\n");
|
||||
MSG_Add("SHELL_CMD_MKDIR_ERROR","Unable to make: %s.\n");
|
||||
MSG_Add("SHELL_CMD_RMDIR_ERROR","Unable to remove: %s.\n");
|
||||
MSG_Add("SHELL_CMD_RENAME_ERROR","Unable to rename: %s.\n");
|
||||
MSG_Add("SHELL_CMD_DEL_ERROR","Unable to delete: %s.\n");
|
||||
MSG_Add("SHELL_CMD_DEL_SURE","Are you sure[Y,N]?");
|
||||
MSG_Add("SHELL_SYNTAXERROR","The syntax of the command is incorrect.\n");
|
||||
@ -1174,12 +1175,12 @@ void SHELL_Init() {
|
||||
/* Set the command line for the shell start up */
|
||||
CommandTail tail;
|
||||
tail.count=(Bit8u)strlen(init_line);
|
||||
memset(&tail.buffer, 0, 127);
|
||||
strncpy(tail.buffer,init_line,127);
|
||||
MEM_BlockWrite(PhysMake(psp_seg,128),&tail,128);
|
||||
memset(&tail.buffer, 0, CTBUF);
|
||||
strncpy(tail.buffer,init_line,CTBUF);
|
||||
MEM_BlockWrite(PhysMake(psp_seg,CTBUF+1),&tail,CTBUF+1);
|
||||
|
||||
/* Setup internal DOS Variables */
|
||||
dos.dta(RealMake(psp_seg,0x80));
|
||||
dos.dta(RealMake(psp_seg,CTBUF+1));
|
||||
dos.psp(psp_seg);
|
||||
|
||||
/* settings */
|
||||
|
@ -408,12 +408,17 @@ continue_1:
|
||||
}
|
||||
/* If delete accept switches mind the space infront of them. See the dir /p code */
|
||||
|
||||
char full[DOS_PATHLENGTH];
|
||||
char full[DOS_PATHLENGTH],sfull[DOS_PATHLENGTH+2];
|
||||
char buffer[CROSS_LEN];
|
||||
args = ExpandDot(args,buffer, CROSS_LEN);
|
||||
StripSpaces(args);
|
||||
if (!DOS_Canonicalize(args,full)) { WriteOut(MSG_Get("SHELL_ILLEGAL_PATH"));return; }
|
||||
bool res=DOS_FindFirst(args,0xffff & ~DOS_ATTR_VOLUME);
|
||||
char spath[DOS_PATHLENGTH],sargs[DOS_PATHLENGTH];
|
||||
if (!DOS_GetSFNPath(args,spath,false)) {
|
||||
WriteOut(MSG_Get("SHELL_CMD_DEL_ERROR"),args);
|
||||
return;
|
||||
} sprintf(sargs,"\"%s\"",spath);
|
||||
bool res=DOS_FindFirst(sargs,0xffff & ~DOS_ATTR_VOLUME);
|
||||
if (!res) {
|
||||
WriteOut(MSG_Get("SHELL_CMD_DEL_ERROR"),args);
|
||||
dos.dta(save_dta);
|
||||
@ -421,13 +426,16 @@ continue_1:
|
||||
}
|
||||
//end can't be 0, but if it is we'll get a nice crash, who cares :)
|
||||
char * end=strrchr(full,'\\')+1;*end=0;
|
||||
char name[DOS_NAMELENGTH_ASCII];Bit32u size;Bit16u time,date;Bit8u attr;
|
||||
char name[DOS_NAMELENGTH_ASCII],lname[LFN_NAMELENGTH+1];
|
||||
Bit32u size;Bit16u time,date;Bit8u attr;
|
||||
DOS_DTA dta(dos.dta());
|
||||
while (res) {
|
||||
dta.GetResult(name,size,date,time,attr);
|
||||
dta.GetResult(name,lname,size,date,time,attr);
|
||||
if (!(attr & (DOS_ATTR_DIRECTORY|DOS_ATTR_READ_ONLY))) {
|
||||
strcpy(end,name);
|
||||
if (!DOS_UnlinkFile(full)) WriteOut(MSG_Get("SHELL_CMD_DEL_ERROR"),full);
|
||||
strcpy(sfull,full);
|
||||
if (uselfn) sprintf(sfull,"\"%s\"",full);
|
||||
if (!DOS_UnlinkFile(sfull)) WriteOut(MSG_Get("SHELL_CMD_DEL_ERROR"),full);
|
||||
}
|
||||
res=DOS_FindNext();
|
||||
}
|
||||
@ -454,7 +462,7 @@ void DOS_Shell::CMD_RENAME(char * args){
|
||||
StripSpaces(args);
|
||||
if (!*args) {SyntaxError();return;}
|
||||
if ((strchr(args,'*')!=NULL) || (strchr(args,'?')!=NULL) ) { WriteOut(MSG_Get("SHELL_CMD_NO_WILD"));return;}
|
||||
char * arg1=StripWord(args);
|
||||
char * arg1=StripArg(args);
|
||||
StripSpaces(args);
|
||||
if (!*args) {SyntaxError();return;}
|
||||
char* slash = strrchr(arg1,'\\');
|
||||
@ -482,10 +490,12 @@ void DOS_Shell::CMD_RENAME(char * args){
|
||||
strcpy(target,dir_source);
|
||||
strncat(target,args,CROSS_LEN);
|
||||
|
||||
DOS_Rename(arg1,target);
|
||||
if (!DOS_Rename(arg1,args))
|
||||
WriteOut(MSG_Get("SHELL_CMD_RENAME_ERROR"),arg1);
|
||||
|
||||
} else {
|
||||
DOS_Rename(arg1,args);
|
||||
if (!DOS_Rename(arg1,args))
|
||||
WriteOut(MSG_Get("SHELL_CMD_RENAME_ERROR"),arg1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -526,15 +536,20 @@ void DOS_Shell::CMD_EXIT(char * args) {
|
||||
void DOS_Shell::CMD_CHDIR(char * args) {
|
||||
HELP("CHDIR");
|
||||
StripSpaces(args);
|
||||
char sargs[CROSS_LEN];
|
||||
if (*args && !DOS_GetSFNPath(args,sargs,false)) {
|
||||
WriteOut(MSG_Get("SHELL_ILLEGAL_PATH"));
|
||||
return;
|
||||
}
|
||||
Bit8u drive = DOS_GetDefaultDrive()+'A';
|
||||
char dir[DOS_PATHLENGTH];
|
||||
if (!*args) {
|
||||
DOS_GetCurrentDir(0,dir);
|
||||
DOS_GetCurrentDir(0,dir,true);
|
||||
WriteOut("%c:\\%s\n",drive,dir);
|
||||
} else if(strlen(args) == 2 && args[1]==':') {
|
||||
Bit8u targetdrive = (args[0] | 0x20)-'a' + 1;
|
||||
unsigned char targetdisplay = *reinterpret_cast<unsigned char*>(&args[0]);
|
||||
if(!DOS_GetCurrentDir(targetdrive,dir)) {
|
||||
if(!DOS_GetCurrentDir(targetdrive,dir,true)) { // verify that this should be true
|
||||
if(drive == 'Z') {
|
||||
WriteOut(MSG_Get("SHELL_EXECUTE_DRIVE_NOT_FOUND"),toupper(targetdisplay));
|
||||
} else {
|
||||
@ -545,7 +560,7 @@ void DOS_Shell::CMD_CHDIR(char * args) {
|
||||
WriteOut("%c:\\%s\n",toupper(targetdisplay),dir);
|
||||
if(drive == 'Z')
|
||||
WriteOut(MSG_Get("SHELL_CMD_CHDIR_HINT"),toupper(targetdisplay));
|
||||
} else if (!DOS_ChangeDir(args)) {
|
||||
} else if (!DOS_ChangeDir(sargs)) {
|
||||
/* Changedir failed. Check if the filename is longer then 8 and/or contains spaces */
|
||||
|
||||
std::string temps(args),slashpart;
|
||||
@ -554,8 +569,8 @@ void DOS_Shell::CMD_CHDIR(char * args) {
|
||||
slashpart = temps.substr(0,1);
|
||||
temps.erase(0,1);
|
||||
}
|
||||
separator = temps.find_first_of("\\/");
|
||||
if(separator != std::string::npos) temps.erase(separator);
|
||||
separator = temps.find_first_of("\"");
|
||||
if(separator != std::string::npos) temps.erase(separator);
|
||||
separator = temps.rfind('.');
|
||||
if(separator != std::string::npos) temps.erase(separator);
|
||||
separator = temps.find(' ');
|
||||
@ -564,10 +579,6 @@ void DOS_Shell::CMD_CHDIR(char * args) {
|
||||
if(temps.size() >6) temps.erase(6);
|
||||
temps += "~1";
|
||||
WriteOut(MSG_Get("SHELL_CMD_CHDIR_HINT_2"),temps.insert(0,slashpart).c_str());
|
||||
} else if (temps.size()>8) {
|
||||
temps.erase(6);
|
||||
temps += "~1";
|
||||
WriteOut(MSG_Get("SHELL_CMD_CHDIR_HINT_2"),temps.insert(0,slashpart).c_str());
|
||||
} else {
|
||||
if (drive == 'Z') {
|
||||
WriteOut(MSG_Get("SHELL_CMD_CHDIR_HINT_3"));
|
||||
@ -633,6 +644,7 @@ static void FormatNumber(Bit32u num,char * buf) {
|
||||
|
||||
struct DtaResult {
|
||||
char name[DOS_NAMELENGTH_ASCII];
|
||||
char lname[LFN_NAMELENGTH+1];
|
||||
Bit32u size;
|
||||
Bit16u date;
|
||||
Bit16u time;
|
||||
@ -659,6 +671,7 @@ void DOS_Shell::CMD_DIR(char * args) {
|
||||
HELP("DIR");
|
||||
char numformat[16];
|
||||
char path[DOS_PATHLENGTH];
|
||||
char sargs[CROSS_LEN];
|
||||
|
||||
std::string line;
|
||||
if(GetEnvStr("DIRCMD",line)){
|
||||
@ -741,10 +754,22 @@ void DOS_Shell::CMD_DIR(char * args) {
|
||||
}
|
||||
if (!strrchr(args,'*') && !strrchr(args,'?')) {
|
||||
Bit16u attribute=0;
|
||||
if(DOS_GetFileAttr(args,&attribute) && (attribute&DOS_ATTR_DIRECTORY) ) {
|
||||
if(!DOS_GetSFNPath(args,sargs,false)) {
|
||||
WriteOut(MSG_Get("SHELL_ILLEGAL_PATH"));
|
||||
return;
|
||||
}
|
||||
if(DOS_GetFileAttr(sargs,&attribute) && (attribute&DOS_ATTR_DIRECTORY) ) {
|
||||
DOS_FindFirst(sargs,0xffff & ~DOS_ATTR_VOLUME);
|
||||
DOS_DTA dta(dos.dta());
|
||||
strcpy(args,sargs);
|
||||
strcat(args,"\\*.*"); // if no wildcard and a directory, get its files
|
||||
}
|
||||
}
|
||||
if (!DOS_GetSFNPath(args,sargs,false)) {
|
||||
WriteOut(MSG_Get("SHELL_ILLEGAL_PATH"));
|
||||
return;
|
||||
}
|
||||
sprintf(args,"\"%s\"",sargs);
|
||||
if (!strrchr(args,'.')) {
|
||||
strcat(args,".*"); // if no extension, get them all
|
||||
}
|
||||
@ -755,10 +780,12 @@ void DOS_Shell::CMD_DIR(char * args) {
|
||||
return;
|
||||
}
|
||||
*(strrchr(path,'\\')+1)=0;
|
||||
if (!optB) {
|
||||
CMD_VOL(empty_string);
|
||||
WriteOut(MSG_Get("SHELL_CMD_DIR_INTRO"),path);
|
||||
if (!DOS_GetSFNPath(path,sargs,true)) {
|
||||
WriteOut(MSG_Get("SHELL_ILLEGAL_PATH"));
|
||||
return;
|
||||
}
|
||||
if (*(sargs+strlen(sargs)-1) != '\\') strcat(sargs,"\\");
|
||||
if (!optB) WriteOut(MSG_Get("SHELL_CMD_DIR_INTRO"),sargs);
|
||||
|
||||
/* Command uses dta so set it to our internal dta */
|
||||
RealPt save_dta=dos.dta();
|
||||
@ -783,7 +810,7 @@ void DOS_Shell::CMD_DIR(char * args) {
|
||||
|
||||
do { /* File name and extension */
|
||||
DtaResult result;
|
||||
dta.GetResult(result.name,result.size,result.date,result.time,result.attr);
|
||||
dta.GetResult(result.name,result.lname,result.size,result.date,result.time,result.attr);
|
||||
|
||||
/* Skip non-directories if option AD is present, or skip dirs in case of A-D */
|
||||
if(optAD && !(result.attr&DOS_ATTR_DIRECTORY) ) continue;
|
||||
@ -813,6 +840,7 @@ void DOS_Shell::CMD_DIR(char * args) {
|
||||
for (std::vector<DtaResult>::iterator iter = results.begin(); iter != results.end(); ++iter) {
|
||||
|
||||
char * name = iter->name;
|
||||
char *lname = iter->lname;
|
||||
Bit32u size = iter->size;
|
||||
Bit16u date = iter->date;
|
||||
Bit16u time = iter->time;
|
||||
@ -821,8 +849,8 @@ void DOS_Shell::CMD_DIR(char * args) {
|
||||
/* output the file */
|
||||
if (optB) {
|
||||
// this overrides pretty much everything
|
||||
if (strcmp(".",name) && strcmp("..",name)) {
|
||||
WriteOut("%s\n",name);
|
||||
if (strcmp(".",uselfn?lname:name) && strcmp("..",uselfn?lname:name)) {
|
||||
WriteOut("%s\n",uselfn?lname:name);
|
||||
}
|
||||
} else {
|
||||
char * ext = empty_string;
|
||||
@ -845,7 +873,7 @@ void DOS_Shell::CMD_DIR(char * args) {
|
||||
for (size_t i=14-namelen;i>0;i--) WriteOut(" ");
|
||||
}
|
||||
} else {
|
||||
WriteOut("%-8s %-3s %-16s %02d-%02d-%04d %2d:%02d\n",name,ext,"<DIR>",day,month,year,hour,minute);
|
||||
WriteOut("%-8s %-3s %-16s %02d-%02d-%04d %2d:%02d %s\n",name,ext,"<DIR>",day,month,year,hour,minute,uselfn?lname:"");
|
||||
}
|
||||
dir_count++;
|
||||
} else {
|
||||
@ -853,7 +881,7 @@ void DOS_Shell::CMD_DIR(char * args) {
|
||||
WriteOut("%-16s",name);
|
||||
} else {
|
||||
FormatNumber(size,numformat);
|
||||
WriteOut("%-8s %-3s %16s %02d-%02d-%04d %2d:%02d\n",name,ext,numformat,day,month,year,hour,minute);
|
||||
WriteOut("%-8s %-3s %16s %02d-%02d-%04d %2d:%02d %s\n",name,ext,numformat,day,month,year,hour,minute,uselfn?lname:"");
|
||||
}
|
||||
file_count++;
|
||||
byte_count+=size;
|
||||
@ -907,7 +935,7 @@ void DOS_Shell::CMD_COPY(char * args) {
|
||||
dos.dta(dos.tables.tempdta);
|
||||
DOS_DTA dta(dos.dta());
|
||||
Bit32u size;Bit16u date;Bit16u time;Bit8u attr;
|
||||
char name[DOS_NAMELENGTH_ASCII];
|
||||
char name[DOS_NAMELENGTH_ASCII], lname[LFN_NAMELENGTH+1];
|
||||
std::vector<copysource> sources;
|
||||
// ignore /b and /t switches: always copy binary
|
||||
while(ScanCMDBool(args,"B")) ;
|
||||
@ -926,9 +954,10 @@ void DOS_Shell::CMD_COPY(char * args) {
|
||||
// Gather all sources (extension to copy more then 1 file specified at command line)
|
||||
// Concatenating files go as follows: All parts except for the last bear the concat flag.
|
||||
// This construction allows them to be counted (only the non concat set)
|
||||
char q[]="\"";
|
||||
char* source_p = NULL;
|
||||
char source_x[DOS_PATHLENGTH+CROSS_LEN];
|
||||
while ( (source_p = StripWord(args)) && *source_p ) {
|
||||
while ( (source_p = StripArg(args)) && *source_p ) {
|
||||
do {
|
||||
char* plus = strchr(source_p,'+');
|
||||
// If StripWord() previously cut at a space before a plus then
|
||||
@ -947,8 +976,9 @@ void DOS_Shell::CMD_COPY(char * args) {
|
||||
if (source_x[source_x_len-1]==':') has_drive_spec = true;
|
||||
}
|
||||
if (!has_drive_spec && !strpbrk(source_p,"*?") ) { //doubt that fu*\*.* is valid
|
||||
if (DOS_FindFirst(source_p,0xffff & ~DOS_ATTR_VOLUME)) {
|
||||
dta.GetResult(name,size,date,time,attr);
|
||||
char spath[DOS_PATHLENGTH];
|
||||
if (DOS_GetSFNPath(source_p,spath,false) && DOS_FindFirst(spath,0xffff & ~DOS_ATTR_VOLUME)) {
|
||||
dta.GetResult(name,lname,size,date,time,attr);
|
||||
if (attr & DOS_ATTR_DIRECTORY)
|
||||
strcat(source_x,"\\*.*");
|
||||
}
|
||||
@ -991,14 +1021,16 @@ void DOS_Shell::CMD_COPY(char * args) {
|
||||
}
|
||||
|
||||
/* Make a full path in the args */
|
||||
char pathSource[DOS_PATHLENGTH];
|
||||
char pathSourcePre[DOS_PATHLENGTH], pathSource[DOS_PATHLENGTH+2];
|
||||
char pathTarget[DOS_PATHLENGTH];
|
||||
|
||||
if (!DOS_Canonicalize(const_cast<char*>(source.filename.c_str()),pathSource)) {
|
||||
if (!DOS_Canonicalize(const_cast<char*>(source.filename.c_str()),pathSourcePre)) {
|
||||
WriteOut(MSG_Get("SHELL_ILLEGAL_PATH"));
|
||||
dos.dta(save_dta);
|
||||
return;
|
||||
}
|
||||
strcpy(pathSource,pathSourcePre);
|
||||
if (uselfn) sprintf(pathSource,"\"%s\"",pathSourcePre);
|
||||
// cut search pattern
|
||||
char* pos = strrchr(pathSource,'\\');
|
||||
if (pos) *(pos+1) = 0;
|
||||
@ -1015,7 +1047,7 @@ void DOS_Shell::CMD_COPY(char * args) {
|
||||
bool target_is_file = true;
|
||||
if (pathTarget[strlen(pathTarget)-1]!='\\') {
|
||||
if (DOS_FindFirst(pathTarget,0xffff & ~DOS_ATTR_VOLUME)) {
|
||||
dta.GetResult(name,size,date,time,attr);
|
||||
dta.GetResult(name,lname,size,date,time,attr);
|
||||
if (attr & DOS_ATTR_DIRECTORY) {
|
||||
strcat(pathTarget,"\\");
|
||||
target_is_file = false;
|
||||
@ -1024,7 +1056,8 @@ void DOS_Shell::CMD_COPY(char * args) {
|
||||
} else target_is_file = false;
|
||||
|
||||
//Find first sourcefile
|
||||
bool ret = DOS_FindFirst(const_cast<char*>(source.filename.c_str()),0xffff & ~DOS_ATTR_VOLUME);
|
||||
char sPath[DOS_PATHLENGTH];
|
||||
bool ret = DOS_GetSFNPath(source.filename.c_str(),sPath,false) && DOS_FindFirst(const_cast<char*>(sPath),0xffff & ~DOS_ATTR_VOLUME);
|
||||
if (!ret) {
|
||||
WriteOut(MSG_Get("SHELL_CMD_FILE_NOT_FOUND"),const_cast<char*>(source.filename.c_str()));
|
||||
dos.dta(save_dta);
|
||||
@ -1052,6 +1085,7 @@ void DOS_Shell::CMD_COPY(char * args) {
|
||||
if (ext[-2] != '\\') {
|
||||
// there is something before the asterisk
|
||||
// save the offset in the source names
|
||||
|
||||
replacementOffset = source.filename.find('*');
|
||||
size_t lastSlash = source.filename.rfind('\\');
|
||||
if (std::string::npos == lastSlash)
|
||||
@ -1081,13 +1115,14 @@ void DOS_Shell::CMD_COPY(char * args) {
|
||||
|
||||
bool second_file_of_current_source = false;
|
||||
while (ret) {
|
||||
dta.GetResult(name,size,date,time,attr);
|
||||
dta.GetResult(name,lname,size,date,time,attr);
|
||||
|
||||
if ((attr & DOS_ATTR_DIRECTORY)==0) {
|
||||
Bit16u ftime,fdate;
|
||||
|
||||
strcpy(nameSource,pathSource);
|
||||
strcat(nameSource,name);
|
||||
|
||||
// Open Source
|
||||
if (DOS_OpenFile(nameSource,0,&sourceHandle)) {
|
||||
// record the file date/time
|
||||
@ -1095,19 +1130,21 @@ void DOS_Shell::CMD_COPY(char * args) {
|
||||
if (!ftdvalid) LOG_MSG("WARNING: COPY cannot obtain file date/time");
|
||||
|
||||
// Create Target or open it if in concat mode
|
||||
strcpy(nameTarget,pathTarget);
|
||||
strcpy(nameTarget,q);
|
||||
strcat(nameTarget,pathTarget);
|
||||
|
||||
if (ext) { // substitute parts if necessary
|
||||
if (!ext[-1]) { // substitute extension
|
||||
strcat(nameTarget, name + replacementOffset);
|
||||
strcat(nameTarget, (uselfn?lname:name) + replacementOffset);
|
||||
strcpy(strchr(nameTarget, '.'), ext);
|
||||
}
|
||||
if (ext[1] == '*') { // substitute name (so just add the extension)
|
||||
strcat(nameTarget, strchr(name, '.'));
|
||||
strcat(nameTarget, strchr(uselfn?lname:name, '.'));
|
||||
}
|
||||
}
|
||||
|
||||
if (nameTarget[pathTargetLen-1]=='\\') strcat(nameTarget,name);
|
||||
if (nameTarget[strlen(nameTarget)-1]=='\\') strcat(nameTarget,uselfn?lname:name);
|
||||
strcat(nameTarget,q);
|
||||
|
||||
//Special variable to ensure that copy * a_file, where a_file is not a directory concats.
|
||||
bool special = second_file_of_current_source && target_is_file;
|
||||
@ -1133,7 +1170,10 @@ void DOS_Shell::CMD_COPY(char * args) {
|
||||
} while (toread==0x8000);
|
||||
failed |= DOS_CloseFile(sourceHandle);
|
||||
failed |= DOS_CloseFile(targetHandle);
|
||||
WriteOut(" %s\n",name);
|
||||
if (strcmp(name,lname)&&uselfn)
|
||||
WriteOut(" %s [%s]\n",lname,name);
|
||||
else
|
||||
WriteOut(" %s\n",uselfn?lname:name);
|
||||
if(!source.concat && !special) count++; //Only count concat files once
|
||||
} else {
|
||||
DOS_CloseFile(sourceHandle);
|
||||
@ -1153,6 +1193,7 @@ void DOS_Shell::CMD_COPY(char * args) {
|
||||
|
||||
WriteOut(MSG_Get("SHELL_CMD_COPY_SUCCESS"),count);
|
||||
dos.dta(save_dta);
|
||||
Drives[DOS_GetDefaultDrive()]->EmptyCache();
|
||||
}
|
||||
|
||||
/* NTS: WARNING, this function modifies the buffer pointed to by char *args */
|
||||
@ -1240,7 +1281,7 @@ void DOS_Shell::CMD_IF(char * args) {
|
||||
if(strncasecmp(args,"EXIST ",6) == 0) {
|
||||
args += 6; //Skip text
|
||||
StripSpaces(args);
|
||||
char* word = StripWord(args);
|
||||
char* word = StripArg(args);
|
||||
if (!*word) {
|
||||
WriteOut(MSG_Get("SHELL_CMD_IF_EXIST_MISSING_FILENAME"));
|
||||
return;
|
||||
@ -1332,7 +1373,7 @@ void DOS_Shell::CMD_TYPE(char * args) {
|
||||
Bit16u handle;
|
||||
char * word;
|
||||
nextfile:
|
||||
word=StripWord(args);
|
||||
word=StripArg(args);
|
||||
if (!DOS_OpenFile(word,0,&handle)) {
|
||||
WriteOut(MSG_Get("SHELL_CMD_FILE_NOT_FOUND"),word);
|
||||
return;
|
||||
@ -1375,7 +1416,7 @@ void DOS_Shell::CMD_MORE(char * args) {
|
||||
Bit16u handle;
|
||||
char * word;
|
||||
nextfile:
|
||||
word=StripWord(args);
|
||||
word=StripArg(args);
|
||||
if (!DOS_OpenFile(word,0,&handle)) {
|
||||
WriteOut(MSG_Get("SHELL_CMD_FILE_NOT_FOUND"),word);
|
||||
return;
|
||||
@ -1581,8 +1622,11 @@ void DOS_Shell::CMD_SUBST (char * args) {
|
||||
strcat(mountstring,temp_str);
|
||||
strcat(mountstring," ");
|
||||
|
||||
Bit8u drive;char fulldir[DOS_PATHLENGTH];
|
||||
if (!DOS_MakeName(const_cast<char*>(arg.c_str()),fulldir,&drive)) throw 0;
|
||||
Bit8u drive;char dir[DOS_PATHLENGTH+2],fulldir[DOS_PATHLENGTH];
|
||||
if (strchr(arg.c_str(),'\"')==NULL)
|
||||
sprintf(dir,"\"%s\"",arg.c_str());
|
||||
else strcpy(dir,arg.c_str());
|
||||
if (!DOS_MakeName(dir,fulldir,&drive)) throw 0;
|
||||
|
||||
localDrive* ldp=0;
|
||||
if( ( ldp=dynamic_cast<localDrive*>(Drives[drive])) == 0 ) throw 0;
|
||||
|
@ -44,7 +44,7 @@
|
||||
void DOS_Shell::ShowPrompt(void) {
|
||||
char dir[DOS_PATHLENGTH];
|
||||
dir[0] = 0; //DOS_GetCurrentDir doesn't always return something. (if drive is messed up)
|
||||
DOS_GetCurrentDir(0,dir);
|
||||
DOS_GetCurrentDir(0,dir,uselfn);
|
||||
std::string line;
|
||||
const char * promptstr = "\0";
|
||||
|
||||
@ -467,9 +467,36 @@ void DOS_Shell::InputCommand(char * line) {
|
||||
// build new completion list
|
||||
// Lines starting with CD will only get directories in the list
|
||||
bool dir_only = (strncasecmp(line,"CD ",3)==0);
|
||||
int q=0, r=0, k=0;
|
||||
|
||||
// get completion mask
|
||||
char *p_completion_start = strrchr(line, ' ');
|
||||
while (p_completion_start) {
|
||||
q=0;
|
||||
char *i;
|
||||
for (i=line;i<p_completion_start;i++)
|
||||
if (*i=='\"') q++;
|
||||
if (q/2*2==q) break;
|
||||
*i=0;
|
||||
p_completion_start = strrchr(line, ' ');
|
||||
*i=' ';
|
||||
}
|
||||
char c[]={'<','>','|'};
|
||||
for (int j=0; j<sizeof(c); j++) {
|
||||
char *sp = strrchr(line, c[j]);
|
||||
while (sp) {
|
||||
q=0;
|
||||
char *i;
|
||||
for (i=line;i<sp;i++)
|
||||
if (*i=='\"') q++;
|
||||
if (q/2*2==q) break;
|
||||
*i=0;
|
||||
sp = strrchr(line, c[j]);
|
||||
*i=c[j];
|
||||
}
|
||||
if (!p_completion_start || p_completion_start<sp)
|
||||
p_completion_start = sp;
|
||||
}
|
||||
|
||||
if (p_completion_start) {
|
||||
p_completion_start ++;
|
||||
@ -478,13 +505,15 @@ void DOS_Shell::InputCommand(char * line) {
|
||||
p_completion_start = line;
|
||||
completion_index = 0;
|
||||
}
|
||||
k=completion_index;
|
||||
|
||||
char *path;
|
||||
if ((path = strrchr(line+completion_index,':'))) completion_index = (Bit16u)(path-line+1);
|
||||
if ((path = strrchr(line+completion_index,'\\'))) completion_index = (Bit16u)(path-line+1);
|
||||
if ((path = strrchr(line+completion_index,'/'))) completion_index = (Bit16u)(path-line+1);
|
||||
|
||||
// build the completion list
|
||||
char mask[DOS_PATHLENGTH] = {0};
|
||||
char mask[DOS_PATHLENGTH+2] = {0}, smask[DOS_PATHLENGTH] = {0};
|
||||
if (p_completion_start && strlen(p_completion_start) + 3 >= DOS_PATHLENGTH) {
|
||||
//Beep;
|
||||
break;
|
||||
@ -505,31 +534,50 @@ void DOS_Shell::InputCommand(char * line) {
|
||||
|
||||
RealPt save_dta=dos.dta();
|
||||
dos.dta(dos.tables.tempdta);
|
||||
|
||||
bool res = DOS_FindFirst(mask, 0xffff & ~DOS_ATTR_VOLUME);
|
||||
|
||||
bool res = false;
|
||||
if (DOS_GetSFNPath(mask,smask,false)) {
|
||||
sprintf(mask,"\"%s\"",smask);
|
||||
res = DOS_FindFirst(mask, 0xffff & ~DOS_ATTR_VOLUME);
|
||||
}
|
||||
if (!res) {
|
||||
dos.dta(save_dta);
|
||||
break; // TODO: beep
|
||||
}
|
||||
|
||||
DOS_DTA dta(dos.dta());
|
||||
char name[DOS_NAMELENGTH_ASCII];Bit32u sz;Bit16u date;Bit16u time;Bit8u att;
|
||||
char name[DOS_NAMELENGTH_ASCII], lname[LFN_NAMELENGTH], qlname[LFN_NAMELENGTH+2];
|
||||
Bit32u sz;Bit16u date;Bit16u time;Bit8u att;
|
||||
|
||||
std::list<std::string> executable;
|
||||
q=0;r=0;
|
||||
while (*p_completion_start) {
|
||||
k++;
|
||||
if (*p_completion_start++=='\"') {
|
||||
if (k<=completion_index)
|
||||
q++;
|
||||
else
|
||||
r++;
|
||||
}
|
||||
}
|
||||
while (res) {
|
||||
dta.GetResult(name,sz,date,time,att);
|
||||
dta.GetResult(name,lname,sz,date,time,att);
|
||||
if (strchr(uselfn?lname:name,' ')!=NULL&&q/2*2==q||r)
|
||||
sprintf(qlname,q/2*2!=q?"%s\"":"\"%s\"",uselfn?lname:name);
|
||||
else
|
||||
strcpy(qlname,uselfn?lname:name);
|
||||
// add result to completion list
|
||||
|
||||
if (strcmp(name, ".") && strcmp(name, "..")) {
|
||||
if (dir_only) { //Handle the dir only case different (line starts with cd)
|
||||
if(att & DOS_ATTR_DIRECTORY) l_completion.push_back(name);
|
||||
if(att & DOS_ATTR_DIRECTORY) l_completion.push_back(qlname);
|
||||
} else {
|
||||
char *ext = strrchr(name, '.'); // file extension
|
||||
if (ext && (strcmp(ext, ".BAT") == 0 || strcmp(ext, ".COM") == 0 || strcmp(ext, ".EXE") == 0))
|
||||
// we add executables to the a seperate list and place that list infront of the normal files
|
||||
executable.push_front(name);
|
||||
executable.push_front(qlname);
|
||||
else
|
||||
l_completion.push_back(name);
|
||||
l_completion.push_back(qlname);
|
||||
}
|
||||
}
|
||||
res=DOS_FindNext();
|
||||
@ -939,13 +987,13 @@ continue_1:
|
||||
/* Fill the command line */
|
||||
CommandTail cmdtail;
|
||||
cmdtail.count = 0;
|
||||
memset(&cmdtail.buffer,0,127); //Else some part of the string is unitialized (valgrind)
|
||||
if (strlen(line)>126) line[126]=0;
|
||||
memset(&cmdtail.buffer,0,CTBUF); //Else some part of the string is unitialized (valgrind)
|
||||
if (strlen(line)>=CTBUF) line[CTBUF-1]=0;
|
||||
cmdtail.count=(Bit8u)strlen(line);
|
||||
memcpy(cmdtail.buffer,line,strlen(line));
|
||||
cmdtail.buffer[strlen(line)]=0xd;
|
||||
/* Copy command line in stack block too */
|
||||
MEM_BlockWrite(SegPhys(ss)+reg_sp+0x100,&cmdtail,128);
|
||||
MEM_BlockWrite(SegPhys(ss)+reg_sp+0x100,&cmdtail,CTBUF+1);
|
||||
|
||||
/* Split input line up into parameters, using a few special rules, most notable the one for /AAA => A\0AA
|
||||
* Qbix: It is extremly messy, but this was the only way I could get things like /:aa and :/aa to work correctly */
|
||||
@ -1031,6 +1079,8 @@ char * DOS_Shell::Which(char * name) {
|
||||
/* Parse through the Path to find the correct entry */
|
||||
/* Check if name is already ok but just misses an extension */
|
||||
|
||||
if (DOS_FileExists(name)) return name;
|
||||
upcase(name);
|
||||
if (DOS_FileExists(name)) return name;
|
||||
/* try to find .com .exe .bat */
|
||||
strcpy(which_ret,name);
|
||||
|
Loading…
x
Reference in New Issue
Block a user