📄 dosfns.c
字号:
{
COUNT result;
BYTE FAR *p;
/* don't do wildcard CHDIR --TE */
for (p = s; *p; p++)
if (*p == '*' || *p == '?')
return DE_PATHNOTFND;
result = truename(s, PriPathName, CDS_MODE_CHECK_DEV_PATH);
if (result < SUCCESS)
{
return result;
}
if ((FP_OFF(current_ldt) != 0xFFFF) &&
(strlen(PriPathName) >= sizeof(current_ldt->cdsCurrentPath)))
return DE_PATHNOTFND;
#if defined(CHDIR_DEBUG)
printf("Remote Chdir: n='%Fs' p='%Fs\n", s, PriPathName);
#endif
/* now get fs to change to new */
/* directory */
result = (result & IS_NETWORK ? network_redirector(REM_CHDIR) :
dos_cd(PriPathName));
#if defined(CHDIR_DEBUG)
printf("status = %04x, new_path='%Fs'\n", result, cdsd->cdsCurrentPath);
#endif
if (result != SUCCESS)
return result;
/*
Copy the path to the current directory
structure.
Some redirectors do not write back to the CDS.
SHSUCdX needs this. jt
*/
fstrcpy(current_ldt->cdsCurrentPath, PriPathName);
if (FP_OFF(current_ldt) != 0xFFFF)
{
fstrcpy(current_ldt->cdsCurrentPath, PriPathName);
if (PriPathName[7] == 0)
current_ldt->cdsCurrentPath[8] = 0; /* Need two Zeros at the end */
}
return SUCCESS;
}
STATIC VOID pop_dmp(dmatch FAR * dmp)
{
dmp->dm_attr_fnd = (BYTE) SearchDir.dir_attrib;
dmp->dm_time = SearchDir.dir_time;
dmp->dm_date = SearchDir.dir_date;
dmp->dm_size = (LONG) SearchDir.dir_size;
ConvertName83ToNameSZ(dmp->dm_name, (BYTE FAR *) SearchDir.dir_name);
}
COUNT DosFindFirst(UCOUNT attr, BYTE FAR * name)
{
int rc;
register dmatch FAR *dmp = dta;
rc = truename(name, PriPathName,
CDS_MODE_CHECK_DEV_PATH | CDS_MODE_ALLOW_WILDCARDS);
if (rc < SUCCESS)
return rc;
/* /// Added code here to do matching against device names.
DOS findfirst will match exact device names if the
filename portion (excluding the extension) contains
a valid device name.
Credits: some of this code was ripped off from truename()
in newstuff.c.
- Ron Cemer */
SAttr = (BYTE) attr;
#if defined(FIND_DEBUG)
printf("Remote Find: n='%Fs\n", PriPathName);
#endif
dta = &sda_tmp_dm;
memset(&sda_tmp_dm, 0, sizeof(dmatch)+sizeof(struct dirent));
if (rc & IS_NETWORK)
rc = network_redirector_fp(REM_FINDFIRST, current_ldt);
else if (rc & IS_DEVICE)
{
const char *p;
COUNT i;
/* Found a matching device. Hence there cannot be wildcards. */
SearchDir.dir_attrib = D_DEVICE;
SearchDir.dir_time = dos_gettime();
SearchDir.dir_date = dos_getdate();
p = (char *)FP_OFF(get_root(PriPathName));
memset(SearchDir.dir_name, ' ', FNAME_SIZE + FEXT_SIZE);
for (i = 0; i < FNAME_SIZE && *p && *p != '.'; i++)
SearchDir.dir_name[i] = *p++;
rc = SUCCESS;
/* /// End of additions. - Ron Cemer ; heavily edited - Bart Oldeman */
}
else
rc = dos_findfirst(attr, PriPathName);
dta = dmp;
if (rc == SUCCESS)
{
fmemcpy(dta, &sda_tmp_dm, 21);
pop_dmp(dmp);
}
return rc;
}
COUNT DosFindNext(void)
{
COUNT rc;
register dmatch FAR *dmp = dta;
/* findnext will always fail on a device name device name or volume id */
if (dmp->dm_attr_fnd & (D_DEVICE | D_VOLID))
return DE_NFILES;
/*
* The new version of SHSUCDX 1.0 looks at the dm_drive byte to
* test 40h. I used RamView to see location MSD 116:04be and
* FD f??:04be, the byte set with 0xc4 = Remote/Network drive 4.
* Ralf Brown docs for dos 4eh say bit 7 set == remote so what is
* bit 6 for?
* SHSUCDX Mod info say "test redir not network bit".
* Just to confuse the rest, MSCDEX sets bit 5 too.
*
* So, assume bit 6 is redirector and bit 7 is network.
* jt
* Bart: dm_drive can be the drive _letter_.
* but better just stay independent of it: we only use
* bit 7 to detect a network drive; the rest untouched.
* RBIL says that findnext can only return one error type anyway
* (12h, DE_NFILES)
*/
#if 0
printf("findnext: %d\n", dmp->dm_drive);
#endif
fmemcpy(&sda_tmp_dm, dmp, 21);
memset(&SearchDir, 0, sizeof(struct dirent));
dta = &sda_tmp_dm;
rc = (sda_tmp_dm.dm_drive & 0x80) ?
network_redirector_fp(REM_FINDNEXT, &sda_tmp_dm) : dos_findnext();
dta = dmp;
if (rc == SUCCESS)
{
fmemcpy(dmp, &sda_tmp_dm, 21);
pop_dmp(dmp);
}
return rc;
}
COUNT DosGetFtime(COUNT hndl, date * dp, time * tp)
{
sft FAR *s;
/*sfttbl FAR *sp;*/
/* Get the SFT block that contains the SFT */
if (FP_OFF(s = get_sft(hndl)) == (size_t) - 1)
return DE_INVLDHNDL;
/* If SFT entry refers to a device, return the date and time of opening */
if (s->sft_flags & (SFT_FDEVICE | SFT_FSHARED))
{
*dp = s->sft_date;
*tp = s->sft_time;
return SUCCESS;
}
/* call file system handler */
return dos_getftime(s->sft_status, dp, tp);
}
COUNT DosSetFtimeSft(int sft_idx, date dp, time tp)
{
/* Get the SFT block that contains the SFT */
sft FAR *s = idx_to_sft(sft_idx);
if (FP_OFF(s) == (size_t) - 1)
return DE_INVLDHNDL;
/* If SFT entry refers to a device, do nothing */
if (s->sft_flags & SFT_FDEVICE)
return SUCCESS;
s->sft_flags |= SFT_FDATE;
s->sft_date = dp;
s->sft_time = tp;
if (s->sft_flags & SFT_FSHARED)
return SUCCESS;
/* call file system handler */
return dos_setftime(s->sft_status, dp, tp);
}
COUNT DosGetFattr(BYTE FAR * name)
{
COUNT result;
result = truename(name, PriPathName, CDS_MODE_CHECK_DEV_PATH);
if (result < SUCCESS)
return result;
/* /// Added check for "d:\", which returns 0x10 (subdirectory) under DOS.
- Ron Cemer */
/* Theoretically: If the redirectory's qualify function
doesn't return nonsense this check can be reduced to
PriPathname[3] == 0, because local path names always
have the three-byte string ?:\ and UNC path shouldn't
validy consist of just two slashes.
-- 2001/09/03 ska*/
if (PriPathName[3] == '\0')
return 0x10;
if (result & IS_NETWORK)
return network_redirector(REM_GETATTRZ);
if (result & IS_DEVICE)
return DE_FILENOTFND;
/* /// Use truename()'s result, which we already have in PriPathName.
I copy it to tmp_name because PriPathName is global and seems
to get trashed somewhere in transit.
The reason for using truename()'s result is that dos_?etfattr()
are very low-level functions and don't handle full path expansion
or cleanup, such as converting "c:\a\b\.\c\.." to "C:\A\B".
- Ron Cemer
*/
/*
memcpy(SecPathName,PriPathName,sizeof(SecPathName));
return dos_getfattr(SecPathName, attrp);
*/
/* no longer true. dos_getfattr() is
A) intelligent (uses dos_open) anyway
B) there are some problems with MAX_PARSE, i.e. if PATH ~= 64
and TRUENAME adds a C:, which leeds to trouble.
the problem was discovered, when VC did something like
fd = DosOpen(filename,...)
jc can't_copy_dialog;
attr = DosGetAttrib(filename);
jc can't_copy_dialog;
and suddenly, the filehandle stays open
shit.
tom
*/
return dos_getfattr(PriPathName);
}
/* This function is almost identical to DosGetFattr().
Maybe it is nice to join both functions.
-- 2001/09/03 ska*/
COUNT DosSetFattr(BYTE FAR * name, UWORD attrp)
{
COUNT result;
result = truename(name, PriPathName, CDS_MODE_CHECK_DEV_PATH);
if (result < SUCCESS)
return result;
if (result & IS_NETWORK)
return remote_setfattr(attrp);
if (result & IS_DEVICE)
return DE_FILENOTFND;
/* /// Use truename()'s result, which we already have in PriPathName.
I copy it to tmp_name because PriPathName is global and seems
to get trashed somewhere in transit.
- Ron Cemer
*/
/*
memcpy(SecPathName,PriPathName,sizeof(SecPathName));
return dos_setfattr(SecPathName, attrp);
see DosGetAttr()
*/
return dos_setfattr(PriPathName, attrp);
}
UBYTE DosSelectDrv(UBYTE drv)
{
current_ldt = get_cds(drv);
if (current_ldt != NULL)
default_drive = drv;
return lastdrive;
}
COUNT DosDelete(BYTE FAR * path, int attrib)
{
COUNT result;
result = truename(path, PriPathName, CDS_MODE_CHECK_DEV_PATH);
if (result < SUCCESS)
return result;
if (result & IS_NETWORK)
return network_redirector(REM_DELETE);
if (result & IS_DEVICE)
return DE_FILENOTFND;
return dos_delete(PriPathName, attrib);
}
COUNT DosRenameTrue(BYTE * path1, BYTE * path2, int attrib)
{
if (path1[0] != path2[0])
{
return DE_DEVICE; /* not same device */
}
if (FP_OFF(current_ldt) == 0xFFFF || (current_ldt->cdsFlags & CDSNETWDRV))
return network_redirector(REM_RENAME);
return dos_rename(path1, path2, attrib);
}
COUNT DosRename(BYTE FAR * path1, BYTE FAR * path2)
{
COUNT result;
result = truename(path2, SecPathName, CDS_MODE_CHECK_DEV_PATH);
if (result < SUCCESS)
return result;
if ((result & (IS_NETWORK | IS_DEVICE)) == IS_DEVICE)
return DE_FILENOTFND;
result = truename(path1, PriPathName, CDS_MODE_CHECK_DEV_PATH);
if (result < SUCCESS)
return result;
if ((result & (IS_NETWORK | IS_DEVICE)) == IS_DEVICE)
return DE_FILENOTFND;
return DosRenameTrue(PriPathName, SecPathName, D_ALL);
}
COUNT DosMkRmdir(const char FAR * dir, int action)
{
COUNT result;
result = truename(dir, PriPathName, CDS_MODE_CHECK_DEV_PATH);
if (result < SUCCESS)
return result;
if (result & IS_NETWORK)
return network_redirector(action == 0x39 ? REM_MKDIR : REM_RMDIR);
if (result & IS_DEVICE)
return DE_ACCESS;
return (action == 0x39 ? dos_mkdir : dos_rmdir)(PriPathName);
}
/* /// Added for SHARE. - Ron Cemer */
COUNT DosLockUnlock(COUNT hndl, LONG pos, LONG len, COUNT unlock)
{
sft FAR *s;
/* Get the SFT block that contains the SFT */
if (FP_OFF(s = get_sft(hndl)) == (size_t) - 1)
return DE_INVLDHNDL;
if (s->sft_flags & SFT_FSHARED)
return remote_lock_unlock(s, pos, len, unlock);
/* Invalid function unless SHARE is installed or remote. */
if (!IsShareInstalled())
return DE_INVLDFUNC;
/* Lock violation if this SFT entry does not support locking. */
if (s->sft_shroff < 0)
return DE_LOCK;
/* Let SHARE do the work. */
return share_lock_unlock(cu_psp, s->sft_shroff, pos, len, unlock);
}
/* /// End of additions for SHARE. - Ron Cemer */
/*
* This seems to work well.
*/
/* check for a device */
struct dhdr FAR *IsDevice(const char FAR * fname)
{
struct dhdr FAR *dhp;
const char FAR *froot = get_root(fname);
int i;
/* /// BUG!!! This is absolutely wrong. A filename of "NUL.LST" must be
treated EXACTLY the same as a filename of "NUL". The existence or
content of the extension is irrelevent in determining whether a
filename refers to a device.
- Ron Cemer
// if we have an extension, can't be a device <--- WRONG.
if (*froot != '.')
{
*/
for (dhp = (struct dhdr FAR *)&nul_dev; dhp != (struct dhdr FAR *)-1;
dhp = dhp->dh_next)
{
/* BUGFIX: MSCD000<00> should be handled like MSCD000<20> TE */
for (i = 0; i < FNAME_SIZE; i++)
{
unsigned char c1 = (unsigned char)froot[i];
if (c1 == '.' || c1 == '\0')
{
/* check if remainder of device name consists of spaces or nulls */
for (; i < FNAME_SIZE; i++)
{
unsigned char c2 = dhp->dh_name[i];
if (c2 != ' ' && c2 != '\0')
break;
}
break;
}
if (DosUpFChar(c1) != DosUpFChar(dhp->dh_name[i]))
break;
}
if (i == FNAME_SIZE)
return dhp;
}
return NULL;
}
/* /// Added for SHARE. - Ron Cemer */
BOOL IsShareInstalled(void)
{
extern unsigned char ASMPASCAL share_check(void);
if (!share_installed && share_check() == 0xff)
share_installed = TRUE;
return share_installed;
}
/* /// End of additions for SHARE. - Ron Cemer */
COUNT DosTruename(const char FAR *src, char FAR *dest)
{
/* RBIL: The buffer has be unchanged, if the call fails.
Therefore, the name is created in an internal buffer
and copied into the user buffer only on success.
*/
COUNT rc = truename(src, PriPathName, CDS_MODE_ALLOW_WILDCARDS);
if (rc >= SUCCESS)
fstrcpy(dest, PriPathName);
return rc;
}
STATIC int remote_lock_unlock(sft FAR *sftp, /* SFT for file */
unsigned long ofs, /* offset into file */
unsigned long len, /* length (in bytes) of region to lock or unlock */
int unlock)
/* one to unlock; zero to lock */
{
struct
{
unsigned long ofs, len;
int unlock;
} param_block;
param_block.ofs = ofs;
param_block.len = len;
param_block.unlock = unlock;
return (int)network_redirector_mx(REM_LOCK, sftp, ¶m_block);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -