📄 dosfns.c
字号:
0000 0010 replace O_TRUNC
0001 0000 create new file O_CREAT
0001 0001 create if not exists, open if exists O_CREAT | O_OPEN
0001 0010 create O_CREAT | O_TRUNC
bits for flags (bits 11-8 are internal FreeDOS bits only)
15 O_FCB called from FCB open
14 O_SYNC commit for each write (not implemented yet)
13 O_NOCRIT do not invoke int23 (not implemented yet)
12 O_LARGEFILE allow files >= 2gb but < 4gb (not implemented yet)
11 O_LEGACY not called from int21/ah=6c: find right fn for redirector
10 O_CREAT if file does not exist, create it
9 O_TRUNC if file exists, truncate and open it \ not both
8 O_OPEN if file exists, open it /
7 O_NOINHERIT do not inherit handle on exec
6 \
5 - sharing modes
4 /
3 reserved
2 bits 2,1,0 = 100: RDONLY and do not modify file's last access time
(not implemented yet)
1 \ 0=O_RDONLY, 1=O_WRONLY,
0 / 2=O_RDWR, 3=O_EXECCASE (preserve case for redirector EXEC,
(not implemented yet))
*/
long DosOpenSft(char FAR * fname, unsigned flags, unsigned attrib)
{
COUNT sft_idx;
sft FAR *sftp;
struct dhdr FAR *dhp;
long result;
result = truename(fname, PriPathName, CDS_MODE_CHECK_DEV_PATH);
if (result < SUCCESS)
return result;
/* now get a free system file table entry */
if ((sftp = get_free_sft(&sft_idx)) == (sft FAR *) - 1)
return DE_TOOMANY;
fmemset(sftp, 0, sizeof(sft));
sftp->sft_psp = cu_psp;
sftp->sft_mode = flags & 0xf0ff;
OpenMode = (BYTE) flags;
sftp->sft_shroff = -1; /* /// Added for SHARE - Ron Cemer */
sftp->sft_attrib = attrib = attrib | D_ARCHIVE;
if (result & IS_NETWORK)
{
int status;
unsigned cmd;
if ((flags & (O_TRUNC | O_CREAT)) == O_CREAT)
attrib |= 0x100;
lpCurSft = sftp;
cmd = REM_CREATE;
if (!(flags & O_LEGACY))
{
extern UWORD ASM ext_open_mode, ASM ext_open_attrib, ASM ext_open_action;
ext_open_mode = flags & 0x70ff;
ext_open_attrib = attrib & 0xff;
ext_open_action = ((flags & 0x0300) >> 8) | ((flags & O_CREAT) >> 6);
cmd = REM_EXTOC;
}
else if (!(flags & O_CREAT))
{
cmd = REM_OPEN;
attrib = (BYTE)flags;
}
status = (int)network_redirector_mx(cmd, sftp, (void *)attrib);
if (status >= SUCCESS)
{
if (sftp->sft_count == 0)
sftp->sft_count++;
return sft_idx | ((long)status << 16);
}
return status;
}
/* check for a device */
if ((result & IS_DEVICE) && (dhp = IsDevice(fname)) != NULL)
{
int rc = DeviceOpenSft(dhp, sftp);
/* check the status code returned by the
* driver when we tried to open it
*/
if (rc < SUCCESS)
return rc;
return sft_idx;
}
/* /// Added for SHARE. - Ron Cemer */
if (IsShareInstalled())
{
if ((sftp->sft_shroff =
share_open_check(PriPathName, cu_psp,
flags & 0x03, (flags >> 4) & 0x07)) < 0)
return sftp->sft_shroff;
}
/* /// End of additions for SHARE. - Ron Cemer */
/* NEVER EVER allow directories to be created */
/* ... though FCB's are weird :) */
if (!(flags & O_FCB) &&
(attrib & ~(D_RDONLY | D_HIDDEN | D_SYSTEM | D_ARCHIVE | D_VOLID)))
return DE_ACCESS;
result = dos_open(PriPathName, flags, attrib);
if (result >= 0)
{
int status = (int)(result >> 16);
if (status == S_OPENED)
{
sftp->sft_attrib = dos_getfattr_fd((COUNT)result);
/* Check permissions. -- JPP
(do not allow to open volume labels/directories) */
if (sftp->sft_attrib & (D_DIR | D_VOLID))
{
dos_close((COUNT)result);
return DE_ACCESS;
}
sftp->sft_size = dos_getfsize((COUNT)result);
}
sftp->sft_status = (COUNT)result;
sftp->sft_flags = PriPathName[0] - 'A';
sftp->sft_count += 1;
DosGetFile(PriPathName, sftp->sft_name);
dos_getftime(sftp->sft_status,
(date FAR *) & sftp->sft_date,
(time FAR *) & sftp->sft_time);
return sft_idx | ((long)status << 16);
}
else
{
/* /// Added for SHARE *** CURLY BRACES ADDED ALSO!!! ***. - Ron Cemer */
if (IsShareInstalled())
{
share_close_file(sftp->sft_shroff);
sftp->sft_shroff = -1;
}
/* /// End of additions for SHARE. - Ron Cemer */
return result;
}
}
long DosOpen(char FAR * fname, unsigned mode, unsigned attrib)
{
long result;
unsigned hndl;
/* test if mode is in range */
if ((mode & ~O_VALIDMASK) != 0)
return DE_INVLDACC;
/* get a free handle */
if ((result = get_free_hndl()) < 0)
return result;
hndl = (unsigned)result;
result = DosOpenSft(fname, mode, attrib);
if (result < SUCCESS)
return result;
((psp FAR *)MK_FP(cu_psp, 0))->ps_filetab[hndl] = (UBYTE)result;
return hndl | (result & 0xffff0000l);
}
COUNT CloneHandle(unsigned hndl)
{
/* now get the system file table entry */
sft FAR *sftp = get_sft(hndl);
if (sftp == (sft FAR *) -1 || (sftp->sft_mode & O_NOINHERIT))
return DE_INVLDHNDL;
/* now that we have the system file table entry, get the fnode */
/* index, and increment the count, so that we've effectively */
/* cloned the file. */
sftp->sft_count += 1;
return SUCCESS;
}
long DosDup(unsigned Handle)
{
long NewHandle;
if ((NewHandle = get_free_hndl()) < 0)
return NewHandle;
if (DosForceDup(Handle, (unsigned)NewHandle) < 0)
return DE_INVLDHNDL;
else
return NewHandle;
}
COUNT DosForceDup(unsigned OldHandle, unsigned NewHandle)
{
psp FAR *p = MK_FP(cu_psp, 0);
sft FAR *Sftp;
/* Get the SFT block that contains the SFT */
if ((Sftp = get_sft(OldHandle)) == (sft FAR *) - 1)
return DE_INVLDHNDL;
/* now close the new handle if it's open */
if ((UBYTE) p->ps_filetab[NewHandle] != 0xff)
{
COUNT ret;
if ((ret = DosClose(NewHandle)) != SUCCESS)
return ret;
}
/* If everything looks ok, bump it up. */
if ((Sftp->sft_flags & (SFT_FDEVICE | SFT_FSHARED))
|| (Sftp->sft_status >= 0))
{
p->ps_filetab[NewHandle] = p->ps_filetab[OldHandle];
/* possible hazard: integer overflow ska*/
Sftp->sft_count += 1;
return SUCCESS;
}
else
return DE_INVLDHNDL;
}
COUNT DosCloseSft(int sft_idx, BOOL commitonly)
{
sft FAR *sftp = idx_to_sft(sft_idx);
if (FP_OFF(sftp) == (size_t) - 1)
return DE_INVLDHNDL;
lpCurSft = sftp;
/*
remote sub sft_count.
*/
if (sftp->sft_flags & SFT_FSHARED)
{
/* printf("closing SFT %d = %p\n",sft_idx,sftp); */
return network_redirector_fp(commitonly ? REM_FLUSH: REM_CLOSE, sftp);
}
/* now just drop the count if a device, else */
/* call file system handler */
if (!commitonly)
sftp->sft_count -= 1;
if (sftp->sft_flags & SFT_FDEVICE)
{
if (sftp->sft_dev->dh_attr & SFT_FOCRM)
{
/* if Open/Close/RM bit in driver's attribute is set
* then issue a Close request to the driver
*/
struct dhdr FAR *dev = sftp->sft_dev;
if (BinaryCharIO(&dev, 0, MK_FP(0x0000, 0x0000), C_CLOSE) != SUCCESS)
return DE_ACCESS;
}
return SUCCESS;
}
if (commitonly || sftp->sft_count > 0)
return dos_commit(sftp->sft_status);
/* /// Added for SHARE *** CURLY BRACES ADDED ALSO!!! ***. - Ron Cemer */
if (IsShareInstalled())
{
if (sftp->sft_shroff >= 0)
share_close_file(sftp->sft_shroff);
sftp->sft_shroff = -1;
}
/* /// End of additions for SHARE. - Ron Cemer */
return dos_close(sftp->sft_status);
}
COUNT DosClose(COUNT hndl)
{
psp FAR *p = MK_FP(cu_psp, 0);
COUNT ret;
/* Get the SFT block that contains the SFT */
ret = DosCloseSft(get_sft_idx(hndl), FALSE);
if (ret != DE_INVLDHNDL && ret != DE_ACCESS)
p->ps_filetab[hndl] = 0xff;
return ret;
}
BOOL DosGetFree(UBYTE drive, UWORD * spc, UWORD * navc,
UWORD * bps, UWORD * nc)
{
/* navc==NULL means: called from FatGetDrvData, fcbfns.c */
struct dpb FAR *dpbp;
struct cds FAR *cdsp;
COUNT rg[4];
/* next - "log" in the drive */
drive = (drive == 0 ? default_drive : drive - 1);
/* first check for valid drive */
*spc = -1;
cdsp = get_cds(drive);
if (cdsp == NULL)
return FALSE;
if (cdsp->cdsFlags & CDSNETWDRV)
{
if (remote_getfree(cdsp, rg) != SUCCESS)
return FALSE;
/* for int21/ah=1c:
Undoc DOS says, its not supported for
network drives. so it's probably OK */
/* some programs such as RHIDE want it though and
the redirector can provide all info
- Bart, 2002 Apr 1 */
if (navc != NULL)
{
*navc = (COUNT) rg[3];
*spc &= 0xff; /* zero out media ID byte */
}
*spc = (COUNT) rg[0];
*nc = (COUNT) rg[1];
*bps = (COUNT) rg[2];
return TRUE;
}
dpbp = cdsp->cdsDpb;
if (dpbp == NULL)
return FALSE;
if (navc == NULL)
{
/* hazard: no error checking! */
flush_buffers(dpbp->dpb_unit);
dpbp->dpb_flags = M_CHANGED;
}
if (media_check(dpbp) < 0)
return FALSE;
/* get the data available from dpb */
*spc = (dpbp->dpb_clsmask + 1);
*bps = dpbp->dpb_secsize;
/* now tell fs to give us free cluster */
/* count */
#ifdef WITHFAT32
if (ISFAT32(dpbp))
{
ULONG cluster_size, ntotal, nfree;
/* we shift ntotal until it is equal to or below 0xfff6 */
cluster_size = (ULONG) dpbp->dpb_secsize << dpbp->dpb_shftcnt;
ntotal = dpbp->dpb_xsize - 1;
if (navc != NULL)
nfree = dos_free(dpbp);
while (ntotal > FAT_MAGIC16 && cluster_size < 0x8000)
{
cluster_size <<= 1;
*spc <<= 1;
ntotal >>= 1;
nfree >>= 1;
}
/* get the data available from dpb */
*nc = ntotal > FAT_MAGIC16 ? FAT_MAGIC16 : (UCOUNT) ntotal;
/* now tell fs to give us free cluster */
/* count */
if (navc != NULL)
*navc = nfree > FAT_MAGIC16 ? FAT_MAGIC16 : (UCOUNT) nfree;
return TRUE;
}
#endif
/* a passed nc of 0xffff means: skip free; see FatGetDrvData
fcbfns.c */
if (*nc != 0xffff)
*navc = (COUNT) dos_free(dpbp);
*nc = dpbp->dpb_size - 1;
if (*spc > 64)
{
/* fake for 64k clusters do confuse some DOS programs, but let
others work without overflowing */
*spc >>= 1;
*navc = ((unsigned)*navc < FAT_MAGIC16 / 2) ? ((unsigned)*navc << 1) : FAT_MAGIC16;
*nc = ((unsigned)*nc < FAT_MAGIC16 / 2) ? ((unsigned)*nc << 1) : FAT_MAGIC16;
}
return TRUE;
}
#ifdef WITHFAT32
/* network names like \\SERVER\C aren't supported yet */
#define IS_SLASH(ch) (ch == '\\' || ch == '/')
COUNT DosGetExtFree(BYTE FAR * DriveString, struct xfreespace FAR * xfsp)
{
struct dpb FAR *dpbp;
struct cds FAR *cdsp;
UCOUNT rg[4];
if (IS_SLASH(DriveString[0]) || !IS_SLASH(DriveString[2])
|| DriveString[1] != ':')
return DE_INVLDDRV;
cdsp = get_cds(DosUpFChar(*DriveString) - 'A');
if (cdsp == NULL)
return DE_INVLDDRV;
if (cdsp->cdsFlags & CDSNETWDRV)
{
if (remote_getfree(cdsp, rg) != SUCCESS)
return DE_INVLDDRV;
xfsp->xfs_clussize = rg[0];
xfsp->xfs_totalclusters = rg[1];
xfsp->xfs_secsize = rg[2];
xfsp->xfs_freeclusters = rg[3];
}
else
{
dpbp = cdsp->cdsDpb;
if (dpbp == NULL || media_check(dpbp) < 0)
return DE_INVLDDRV;
xfsp->xfs_secsize = dpbp->dpb_secsize;
xfsp->xfs_totalclusters =
(ISFAT32(dpbp) ? dpbp->dpb_xsize : dpbp->dpb_size);
xfsp->xfs_freeclusters = dos_free(dpbp);
xfsp->xfs_clussize = dpbp->dpb_clsmask + 1;
}
xfsp->xfs_totalunits = xfsp->xfs_totalclusters;
xfsp->xfs_freeunits = xfsp->xfs_freeclusters;
xfsp->xfs_totalsectors = xfsp->xfs_totalclusters * xfsp->xfs_clussize;
xfsp->xfs_freesectors = xfsp->xfs_freeclusters * xfsp->xfs_clussize;
xfsp->xfs_datasize = sizeof(struct xfreespace);
fmemset(xfsp->xfs_reserved, 0, 8);
return SUCCESS;
}
#endif
COUNT DosGetCuDir(UBYTE drive, BYTE FAR * s)
{
BYTE *cp;
struct cds FAR *cdsp;
/* next - "log" in the drive */
/* first check for valid drive */
cdsp = get_cds(drive == 0 ? default_drive : drive - 1);
if (cdsp == NULL)
return DE_INVLDDRV;
fmemcpy(&TempCDS, cdsp, sizeof(TempCDS));
cp = TempCDS.cdsCurrentPath;
/* ensure termination of fstrcpy */
cp[MAX_CDSPATH - 1] = '\0';
if ((TempCDS.cdsFlags & CDSNETWDRV) == 0)
{
/* dos_cd ensures that the path exists; if not, we
need to change to the root directory */
int result = dos_cd(cp);
if (result == DE_PATHNOTFND)
cp[TempCDS.cdsBackslashOffset + 1] =
cdsp->cdsCurrentPath[TempCDS.cdsBackslashOffset + 1] = '\0';
else if (result < SUCCESS)
return result;
}
cp += TempCDS.cdsBackslashOffset;
if (*cp == '\0')
s[0] = '\0';
else
fstrcpy(s, cp + 1);
return SUCCESS;
}
#undef CHDIR_DEBUG
COUNT DosChangeDir(BYTE FAR * s)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -