Skip to content

Commit 08b02e0

Browse files
committed
improve truename compatibility for character devices, additional debug prints, rename cds netflags to better match purpose and note unused.
1 parent 6932a3a commit 08b02e0

8 files changed

Lines changed: 127 additions & 110 deletions

File tree

hdr/cds.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ struct cds {
4444
} _cdsRedir;
4545
} _cdsUnion;
4646

47-
UWORD cdsStoreUData;
47+
UWORD cdsUserData; /* initialized to 0xFFFF, otherwise unused by kernel */
4848

4949
#define cdsJoinOffset cdsBackslashOffset
5050
WORD cdsBackslashOffset; /* Position of "root directory" backslash for
@@ -55,9 +55,9 @@ struct cds {
5555
if local path: ofs > colon
5656
*/
5757

58-
BYTE cdsNetFlag1; /* According to PCDOS 7 Tech Ref: IFS drive, 2=IFS, 4=NetUse */
58+
BYTE cdsIfsType; /* According to PCDOS 7 Tech Ref: IFS drive, 2=IFS, 4=NetUse, unused by kernel */
5959
BYTE FAR *cdsIfs; /* Pointer to Installable File System Header */
60-
UWORD cdsNetFlags2; /* File System specific data */
60+
UWORD cdsFileSysData; /* File System specific data, unused by kernel */
6161

6262
};
6363

kernel/dosfns.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,10 +116,13 @@ struct cds FAR *get_cds(unsigned drive)
116116
struct cds FAR *cdsp;
117117
unsigned flags;
118118

119-
if (drive >= lastdrive)
119+
if (drive >= lastdrive) {
120+
DebugPrintf(("%u >= %u\n", drive, lastdrive));
120121
return NULL;
122+
}
121123
cdsp = &CDSp[drive];
122124
flags = cdsp->cdsFlags;
125+
DebugPrintf(("flags=%0x valid=%04x, join=%04x, net=%04x, DPB is NULL?%d\n", flags, flags & CDSVALID, flags & CDSJOINED, flags & CDSNETWDRV, (cdsp->cdsDpb == NULL)?0:1));
123126
/* Entry is disabled or JOINed drives are accessable by the path only */
124127
if (!(flags & CDSVALID) || (flags & CDSJOINED) != 0)
125128
return NULL;
@@ -541,6 +544,7 @@ long DosOpenSft(char FAR * fname, unsigned flags, unsigned attrib)
541544
sftp->sft_attrib = attrib = attrib | D_ARCHIVE;
542545

543546
/* check for a (local) device */
547+
DebugPrintf(("result for %Fs is %s%s%s%s",fname,(result & IS_DEVICE)?"device ":"X",(result & IS_NETWORK)?"network ":"N",(dhp = IsDevice(fname)) != NULL?"IsDevice!=NULL ":"="));
544548
if ((result & IS_DEVICE) && !(result & IS_NETWORK) && (dhp = IsDevice(fname)) != NULL)
545549
{
546550
int rc = DeviceOpenSft(dhp, sftp);
@@ -1392,6 +1396,7 @@ struct dhdr FAR *IsDevice(const char FAR * fname)
13921396
((*froot=='.') && ((*(froot+1)=='\0') || (*(froot+2)=='\0' && *(froot+1)=='.')))
13931397
)
13941398
{
1399+
DebugPrintf(("root is blank\n"));
13951400
return NULL;
13961401
}
13971402

@@ -1402,9 +1407,11 @@ struct dhdr FAR *IsDevice(const char FAR * fname)
14021407
if (!(dhp->dh_attr & ATTR_CHAR)) /* if this is block device, skip */
14031408
continue;
14041409

1410+
DebugPrintf(("checking filename\n"));
14051411
for (i = 0; i < FNAME_SIZE; i++)
14061412
{
14071413
unsigned char c1 = (unsigned char)froot[i];
1414+
DebugPrintf(("%c",c1));
14081415
/* ignore extensions and handle filenames shorter than FNAME_SIZE */
14091416
if (c1 == '.' || c1 == '\0')
14101417
{
@@ -1421,11 +1428,13 @@ struct dhdr FAR *IsDevice(const char FAR * fname)
14211428
break;
14221429
}
14231430

1431+
DebugPrintf(("\ni=%d\n", i));
14241432
/* if found a match then return device header */
14251433
if (i == FNAME_SIZE)
14261434
return dhp;
14271435
}
14281436

1437+
DebugPrintf(("Not device\n"));
14291438
return NULL;
14301439
}
14311440

@@ -1453,7 +1462,7 @@ COUNT DosTruename(const char FAR *src, char FAR *dest)
14531462
Therefore, the name is created in an internal buffer
14541463
and copied into the user buffer only on success.
14551464
*/
1456-
COUNT rc = truename(src, PriPathName, CDS_MODE_ALLOW_WILDCARDS);
1465+
COUNT rc = truename(src, PriPathName, CDS_MODE_ALLOW_WILDCARDS|CDS_MODE_CHECK_DEV_PATH);
14571466
if (rc >= SUCCESS)
14581467
{
14591468
fstrcpy(dest, PriPathName);

kernel/inthndlr.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2991,7 +2991,7 @@ VOID ASMCFUNC int2F_12_handler(struct int2f12regs FAR *pr)
29912991
}
29922992
TempCDS.cdsStrtClst = 0xffff;
29932993
TempCDS.cdsParam = 0xffff;
2994-
TempCDS.cdsStoreUData = 0xffff;
2994+
TempCDS.cdsUserData = 0xffff;
29952995
r.CX = sizeof(TempCDS);
29962996
r.ES = FP_SEG(&TempCDS);
29972997
r.DI = FP_OFF(&TempCDS);

kernel/kernel.asm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -873,7 +873,7 @@ current_device times 2 dw 0 ;27A - point to device header if filename is
873873
global _lpCurSft
874874
_lpCurSft times 2 dw 0 ;27e - Current SFT
875875
global _current_ldt
876-
_current_ldt times 2 dw 0 ;282 - Current CDS
876+
_current_ldt times 2 dw 0 ;282 - Current CDS (ThisCDS in published MSDOS sources)
877877
global _sda_lpFcb
878878
_sda_lpFcb times 2 dw 0 ;286 - pointer to callers FCB
879879
global _current_sft_idx

kernel/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ STATIC VOID FsConfig(VOID)
401401
}
402402
pcds_table->cdsStrtClst = 0xffff;
403403
pcds_table->cdsParam = 0xffff;
404-
pcds_table->cdsStoreUData = 0xffff;
404+
pcds_table->cdsUserData = 0xffff;
405405
pcds_table->cdsJoinOffset = 2;
406406
}
407407

kernel/newstuff.c

Lines changed: 108 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -282,93 +282,11 @@ COUNT truename(const char FAR * src, char * dest, COUNT mode)
282282
/* referenced for network with empty current_ldt. */
283283
return IS_NETWORK;
284284
}
285-
286-
/* Do we have a drive? */
287-
if (src[1] == ':')
288-
result = drLetterToNr(DosUpFChar(src0));
289-
else
290-
result = default_drive;
291-
292-
dhp = IsDevice(src);
293-
294-
cdsEntry = get_cds(result);
295-
if (cdsEntry == NULL)
296-
{
297-
/* If opening a character device, DOS allows device name
298-
to be prefixed by [invalid] drive letter and/or optionally
299-
\DEV\ directory prefix, however, any other directory
300-
including root (\) is an invalid path if drive is not
301-
valid and returns such.
302-
Whereas truename always fails for invalid drive.
303-
*/
304-
if (dhp && (mode & CDS_MODE_CHECK_DEV_PATH) && (result >= lastdrive))
305-
{
306-
/* Note: check for (result >= lastdrive) means invalid drive
307-
was provided as otherwise we would have used default_drive
308-
so we know src in the form of X:?
309-
fail if anything other than no path or path is \DEV\
310-
*/
311-
const char FAR *s = src+2;
312-
char c = *s;
313-
314-
if( c != '\\' && c != '/' ) c = '\0';
315-
/* could be 1 letter devicename, don't go scanning random memory */
316-
if (*(src+3) != '\0')
317-
{
318-
s = fstrchr(src+3, '\\'); /* ?is there \ or / other than immediately after drive: */
319-
if (s == NULL) s = fstrchr(src+3, '/');
320-
}
321-
else
322-
{
323-
s = NULL;
324-
}
325-
326-
if (c == '\0')
327-
{
328-
/* either X:devicename or X:path\devicename */
329-
if (s != NULL) goto invalid_path;
330-
}
331-
else
332-
{
333-
/* either X:\devicename or X:\path\devicename
334-
only X:\DEV\devicename is valid path
335-
*/
336-
if (s == NULL) goto invalid_path;
337-
if (s != src+6) goto invalid_path;
338-
if (fmemcmp(src+3, "DEV", 3) != 0) goto invalid_path;
339-
s = fstrchr(src+7, '\\');
340-
if (s == NULL) s = fstrchr(src+7, '/');
341-
if (s != NULL) goto invalid_path;
342-
}
343-
344-
/* use CDS of current drive (MS-DOS may return drive P: for invalid drive.) */
345-
result = default_drive;
346-
cdsEntry = get_cds(result);
347-
if (cdsEntry == NULL) goto invalid_path;
348-
}
349-
else
350-
{
351-
invalid_path:
352-
return DE_PATHNOTFND;
353-
}
354-
}
355-
356-
fmemcpy(&TempCDS, cdsEntry, sizeof(TempCDS));
357-
tn_printf(("CDS entry: #%u @%p (%u) '%s'\n", result, cdsEntry,
358-
TempCDS.cdsBackslashOffset, TempCDS.cdsCurrentPath));
359-
/* is the current_ldt thing necessary for compatibly??
360-
-- 2001/09/03 ska*/
361-
current_ldt = cdsEntry;
362-
if (TempCDS.cdsFlags & CDSNETWDRV)
363-
result |= IS_NETWORK;
364-
365-
if (dhp)
366-
result |= IS_DEVICE;
367285

368286
/* Try if the Network redirector wants to do it */
369287
/* via Qualify Remote Filename call & validate results */
370-
assert(sizeof(PriPathName)>=12); /* dest is always pointer to PriPathName */
371-
memset(dest, 0, 12); /* enable can verify redirector set result value */
288+
assert(sizeof(PriPathName)>=12); /* dest is always pointer to PriPathName or SecPathName */
289+
memset(dest, 0, 12); /* so we can verify redirector set result value */
372290
/* MUX succeeded and really something */
373291
if (!(mode & CDS_MODE_SKIP_PHYSICAL) &&
374292
QRemote_Fn(dest, src) == SUCCESS && dest[0] != '\0')
@@ -392,22 +310,114 @@ COUNT truename(const char FAR * src, char * dest, COUNT mode)
392310
return result;
393311
}
394312

313+
/* Redirector interface failed (or skipped) --> proceed with local mapper */
314+
315+
/* Was a drive letter provided? If not then use current drive */
316+
if (src[1] == ':')
317+
result = drLetterToNr(DosUpFChar(src0));
318+
else
319+
result = default_drive;
320+
321+
dhp = IsDevice(src);
322+
323+
/* Note: [older] redirectors may not provide Int 2Fh API and instead simply wrap Int 21h calls
324+
so above callout to redirector may fail but still be a redirected (mapped) drive that is invalid to us.
325+
326+
When given a character device, Truename or Open allows device name to be prefixed by invalid
327+
drive letter and\or optional \DEV\ directory prefix, however any other directory including
328+
root path (\) will always return error. However, if drive is valid, then for character
329+
devices any path may be provided.
330+
For example:
331+
CON will use default drive and assuming default is X: then same as X:CON
332+
X:CON and X:\DEV\CON will succeed regardless if X: is valid or not
333+
334+
If X: is a valid drive then returns proper path for drive (X:/CON or \\remote\path\CON respectively)
335+
If X: is not a valid drive then if no path (not even root \ path) or path exactly \DEV\ will
336+
succeed and use dummy path of P:/CON (always P: apparently for dummy CDS), or if any path than \DEV\
337+
will fail.
338+
339+
X:\CON and X:\path\CON will always succeed if X: is a valid drive even if path does not exists
340+
If X: is a valid drive then returns provided path for drive (X:/CON or \\remote\path\CON respectively).
341+
*/
342+
343+
/* determine if valid drive */
344+
cdsEntry = get_cds(result);
345+
346+
/* is this a character device (dhp != NULL)? if so check special cases
347+
if cdsEntry is not NULL then valid drive, so any path acceptable for character device
348+
*/
349+
if (dhp && (mode & CDS_MODE_CHECK_DEV_PATH) && (cdsEntry == NULL))
350+
{
351+
/* determine if drive letter provided (we know at least 1 character long) */
352+
const char FAR *s = src+1;
353+
const char FAR *hasSlash;
354+
if (*s == ':') s++; else s--; /* skip drive (X:) if provided */
355+
/* s points to start of device name or path, just past optional drive letter */
356+
357+
/* determine if path provided, any \ or / characters indicate path including root */
358+
hasSlash = fstrchr(s, '\\');
359+
if (hasSlash == NULL) hasSlash = fstrchr(s, '/');
360+
361+
if (hasSlash != NULL) {
362+
/* only \DEV\ (with leading \) or /DEV/ for path portion allowed since drive is invalid */
363+
tn_printf(("-->%Fs<--\n", s));
364+
if ((*s == '\\') || (*s == '/')) {
365+
unsigned char c[6];
366+
unsigned x;
367+
c[0]= *(++s) & 0xDF; /* get uppercase next character */
368+
c[1]= *(++s) & 0xDF;
369+
c[2]= *(++s) & 0xDF;
370+
c[3]= *(++s);
371+
if (c[3]=='\\') c[3]='/';
372+
s++; /* s now points to start of device name */
373+
c[4]= '\0';
374+
x = fstrcmp((char *)c, "DEV/");
375+
tn_printf(("comparing %s to %s == %d\n", c, "DEV/", x));
376+
if (x != 0) goto invalid_path;
377+
tn_printf(("ok\n"));
378+
} else {
379+
/* there is a / or \ but not at beginning so must be a path, which is invalid for device */
380+
goto invalid_path;
381+
}
382+
} /* else { just devicename or X:devicename, drive even default need not be valid to us (mapped drive with invalid CDS) } */
383+
384+
/* we have a character device with invalid drive
385+
instead of using CDS of current drive follow MS-DOS convention of returning drive P: for invalid drive.
386+
*/
387+
result = 'P' - 'A'; /* return drive P: */
388+
/* cdsEntry = get_cds_unvalidated(result); * WARNING: may point past valid memory! if result >= lastdrive */
389+
cdsEntry = (struct cds FAR *)MK_FP(-1,-1);
390+
tn_printf(("No CDS using entry P: #%u\n", result));
391+
fmemset(&TempCDS, 0, sizeof(TempCDS));
392+
fstrcpy(TempCDS.cdsCurrentPath, s); /* just device name no path or drive letter */
393+
tn_printf(("cds=%s\n", TempCDS.cdsCurrentPath));
394+
}
395+
396+
397+
/* Note: on redirected drives cdsEntry may not be NULL but with dhp==NULL, so must check network redir prior to here */
398+
if (cdsEntry == NULL)
399+
{
400+
invalid_path:
401+
return DE_PATHNOTFND;
402+
} else {
403+
if (cdsEntry != (struct cds FAR *)MK_FP(-1,-1))
404+
fmemcpy(&TempCDS, cdsEntry, sizeof(TempCDS));
405+
}
406+
current_ldt = cdsEntry; /* update current_ldt for compatibility, stored in LOL */
407+
tn_printf(("CDS entry: #%u @%p (%u) '%s'\n", result, cdsEntry,
408+
TempCDS.cdsBackslashOffset, TempCDS.cdsCurrentPath));
409+
if (TempCDS.cdsFlags & CDSNETWDRV)
410+
result |= IS_NETWORK;
411+
412+
if (dhp)
413+
result |= IS_DEVICE;
414+
395415
/* Redirector interface failed --> proceed with local mapper */
396416
dest[0] = drNrToLetter(result & 0x1f);
397417
dest[1] = ':';
398418

399-
/* Do we have a drive? */
400-
if (src[1] == ':') {
401-
src += 2;
402-
if (result & IS_DEVICE)
403-
{
404-
/* stripped optional X: from source, and verified not \path\devicename
405-
so treat \devicename as devicename same (and \dev\devicename as dev\devicename)
406-
*/
407-
if (src[0] == '\\' || src[0] == '/')
408-
src++;
409-
}
410-
}
419+
/* Do we have a drive? if so skip over it */
420+
if (src[1] == ':') src += 2;
411421

412422
/*
413423
Code repoff from dosfns.c
@@ -444,6 +454,7 @@ COUNT truename(const char FAR * src, char * dest, COUNT mode)
444454
src = froot;
445455
}
446456
}
457+
tn_printf(("DEVICE: dest=%s, src=%Fs\n", dest, (char far *)src));
447458
}
448459

449460
/* Make fully-qualified logical path */
@@ -458,7 +469,7 @@ COUNT truename(const char FAR * src, char * dest, COUNT mode)
458469
cp = TempCDS.cdsCurrentPath;
459470
/* ensure termination of strcpy */
460471
cp[MAX_CDSPATH - 1] = '\0';
461-
if ((TempCDS.cdsFlags & CDSNETWDRV) == 0)
472+
if ((cdsEntry != (struct cds FAR *)MK_FP(-1,-1)) && ((TempCDS.cdsFlags & CDSNETWDRV) == 0))
462473
{
463474
if (media_check(TempCDS.cdsDpb) < 0)
464475
return DE_PATHNOTFND;
@@ -668,10 +679,6 @@ COUNT truename(const char FAR * src, char * dest, COUNT mode)
668679
}
669680
/* nothing found => continue normally */
670681
}
671-
if ((mode & CDS_MODE_CHECK_DEV_PATH) &&
672-
((result & (IS_DEVICE|IS_NETWORK)) == IS_DEVICE) &&
673-
dest[2] != '/' && !dir_exists(dest))
674-
return DE_PATHNOTFND;
675682

676683
/* Note: Not reached on error or if JOIN or QRemote_Fn (2f.1123) matched */
677684
if (mode==CDS_MODE_ALLOW_WILDCARDS) /* DosTruename mode */

kernel/proto.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,7 @@ long ASMPASCAL network_redirector_mx(unsigned cmd, void far *s, void *arg);
381381
#define remote_lseek(s,new_pos) network_redirector_mx(REM_LSEEK, s, &new_pos)
382382
#define remote_setfattr(attr) (int)network_redirector_mx(REM_SETATTR, NULL, (void *)attr)
383383
#define remote_printredir(dx,ax) (int)network_redirector_mx(REM_PRINTREDIR, MK_FP(0,dx),(void *)ax)
384+
/* local (near) address of s pushed on stack, where s is far (segment:offset) of argument */
384385
#define QRemote_Fn(d,s) (int)network_redirector_mx(REM_FILENAME, d, (void *)&s)
385386

386387
UWORD get_machine_name(BYTE FAR * netname);

tests/int2f-12/t121f.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
* cdsFlags = 0
2626
* cdsStrtClst = 0xFFFF
2727
* cdsParam = 0xFFFF
28-
* cdsStoreUData = 0xFFFF
28+
* cdsUserData = 0xFFFF
2929
*
3030
* Care masks:
3131
* Success path: CARE_FLAGS | CARE_BUF

0 commit comments

Comments
 (0)