fe51b7a036
git-svn-id: https://svn.code.sf.net/p/freedos/svn/kernel/trunk@326 6ac86273-5f31-0410-b378-82cca8765d1b
557 lines
17 KiB
C
557 lines
17 KiB
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$";
|
|
#endif
|
|
|
|
#include "portab.h"
|
|
#include "globals.h"
|
|
#include "proto.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;
|
|
psp FAR *ppsp = MK_FP(cu_psp, 0);
|
|
UBYTE FAR *newtab;
|
|
COUNT i;
|
|
|
|
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);
|
|
|
|
for (i = 0; i < ppsp->ps_maxfiles; i++)
|
|
newtab[i] = ppsp->ps_filetab[i];
|
|
|
|
for (; i < nHandles; i++)
|
|
newtab[i] = 0xff;
|
|
|
|
ppsp->ps_maxfiles = nHandles;
|
|
ppsp->ps_filetab = newtab;
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
/* this is the same, is shorter (~170)and slightly easier to understand TE*/
|
|
int DosMkTmp(BYTE FAR * pathname, UWORD attr)
|
|
{
|
|
/* create filename from current date and time */
|
|
char FAR *ptmp = pathname;
|
|
BYTE wd,
|
|
month,
|
|
day;
|
|
BYTE h,
|
|
m,
|
|
s,
|
|
hund;
|
|
WORD sh;
|
|
WORD year;
|
|
int rc;
|
|
char name83[13];
|
|
int loop;
|
|
|
|
while (*ptmp)
|
|
ptmp++;
|
|
|
|
if (ptmp == pathname || (ptmp[-1] != '\\' && ptmp[-1] != '/'))
|
|
*ptmp++ = '\\';
|
|
|
|
DosGetDate(&wd, &month, &day, (COUNT FAR *) & year);
|
|
DosGetTime(&h, &m, &s, &hund);
|
|
|
|
sh = s * 100 + hund;
|
|
|
|
for ( loop = 0; loop < 0xfff; loop++)
|
|
{
|
|
sprintf(name83,"%x%x%x%x%x%03x.%03x",
|
|
|
|
year & 0xf,month & 0xf, day & 0xf,h & 0xf,m & 0xf, sh&0xfff,
|
|
loop & 0xfff);
|
|
|
|
fmemcpy(ptmp, name83, 13);
|
|
|
|
if ((rc = DosOpen(pathname, 0)) < 0 &&
|
|
rc != DE_ACCESS /* subdirectory ?? */
|
|
/* todo: sharing collision on
|
|
network drive
|
|
*/
|
|
)
|
|
break;
|
|
|
|
if (rc >= 0) DosClose(rc);
|
|
}
|
|
|
|
if (rc == DE_FILENOTFND)
|
|
{
|
|
rc = DosCreat(pathname, attr);
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
COUNT get_verify_drive(char FAR *src)
|
|
{
|
|
UBYTE drive;
|
|
|
|
/* Do we have a drive? */
|
|
if (src[1] == ':')
|
|
drive = ((src[0]-1) | 0x20) - ('a'-1);
|
|
else
|
|
return default_drive;
|
|
if (drive < lastdrive && CDSp->cds_table[drive].cdsFlags & CDSVALID)
|
|
return drive;
|
|
else
|
|
return DE_INVLDDRV;
|
|
}
|
|
|
|
/*
|
|
* 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
|
|
|
|
*/
|
|
|
|
COUNT ASMCFUNC truename(char FAR * src, char FAR * dest, COUNT t)
|
|
{
|
|
static char buf[128] = "A:\\\0\0\0\0\0\0\0\0\0";
|
|
char *bufp = buf + 3;
|
|
COUNT i, rootEndPos = 2; /* renamed x to rootEndPos - Ron Cemer */
|
|
struct dhdr FAR *dhp;
|
|
BYTE FAR *froot;
|
|
WORD d;
|
|
|
|
dest[0] = '\0';
|
|
|
|
i = get_verify_drive(src);
|
|
if (i < 0)
|
|
return DE_INVLDDRV;
|
|
|
|
buf[0] = i + 'A';
|
|
buf[1] = ':'; /* Just to be sure */
|
|
|
|
/* First, adjust the source pointer */
|
|
src = adjust_far(src);
|
|
|
|
/* Do we have a drive? */
|
|
if (src[1] == ':')
|
|
src += 2;
|
|
|
|
/*
|
|
Code repoff from dosfns.c
|
|
MSD returns X:/CON for truename con. Not X:\CON
|
|
*/
|
|
/* check for a device */
|
|
|
|
if ((*src != '.') && (*src != '\\') && (*src != '/') && ((dhp = IsDevice(src)) != NULL))
|
|
{
|
|
|
|
froot = get_root(src);
|
|
|
|
/* /// Bugfix: NUL.LST is the same as NUL. This is true for all
|
|
devices. On a device name, the extension is irrelevant
|
|
as long as the name matches.
|
|
- Ron Cemer */
|
|
|
|
buf[2] ='/';
|
|
/* /// Bug: should be only copying up to first space.
|
|
- Ron Cemer */
|
|
|
|
for (d = 0; d < FNAME_SIZE && dhp->dh_name[d] != 0 && dhp->dh_name[d] != ' '; d++)
|
|
*bufp++ = dhp->dh_name[d];
|
|
/* /// DOS will return C:/NUL.LST if you pass NUL.LST in.
|
|
DOS will also return C:/NUL.??? if you pass NUL.* in.
|
|
Code added here to support this.
|
|
- Ron Cemer */
|
|
while ( (*froot != '.') && (*froot != '\0') ) froot++;
|
|
if (*froot) froot++;
|
|
if (*froot) {
|
|
*bufp++ = '.';
|
|
for (i = 0; i < FEXT_SIZE; i++) {
|
|
if ( (*froot == '\0') || (*froot == '.') )
|
|
break;
|
|
if (*froot == '*') {
|
|
for (; i < FEXT_SIZE; i++) *bufp++ = '?';
|
|
break;
|
|
}
|
|
*bufp++ = *froot++;
|
|
}
|
|
}
|
|
/* /// End of code additions. - Ron Cemer */
|
|
goto exit_tn;
|
|
}
|
|
|
|
/* /// Added to adjust for filenames which begin with ".\"
|
|
* The problem was manifesting itself in the inability
|
|
* to run an program whose filename (without the extension)
|
|
* was longer than six characters and the PATH variable
|
|
* contained ".", unless you explicitly specified the full
|
|
* path to the executable file.
|
|
* Jun 11, 2000 - rbc */
|
|
/* /// Changed to "while" from "if". - Ron Cemer */
|
|
while ( (src[0] == '.') && (src[1] == '\\') ) src += 2;
|
|
|
|
current_ldt = &CDSp->cds_table[i];
|
|
|
|
/* Always give the redirector a chance to rewrite the filename */
|
|
fstrncpy(bufp - 1, src, sizeof(buf) - (bufp - buf));
|
|
if ((t == FALSE) && (QRemote_Fn(buf, dest) == SUCCESS) && (dest[0] != '\0')) {
|
|
return SUCCESS;
|
|
} else {
|
|
bufp[-1] = '\\';
|
|
}
|
|
if (t == FALSE)
|
|
{
|
|
fstrncpy(buf, current_ldt->cdsCurrentPath, current_ldt->cdsJoinOffset);
|
|
bufp = buf + current_ldt->cdsJoinOffset;
|
|
rootEndPos = current_ldt->cdsJoinOffset; /* renamed x to rootEndPos - Ron Cemer */
|
|
*bufp++ = '\\';
|
|
}
|
|
|
|
if (*src != '\\' && *src != '/') /* append current dir */
|
|
{
|
|
DosGetCuDir((UBYTE)(i+1), bufp);
|
|
if (*bufp)
|
|
{
|
|
while (*bufp)
|
|
bufp++;
|
|
*bufp++ = '\\';
|
|
}
|
|
}
|
|
else
|
|
src++;
|
|
|
|
/*move_name:*/
|
|
|
|
/* /// The block inside the "#if (0) ... #endif" is
|
|
seriously broken. New code added below to replace it.
|
|
This eliminates many serious bugs, specifically
|
|
with FreeCOM where truename is required to work
|
|
according to the DOS specification in order for
|
|
the COPY and other file-related commands to work
|
|
properly.
|
|
This should be a major improvement to all apps which
|
|
use truename.
|
|
- Ron Cemer */
|
|
|
|
#if (0)
|
|
/*
|
|
* The code here is brain dead. It works long as the calling
|
|
* function are operating with in normal parms.
|
|
* jt
|
|
*/
|
|
n = 9;
|
|
/* convert all forward slashes to backslashes, and uppercase all characters */
|
|
while (*src)
|
|
{
|
|
char c;
|
|
c = *src++;
|
|
if(!n)
|
|
return DE_PATHNOTFND; /* do this for now */
|
|
n--;
|
|
switch (c)
|
|
{
|
|
case '*':
|
|
if (*src == '.')
|
|
{
|
|
while (n--)
|
|
*bufp++ = '?';
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
if (src[-2] == '.')
|
|
{
|
|
while (n--)
|
|
*bufp++ = '?';
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
while (n--)
|
|
*bufp++ = '?';
|
|
break;
|
|
}
|
|
}
|
|
case '/': /* convert to backslash */
|
|
case '\\':
|
|
|
|
if (bufp[-1] != '\\'){
|
|
*bufp++ = '\\';
|
|
n = 9;
|
|
}
|
|
break;
|
|
|
|
/* look for '.' and '..' dir entries */
|
|
case '.':
|
|
if (bufp[-1] == '\\')
|
|
{
|
|
if (*src == '.' && (src[1] == '/' || src[1] == '\\' || !src[1]))
|
|
{
|
|
/* '..' dir entry: rewind bufp to last backslash */
|
|
|
|
for (bufp -= 2; *bufp != '\\'; bufp--)
|
|
{
|
|
if (bufp < buf + rootEndPos) /* '..' illegal in root dir */
|
|
return DE_PATHNOTFND;
|
|
}
|
|
src++;
|
|
if (bufp[-1] == ':')
|
|
bufp++;
|
|
}
|
|
else if (*src == '/' || *src == '\\' || *src == 0)
|
|
break;
|
|
/* --bufp;*/
|
|
else
|
|
return DE_PATHNOTFND;
|
|
}
|
|
else if ( *src == '/' || *src == '\\' || *src == 0)
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
n = 4;
|
|
*bufp++ = c;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
*bufp++ = c;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* remove trailing backslashes */
|
|
while (bufp[-1] == '\\')
|
|
--bufp;
|
|
#endif
|
|
|
|
/* /// Beginning of new code. - Ron Cemer */
|
|
bufp--;
|
|
{
|
|
char c, *bufend = buf+(sizeof(buf)-1);
|
|
int gotAnyWildcards = 0;
|
|
int seglen, copylen, state;
|
|
while ( (*src) && (bufp < bufend) ) {
|
|
/* Skip duplicated slashes. */
|
|
while ( (*src == '/') || (*src == '\\') ) src++;
|
|
if (!(*src)) break;
|
|
/* Find the end of this segment in the source string. */
|
|
for (seglen = 0; ; seglen++) {
|
|
c = src[seglen];
|
|
if ( (c == '\0') || (c == '/') || (c == '\\') )
|
|
break;
|
|
}
|
|
if (seglen > 0) {
|
|
/* Ignore all ".\" or "\." path segments. */
|
|
if ( (seglen != 1) || (*src != '.') ) {
|
|
/* Apply ".." to the path by removing
|
|
last path segment from buf. */
|
|
if ( (seglen==2) && (src[0] == '.') && (src[1] == '.') ) {
|
|
if (bufp > (buf+rootEndPos)) {
|
|
bufp--;
|
|
while ( (bufp > (buf+rootEndPos))
|
|
&& (*bufp != '/')
|
|
&& (*bufp != '\\') )
|
|
bufp--;
|
|
} else {
|
|
/* .. in root dir illegal */
|
|
return DE_PATHNOTFND;
|
|
}
|
|
} else {
|
|
/* New segment. If any wildcards in previous
|
|
segment(s), this is an invalid path. */
|
|
if (gotAnyWildcards || src[0]=='.') return DE_PATHNOTFND;
|
|
/* Append current path segment to result. */
|
|
*(bufp++) = '\\';
|
|
if (bufp >= bufend) break;
|
|
copylen = state = 0;
|
|
for (i=0; ( (i < seglen) && (bufp < bufend) ); i++) {
|
|
c = src[i];
|
|
gotAnyWildcards |= ( (c == '?') || (c == '*') );
|
|
switch (state) {
|
|
case 0: /* Copying filename (excl. extension) */
|
|
if (c == '*') {
|
|
while (copylen < FNAME_SIZE) {
|
|
*(bufp++) = '?';
|
|
if (bufp >= bufend) break;
|
|
copylen++;
|
|
}
|
|
copylen = 0;
|
|
state = 1; /* Go wait for dot */
|
|
break;
|
|
}
|
|
if (c == '.') {
|
|
if (src[i+1] != '.' && i+1 < seglen) *(bufp++) = '.';
|
|
copylen = 0;
|
|
state = 2; /* Copy extension next */
|
|
break;
|
|
}
|
|
*(bufp++) = c;
|
|
copylen++;
|
|
if (copylen >= FNAME_SIZE) {
|
|
copylen = 0;
|
|
state = 1; /* Go wait for dot */
|
|
break;
|
|
}
|
|
break;
|
|
case 1: /* Looking for dot so we can copy exten */
|
|
if (src[i] == '.' && src[i+1] != '.' && i+1 < seglen) {
|
|
*(bufp++) = '.';
|
|
state = 2;
|
|
}
|
|
break;
|
|
case 2: /* Copying extension */
|
|
if (c == '*') {
|
|
while (copylen < FEXT_SIZE) {
|
|
*(bufp++) = '?';
|
|
if (bufp >= bufend) break;
|
|
copylen++;
|
|
}
|
|
i = seglen; /* Done with segment */
|
|
break;
|
|
}
|
|
if (c == '.') {
|
|
i = seglen; /* Done with segment */
|
|
break;
|
|
}
|
|
*(bufp++) = c;
|
|
copylen++;
|
|
if (copylen >= FEXT_SIZE) {
|
|
i = seglen; /* Done with segment */
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} /* if (seglen > 0) */
|
|
src += seglen;
|
|
if (*src) src++;
|
|
} /* while ( (*src) && (bufp < bufend) ) */
|
|
}
|
|
/* /// End of new code. - Ron Cemer */
|
|
|
|
if (bufp == buf + 2)
|
|
++bufp;
|
|
|
|
exit_tn:
|
|
|
|
*bufp++ = 0;
|
|
|
|
/* finally, uppercase everything */
|
|
DosUpString(buf);
|
|
|
|
/* copy to user's buffer */
|
|
fmemcpy(dest, buf, bufp - buf);
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* Log: newstuff.c,v - for newer entries see "cvs log newstuff.c"
|
|
*
|
|
* Revision 1.8 2000/04/02 06:11:35 jtabor
|
|
* Fix ChgDir Code
|
|
*
|
|
* Revision 1.7 2000/04/02 05:30:48 jtabor
|
|
* Fix ChgDir Code
|
|
*
|
|
* Revision 1.6 2000/03/31 05:40:09 jtabor
|
|
* Added Eric W. Biederman Patches
|
|
*
|
|
* Revision 1.5 2000/03/09 06:07:11 kernel
|
|
* 2017f updates by James Tabor
|
|
*
|
|
* Revision 1.4 1999/08/25 03:18:09 jprice
|
|
* ror4 patches to allow TC 2.01 compile.
|
|
*
|
|
* Revision 1.3 1999/04/11 04:33:39 jprice
|
|
* ror4 patches
|
|
*
|
|
* Revision 1.2 1999/04/04 18:51:43 jprice
|
|
* no message
|
|
*
|
|
* Revision 1.1.1.1 1999/03/29 15:41:22 jprice
|
|
* New version without IPL.SYS
|
|
*
|
|
* Revision 1.4 1999/02/08 05:55:57 jprice
|
|
* Added Pat's 1937 kernel patches
|
|
*
|
|
* Revision 1.3 1999/02/01 01:48:41 jprice
|
|
* Clean up; Now you can use hex numbers in config.sys. added config.sys screen function to change screen mode (28 or 43/50 lines)
|
|
*
|
|
* Revision 1.2 1999/01/22 04:13:26 jprice
|
|
* Formating
|
|
*
|
|
* Revision 1.1.1.1 1999/01/20 05:51:01 jprice
|
|
* Imported sources
|
|
*
|
|
*
|
|
* Rev 1.4 06 Dec 1998 8:49:02 patv
|
|
* Bug fixes.
|
|
*
|
|
* Rev 1.3 04 Jan 1998 23:15:22 patv
|
|
* Changed Log for strip utility
|
|
*
|
|
* Rev 1.2 04 Jan 1998 17:26:14 patv
|
|
* Corrected subdirectory bug
|
|
*
|
|
* Rev 1.1 22 Jan 1997 13:21:22 patv
|
|
* pre-0.92 Svante Frey bug fixes.
|
|
*/
|
|
|