📄 newstuff.c
字号:
/****************************************************************/
/* */
/* newstuff.c */
/* DOS-C */
/* */
/* Copyright (c) 1996 */
/* Svante Frey */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/****************************************************************/
#ifdef VERSION_STRINGS
static BYTE *mainRcsId =
"$Id: newstuff.c,v 1.35 2004/05/23 20:06:51 bartoldeman Exp $";
#endif
#include "portab.h"
#include "globals.h"
/*
TE-TODO: if called repeatedly by same process,
last allocation must be freed. if handle count < 20, copy back to PSP
*/
int SetJFTSize(UWORD nHandles)
{
UWORD block, maxBlock, i;
psp FAR *ppsp = MK_FP(cu_psp, 0);
UBYTE FAR *newtab;
if (nHandles <= ppsp->ps_maxfiles)
{
ppsp->ps_maxfiles = nHandles;
return SUCCESS;
}
if ((DosMemAlloc
((nHandles + 0xf) >> 4, mem_access_mode, &block, &maxBlock)) < 0)
return DE_NOMEM;
++block;
newtab = MK_FP(block, 0);
i = ppsp->ps_maxfiles;
/* copy existing part and fill up new part by "no open file" */
fmemcpy(newtab, ppsp->ps_filetab, i);
fmemset(newtab + i, 0xff, nHandles - i);
ppsp->ps_maxfiles = nHandles;
ppsp->ps_filetab = newtab;
return SUCCESS;
}
long DosMkTmp(BYTE FAR * pathname, UWORD attr)
{
/* create filename from current date and time */
char FAR *ptmp;
unsigned long randvar;
long rc;
int loop;
ptmp = pathname + fstrlen(pathname);
if (ptmp == pathname || (ptmp[-1] != '\\' && ptmp[-1] != '/'))
*ptmp++ = '\\';
ptmp[8] = '\0';
randvar = ((unsigned long)dos_getdate() << 16) | dos_gettime();
loop = 0;
do {
unsigned long tmp = randvar++;
int i;
for(i = 7; i >= 0; tmp >>= 4, i--)
ptmp[i] = ((char)tmp & 0xf) + 'A';
/* DOS versions: > 5: characters A - P
< 5: hex digits */
if (os_major < 5)
for (i = 0; i < 8; i++)
ptmp[i] -= (ptmp[i] < 'A' + 10) ? '0' - 'A' : 10;
/* only create new file -- 2001/09/22 ska*/
rc = DosOpen(pathname, O_LEGACY | O_CREAT | O_RDWR, attr);
} while (rc == DE_FILEEXISTS && loop++ < 0xfff);
return rc;
}
#ifdef DEBUG
#define DEBUG_TRUENAME
#endif
#define drLetterToNr(dr) ((unsigned char)((dr) - 'A'))
/* Convert an uppercased drive letter into the drive index */
#define drNrToLetter(dr) ((dr) + 'A')
/* the other direction */
/* In DOS there are no free-standing UNC paths, therefore there
is always a logical drive letter associated with a path
spec. This letter is also the index into the CDS */
/*
Definition of functions for the handling of the Current
Directory Structure.
MUX-11-23: Qualify Remote Filename
DOS-0x60 calls this MUX functions to let the Network Redirector
qualify the filename. According INTRSPY MS DOS 6 does not pre-
process the passed in filename in any way (see attached transcripts).
The DOS-60 interface TRUENAME looks like this:
DosTruename(src, dest) {
if (MUX-11-23(src, dest) != Error)
return SUCCESS
return local_truename(src, dest);
}
The CDS has the following entries:
char cdsPath[CDSPATHLEN];
The fully-qualified current working directory of this drive.
The format is DOS <dr>:\[<path>{\<path>}]
or UNC \<id>\[<path>{\<path>}].
The drive <dr> indicates the physical drive letter and is the
index into the blk_device[].
UWORD cdsFlags;
Indicates what kind this logical drive is:
NETWORK: drive is NOT local \ If both are set, drive is IFS
PHYSICAL: drive is local / If none is set, drive is non-existant
JOIN: drive is joined in as the path cdsPath. This Flag uses the
index into the CDS table to indicate the physical drive.
SUBST: drive substitutes the path cdsPath.
HIDDEN: drive is not included into the redirector's list.
struct dpb FAR *cdsDpb;
Pointer to the DPB driving the physical drive. In DOS-C, the physical
drive letter is the index into the DPB[]. But for compatibly reason
this field will be set correctly.
UWORD cdsStartCluster;
For local drives only: This holds the cluster number of
the start of the current working directory of this
logical drive. If 0000h, it's the root directory; if
0ffffh, the drive was never accessed and has to be read
again.
void FAR *cdsIFSrecord;
UWORD cdsIFSparameter;
For networked drives only: Holds pointer/parameters to/for IFS
driver. (Well, I don't know.)
UWORD cdsPathOff;
Number of characters of the cdsPath[], which are hidden. The
logical path is combined by the logical drive letter and the
cdsPath[] part, which is not hidden.
IFS FAR *cdsIFSdrv;
Will be zeroed for local drives.
Revision 1.2 1995/12/03 22:17:41 ska
bugfix: Scanning of file name in 8.3 failed on "." and on longer names.
Revision 1.1 1995/11/09 07:43:30 ska
#
*/
#define PATH_ERROR goto errRet
#define PATHLEN 128
/* Map a logical path into a physical one.
1) Uppercasing path.
2) Flipping '/' -> '\\'.
3) Removing empty directory components & ".".
4) Processing ".." components.
5) Convert path components into 8.3 convention.
6) Make it fully-qualified.
7) Map it to SUBST/UNC.
8) Map to JOIN.
Return:
*cdsItem will be point to the appropriate CDS entry. This will allow
the caller to aquire the DPB or the IFS informtion of this entry.
error number
Return value:
DE_FILENOTFND, or DE_PATHNOTFND (as described in RBIL)
If the output path pnfo->physPath exceeds the length MAX_PATH, the error
DE_FILENOTFND will be returned.
*/
/*
* Added support for external and internal calls.
* Clean buffer before use. Make the true path and expand file names.
* Example: *.* -> ????????.??? as in the currect way.
* MSD returns \\D.\A.\????????.??? with SHSUCDX. So, this code is not
* compatible MSD Func 60h.
*/
/*TE TODO:
experimenting with NUL on MSDOS 7.0 (win95)
WIN95 FREEDOS
TRUENAME NUL C:/NUL OK
TRUENAME .\NUL C:\DOS\NUL
TRUENAME ..\NUL C:\NUL
TRUENAME ..\..\NUL path not found
TRUENAME Z:NUL invalid drive (not lastdrive!!)
TRUENAME A:NUL A:/NUL OK
TRUENAME A:\NUL A:\NUL
*/
#ifdef DEBUG_TRUENAME
#define tn_printf(x) printf x
#else
#define tn_printf(x)
#endif
#define PNE_WILDCARD 1
#define PNE_DOT 2
#define addChar(c) \
{ \
if (p >= dest + SFTMAX) PATH_ERROR; /* path too long */ \
*p++ = c; \
}
/* helper for truename: parses either name or extension */
STATIC int parse_name_ext(int i, const char FAR **src, char **cp, char *dest)
{
int retval = SUCCESS;
char *p = *cp;
char c;
while(1) switch(c=*(*src)++)
{
case '.':
retval |= PNE_DOT;
/* fall through */
case '/':
case '\\':
case '\0':
*cp = p;
return retval;
case '*':
retval |= PNE_WILDCARD;
/* register the wildcard, even if no '?' is appended */
if (i) do
{
addChar('?');
} while(--i);
/** Alternative implementation:
if (i)
{
if (dest + SFTMAX - *p < i)
PATH_ERROR;
fmemset(p, '?', i);
p += i;
} **/
break;
case '?':
retval |= PNE_WILDCARD;
/* fall through */
default:
if (i) { /* name length in limits */
--i;
addChar(c);
}
}
errRet:
return -1;
}
COUNT truename(const char FAR * src, char * dest, COUNT mode)
{
COUNT i;
struct dhdr FAR *dhp;
const char FAR *froot;
COUNT result;
int gotAnyWildcards = 0;
struct cds FAR *cdsEntry;
char *p = dest; /* dynamic pointer into dest */
char *rootPos;
char src0;
enum { DONT_ADD, ADD, ADD_UNLESS_LAST } addSep;
tn_printf(("truename(%S)\n", src));
/* First, adjust the source pointer */
src = adjust_far(src);
/* In opposite of the TRUENAME shell command, an empty string is
rejected by MS DOS 6 */
src0 = src[0];
if (src0 == '\0')
return DE_FILENOTFND;
if (src0 == '\\' && src[1] == '\\') {
const char FAR *unc_src = src;
/* Flag UNC paths and short circuit processing. Set current LDT */
/* to sentinel (offset 0xFFFF) for redirector processing. */
tn_printf(("Truename: UNC detected\n"));
do {
src0 = unc_src[0];
addChar(src0);
unc_src++;
} while (src0);
current_ldt = (struct cds FAR *)MK_FP(0xFFFF,0xFFFF);
tn_printf(("Returning path: \"%s\"\n", dest));
/* Flag as network - drive bits are empty but shouldn't get */
/* referenced for network with empty current_ldt. */
return IS_NETWORK;
}
/* Do we have a drive? */
if (src[1] == ':')
result = drLetterToNr(DosUpFChar(src0));
else
result = default_drive;
cdsEntry = get_cds(result);
if (cdsEntry == NULL)
return DE_PATHNOTFND;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -