Skip to content

Commit

Permalink
Fix crash in TDirListBox (used by TChDirDialog) on Linux if given a L…
Browse files Browse the repository at this point in the history
…inux path (eg /home), makes TDirListBox work properly on Linux (no C:\ drives etc)

Fixes segfault on Linux if you call  TDirListBox::newDirectory() with a real Unix-style path.
Makes the TChDirDialog support native Linux paths (no simulated C:\ drive etc).
  • Loading branch information
MookThompson committed Jan 31, 2024
1 parent 0917f04 commit d0d645f
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 5 deletions.
19 changes: 18 additions & 1 deletion source/tvision/tchdrdlg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,11 @@ void TChDirDialog::getData( void * )
{
}

#define isSeparator(c) (c == '\\' || c == '/')
#ifndef _TV_UNIX
#define isSeparator(c) (c == '\\' || c == '/')
#else
#define isSeparator(c) (c == '/')
#endif

static void trimEndSeparator(char *path)
{
Expand All @@ -114,6 +118,7 @@ void TChDirDialog::handleEvent( TEvent& event )
{
TDirEntry *p = dirList->list()->at( dirList->focused );
strcpy( curDir, p->dir() );
#ifndef _TV_UNIX
if( strcmp( curDir, drivesText ) == 0 )
break;
else if( driveValid( curDir[0] ) )
Expand All @@ -124,6 +129,16 @@ void TChDirDialog::handleEvent( TEvent& event )
}
else
return;
#else
if ( strcmp( curDir, "/" ) == 0 )
break;
else
{
int len = strlen( curDir );
if( !isSeparator(curDir[len - 1]) )
strcat(curDir, "/");
}
#endif
break;
}
default:
Expand Down Expand Up @@ -163,8 +178,10 @@ void TChDirDialog::setUpDialog()

static int changeDir( const char *path )
{
#ifndef _TV_UNIX
if( path[1] == ':' )
setdisk( toupper(path[0]) - 'A' );
#endif
return chdir( path );
}

Expand Down
11 changes: 10 additions & 1 deletion source/tvision/tdircoll.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,11 @@ Boolean isDir( const char *str ) noexcept
(ff.ff_attrib & FA_DIREC) != 0 );
}

#define isSeparator(c) (c == '\\' || c == '/')
#ifndef _TV_UNIX
#define isSeparator(c) (c == '\\' || c == '/')
#else
#define isSeparator(c) (c == '/')
#endif

Boolean pathValid( const char *path ) noexcept
{
Expand Down Expand Up @@ -124,13 +128,18 @@ Boolean validFileName( const char *fileName ) noexcept

void getCurDir( char *dir, char drive ) noexcept
{
#ifndef _TV_UNIX
dir[0] = (char) ((0 <= drive && drive <= 'Z' - 'A' ? drive : getdisk()) + 'A');
dir[1] = ':';
dir[2] = '\\';
dir[3] = '\0';
getcurdir( dir[0] - 'A' + 1, dir+3 );
if( strlen( dir ) > 3 )
strnzcat( dir, "\\", MAXPATH );
#else
getcwd( dir, MAXPATH );
strnzcat( dir, "/", MAXPATH );
#endif
}

Boolean isWild( const char *f ) noexcept
Expand Down
31 changes: 28 additions & 3 deletions source/tvision/tdirlist.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ Boolean TDirListBox::isSelected( short item )

void TDirListBox::showDrives( TDirCollection *dirs )
{
#ifndef _TV_UNIX
Boolean isFirst = True;
char oldc[5];
strcpy( oldc, "0:\\" );
Expand Down Expand Up @@ -116,6 +117,7 @@ void TDirListBox::showDrives( TDirCollection *dirs )
s[ strlen(lastDir)+1 ] = EOS;
dirs->insert( new TDirEntry( s, oldc ) );
}
#endif
}

void TDirListBox::showDirs( TDirCollection *dirs )
Expand All @@ -131,32 +133,50 @@ void TDirListBox::showDirs( TDirCollection *dirs )
strcpy( org, pathDir );

char *curDir = dir;
#ifndef _TV_UNIX
char *end = dir + 3;
const char sepChar = '\\';

char hold = *end;
*end = EOS; // mark end of drive name
strcpy( name, curDir );
dirs->insert( new TDirEntry( org, name ) );

*end = hold; // restore full path
#else
char *end = dir + 1;
const char sepChar = '/';
indent = 0;
#endif
curDir = end;
while( (end = strchr( curDir, '\\' )) != 0 )
while( (end = strchr( curDir, sepChar )) != 0 )
{
*end = EOS;
strncpy( name, curDir, size_t(end-curDir) );
name[size_t(end-curDir)] = EOS;
dirs->insert( new TDirEntry( org - indent, dir ) );
*end = '\\';
*end = sepChar;
curDir = end+1;
indent += indentSize;
}

cur = dirs->getCount() - 1;

end = strrchr( dir, '\\' );
end = strrchr( dir, sepChar );
if ( end == NULL )
{
// no separators found so just bail.
// fixes segfault if no separators found (eg Linux path on Windows or vice versa)
return;
}
char path[MAXPATH];
strncpy( path, dir, size_t(end-dir+1) );
end = path + unsigned(end-dir)+1;
#ifndef _TV_UNIX
strcpy( end, "*.*" );
#else
strcpy( end, "*" );
#endif

Boolean isFirst = True;
ffblk ff;
Expand Down Expand Up @@ -198,11 +218,16 @@ void TDirListBox::newDirectory( TStringView str )
{
strnzcpy( dir, str, sizeof(dir) );
TDirCollection *dirs = new TDirCollection( 5, 5 );
#ifndef _TV_UNIX
dirs->insert( new TDirEntry( drives, drives ) );
if( str == drives )
showDrives( dirs );
else
showDirs( dirs );
#else
dirs->insert( new TDirEntry( "/", "/" ) );
showDirs( dirs );
#endif
newList( dirs );
focusItem( cur );
}
Expand Down

0 comments on commit d0d645f

Please sign in to comment.