@@ -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 */
0 commit comments