📄 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_STRINGSstatic 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 + -