Hi List,
I am looking for a way to do a case insensitive search for file names.
Anybody have some hints ?
thanks
Henrik
pl1gcc.sourceforge.net
/*this is a OS particular question but I'd like my UNIX-specific code
criticized here - any errors I'd like to know*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <ustat.h>
#include <malloc.h>
#include <unistd.h>
#include <dirent.h>
static char *
CopyStringPrefix( const char *String, size_t PrefixLength )
{
char *CopyOfString = NULL;
if ( NULL == String || PrefixLength < 0 )
{
return NULL;
}
CopyOfString = (char *)malloc( PrefixLength + 1 );
if ( NULL == CopyOfString )
{
return NULL;
}
strncpy( CopyOfString, String, PrefixLength );
CopyOfString[ PrefixLength ] = '\0';
return CopyOfString;
}
static char *
CopyString( const char *String )
{
if ( NULL == String )
{
return NULL;
}
return CopyStringPrefix( String, strlen( String ) );
}
static char *
CopyDirectory( const char *InFullPath )
{
char *DirectoryName = NULL;
char *LastSlash = NULL;
if ( NULL == InFullPath )
{
return NULL;
}
LastSlash = strrchr( InFullPath, '/' );
if ( NULL == LastSlash )
{
DirectoryName = CopyString( "./" );
}
else
{
DirectoryName = CopyStringPrefix( InFullPath, LastSlash - InFullPath
+ 1 );
}
return DirectoryName;
}
static char *
CopyFileName( const char *InFullPath )
{
char *FileName= NULL;
char *LastSlash = NULL;
if ( NULL == InFullPath )
{
return NULL;
}
LastSlash = strrchr( InFullPath, '/' );
if ( NULL == LastSlash )
{
FileName = CopyString( InFullPath );
}
else
{
FileName = CopyString( LastSlash + 1 );
}
return FileName;
}
static int
IsRegularFile( const char *FullPath )
{
struct stat FileStatus;
if ( 0 != stat( FullPath, &FileStatus ) )
{
return 0;
}
return S_ISREG(FileStatus.st_mode );
}
static int
OpenDirFile( const char *DirPath, const char *FileName, int
ReadWriteMode )
{
int fd = -1;
char *NewFullPath = NULL;
if ( NULL == DirPath || NULL == FileName )
{
return -1;
}
NewFullPath = malloc( strlen( DirPath ) + strlen( FileName ) + 1 );
if ( NULL == NewFullPath )
return -1;
strcpy( NewFullPath, DirPath );
strcat( NewFullPath, FileName );
if ( IsRegularFile( NewFullPath ) )
{
ReadWriteMode = O_RDWR;
fd = open( NewFullPath, ReadWriteMode );
}
free( NewFullPath );
return fd;
}
int
CaseInsensitiveIsEqual( const char *String1, const char *String2 )
{
int LengthOfString1 = 0, LengthOfString2 = 0, EqualCharCount = 0;
if ( NULL == String1 || NULL == String2 )
{
return String1 == String2;
}
LengthOfString1 = strlen( String1 );
LengthOfString2 = strlen( String2 );
if ( LengthOfString1 != LengthOfString2 )
{
return 0;
}
EqualCharCount = 0;
while ( EqualCharCount < LengthOfString1 &&
tolower(String1[EqualCharCount]) == tolower(String2[EqualCharCount])
)
{
EqualCharCount++;
}
return EqualCharCount == LengthOfString1;
}
static char *
CaseInsensitiveFindFileName( const char *DirPath, const char *FileName
)
{
char *FoundFileName = NULL;
struct dirent *DirectoryEntry = NULL;
DIR *Directory = NULL;
if ( NULL == DirPath )
{
return NULL;
}
Directory = opendir( DirPath );
if ( NULL == Directory )
{
return NULL;
}
DirectoryEntry = readdir( Directory );
while ( NULL != DirectoryEntry )
{
if ( CaseInsensitiveIsEqual( FileName, DirectoryEntry->d_name ) )
{
FoundFileName = CopyString( DirectoryEntry->d_name );
break;
}
DirectoryEntry = readdir( Directory );
}
closedir( Directory );
return FoundFileName;
}
int
CaseInsensitiveFileOpen( /* const */ char *FullPath, int ReadWriteMode
)
{
char *DirectoryPath = NULL, *FileName = NULL;
int fd = open( FullPath, O_RDWR );
if ( fd >= 0 )
{
return fd;
}
DirectoryPath = CopyDirectory( FullPath );
if ( NULL == DirectoryPath )
{
return -1;
}
FileName = CopyFileName( FullPath );
if ( NULL == FileName )
{
free( DirectoryPath );
return -1;
}
else
{
char *FoundFileName = CaseInsensitiveFindFileName( DirectoryPath,
FileName );
fd = -1;
if ( NULL != FoundFileName )
{
fd = OpenDirFile( DirectoryPath, FoundFileName, ReadWriteMode );
free( FoundFileName );
}
}
free( DirectoryPath );
free( FileName );
return fd;
}