rohin1702
asked on
struct dirent not reading proper file name
hi..
i am using struct dirent to search for a given file in a directory.the trouble is that if the name of the file is LP36-3_27FP.phd.1 it is reading it as LP-3~1.1 (and some are taking hexadecimal value) and hence strcmpi is not working.Can anyone help me solve my problem?
This is clearly Windoze. Are you running as a DOS only tool or full Win32?
Under Win32 you can use FindFirstFile etc. Under DOS you can use the equivalent under assembly:
// Windows structures for long file name handling.
#ifndef WIN32
// Look for '714e' in MSDN to find the descriptions.
typedef struct FILETIME
{
ulong dwLowDateTime;
ulong dwHighDateTime;
}FILETIME;
typedef struct WIN32_FIND_DATA
{
ulong dwFileAttributes;
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
ulong nFileSizeHigh;
ulong nFileSizeLow;
ulong dwReserved0;
ulong dwReserved1;
char cFileName[ _MAX_PATH ];
char cAlternateFileName[ 14 ];
} WIN32_FIND_DATA;
// The possible file attributes (from WINNT.H).
#define FILE_ATTRIBUTE_READONLY 0x00000001
#define FILE_ATTRIBUTE_HIDDEN 0x00000002
#define FILE_ATTRIBUTE_SYSTEM 0x00000004
#define FILE_ATTRIBUTE_DIRECTORY 0x00000010
#define FILE_ATTRIBUTE_ARCHIVE 0x00000020
#define FILE_ATTRIBUTE_NORMAL 0x00000080
#define FILE_ATTRIBUTE_TEMPORARY 0x00000100
#endif
// The windows (long names) versions;
static unsigned WIN_findfirst(const char * name, unsigned flags, WildFindT * found, long * handle);
static unsigned WIN_findnext(WildFindT * found, long * handle);
static void WIN_findclose(long handle);
// Translate the long found structure into the short.
void WIN_TranslateFileDetails ( WIN32_FIND_DATA * longFound, WildFindT * found);
// Get the short version of a long file name.
void WIN_ShortName ( char * longName, char * shortName );
// The windows (long names) versions;
unsigned WIN_findfirst(const char * name, unsigned flags, WildFindT * found, long * handle)
{
WIN32_FIND_DATA longFound;
bool noMore = true;
#ifdef WIN32
*handle = (long)FindFirstFile ( name, &longFound );
if ( *handle != -1 )
{
// Fill in the found structure.
WIN_TranslateFileDetails ( &longFound, found );
noMore = false;
#ifdef _DEBUG
Finds += 1;
// TFPRINT(("WIN_findfirst '%s'->'%s' (%d) [%d]", name, longFound.cFileName, outregs.x.ax, Finds));
// DBG(Finds);
#endif
}
#else
WIN32_FIND_DATA far * farFound = &longFound;
char far * farName = (char far *)name;
union REGS inregs, outregs;
struct SREGS segregs;
/*
mov ax, 714Eh ; Find First File
mov ch, MustMatchAttrs ; see below
mov cl, SearchAttrs ; see below
mov dx, seg Filename ; see below
mov ds, dx
mov dx, offset Filename
mov di, seg FindData ; see below
mov es, di
mov di, offset FindData
mov si, DateTimeFormat ; see below
int 21h
jc error
mov [Handle], ax ; search handle
mov [ConversionCode], cx ; Unicode to OEM/ANSI conversion OK?
*/
// Start them clear.
Clear (inregs);
Clear (segregs);
// Setup the parameters.
inregs.x.ax = 0x714E; // Find First File
inregs.h.ch = 0; // Match all.
inregs.h.cl = (uchar)flags;
segregs.ds = FP_SEG( farName );
inregs.x.dx = FP_OFF( farName );
segregs.es = FP_SEG( farFound );
inregs.x.di = FP_OFF( farFound );
inregs.x.si = 1; // Date/Time format
intdosx( &inregs, &outregs, &segregs ); // DoIt
if ( outregs.x.cflag == 0 )
{
// Fill in the found structure.
WIN_TranslateFileDetails ( &longFound, found );
// Save the handle.
*handle = outregs.x.ax;
noMore = false;
#ifdef _DEBUG
Finds += 1;
// TFPRINT(("WIN_findfirst '%s'->'%s' (%d) [%d]", name, longFound.cFileName, outregs.x.ax, Finds));
// DBG(Finds);
#endif
}
#endif
return ( noMore );
}
// The windows (long names) versions;
unsigned WIN_findnext(WildFindT * found, long * handle)
{
WIN32_FIND_DATA longFound;
bool noMore = true;
#ifdef WIN32
if ( FindNextFile ( (HANDLE)*handle, &longFound ) )
{
// Fill in the found structure.
WIN_TranslateFileDetails ( &longFound, found );
noMore = false;
}
else
{
// Done with that one.
WIN_findclose(*handle);
// Fill in an invalid handle.
*handle = 0;
}
#else
union REGS inregs, outregs;
struct SREGS segregs;
WIN32_FIND_DATA far * farFound = &longFound;
/*
mov ax, 714Fh ; Find Next File
mov bx, Handle ; see below
mov di, seg FindData ; see below
mov es, di
mov di, offset FindData
mov si, DateTimeFormat ; see below
int 21h
jc error
mov [ConversionCode], cx ; Unicode to OEM/ANSI conversion OK?
*/
// Start them clear.
Clear (inregs);
Clear (segregs);
// Setup the parameters.
inregs.x.ax = 0x714F; // Find First File
inregs.x.bx = (ushort)*handle; // The handle.
segregs.es = FP_SEG( farFound );
inregs.x.di = FP_OFF( farFound );
inregs.x.si = 1; // Date/Time format
intdosx( &inregs, &outregs, &segregs ); // DoIt
if ( outregs.x.cflag == 0 )
{
// TFPRINT(("\tWIN_findnext -> '%s' (%d)", longFound.cFileName, *handle ));
// Fill in the found structure.
WIN_TranslateFileDetails ( &longFound, found );
noMore = false;
}
else
{
// Done with that one.
WIN_findclose(*handle);
// Fill in an invalid handle.
*handle = 0;
}
#endif
return ( noMore );
}
// The windows (long names) versions;
void WIN_findclose(long handle)
{
#ifdef WIN32
FindClose ((HANDLE)handle);
#else
union REGS inregs, outregs;
/*
mov ax, 71A1h ; Find Close
mov bx, Handle ; see below
int 21h
*/
if ( handle != 0 )
{
// Start them clear.
Clear (inregs);
// Setup the parameters.
inregs.x.ax = 0x71A1; // Find close
inregs.x.bx = (ushort)handle; // The handle.
intdos( &inregs, &outregs ); // DoIt
#ifdef _DEBUG
Finds -= 1;
// TFPRINT(("WIN_findclose (%d) [%d]", handle, Finds));
// DBG(Finds);
#endif
}
else
{
TFPRINT(("WIN_findclose BAD!!!"));
}
#endif
}
// Get the short version of a long file name.
void WIN_ShortName ( char * longName, char * shortName )
{
#ifdef WIN32
GetShortPathName( longName, shortName, _MAX_PATH );
#else
union REGS inregs, outregs;
struct SREGS segregs;
char far * farName = longName;
char far * farShortName = shortName;
/*
mov ax, 7160h
mov cl, 1 ; Get Short Path Name
mov ch, SubstExpand ; see below
mov si, seg SourcePath ; see below
mov ds, si
mov si, offset SourcePath
mov di, seg DestPath ; see below
mov es, di
mov di, offset DestPath
int 21h
jc error
*/
// Start them clear.
Clear (inregs);
Clear (segregs);
// Setup the parameters.
inregs.x.ax = 0x7160; // Get Short Path Name
inregs.h.ch = 0x80; // Dont translate SUBST.
inregs.h.cl = 1; // Get Short Path Name (subcode)
segregs.ds = FP_SEG( farName );
inregs.x.si = FP_OFF( farName );
segregs.es = FP_SEG( farShortName );
inregs.x.di = FP_OFF( farShortName );
intdosx( &inregs, &outregs, &segregs ); // DoIt
if ( outregs.x.cflag != 0 )
{
// Bad!
shortName[0] = '\0';
}
#endif
}
// Are long names available?
static bool LongNamesAvailable ( void )
{
#ifdef WIN32
return true;
#else
bool available = true;
// First check dos version (must be >= 7.1).
int dosVer = bdos( 0x30, 0, 0 );
int major = dosVer & 0xff;
int minor = dosVer >> 8;
// Dos version must be >= 7.1
if ( major < 7 || ( major == 7 && minor < 1 ) )
{
// NO!
available = false;
}
/*
Later use 71a0 too.
union REGS inregs, outregs;
But not like this!!! This is dangerous!
_asm {
mov ax,71A0h
int 21h
mov [OurError],al
}
*/
return available;
#endif
}
// Translate the long found structure into the short.
void WIN_TranslateFileDetails ( WIN32_FIND_DATA * longFound, WildFindT * found)
{
//struct tm time;
// Translate the attributes.
found->attrib = (char)(longFound->dwFileAt tributes & 0xff);
// Translate the date and time.
found->wr_date = (ushort)(longFound->ftLast WriteTime. dwLowDateT ime >> 16);
found->wr_time = (ushort)(longFound->ftLast WriteTime. dwLowDateT ime & 0xffffL);
// The file size.
if ( longFound->nFileSizeHigh == 0 )
{
// Give them the low file size.
found->size = longFound->nFileSizeLow;
}
else
{
// Give them max.
found->size = 0x7fffffffL;
}
// The name.
strcpy ( found->name, longFound->cFileName );
}
// Find the first/next file.
bool FindFile ( bool first, Wild * stack, bool longNames, int findFlags )
{
bool noMore = true;
#ifndef WIN32
if ( longNames )
{
#endif
// Windows one ( if we can ).
noMore = (first ? WIN_findfirst( stack->fullName,
findFlags,
&stack->search[stack->dept h].found,
&stack->search[stack->dept h].handle) :
WIN_findnext( &stack->search[stack->dept h].found,
&stack->search[stack->dept h].handle) ) != 0;
#ifndef WIN32
}
else
{
// Normal DOS one.
noMore = (first ? _dos_findfirst( stack->fullName,
findFlags,
(struct find_t *)&stack->search[stack->de pth].found ):
_dos_findnext( (struct find_t *)&stack->search[stack->de pth].found )) != 0;
// Short name is same as long name.
strcpy ( stack->search[stack->depth ].found.sh ortName,
stack->search[stack->depth ].found.na me );
}
#endif
return noMore;
}
Sorry but there is more code here than I intended but I hope some of it is of use. Note that this process will still not work under NT ore XP or 2K. Only the standard 32bit calls will work there as this functionality is provided by DLLs which are not available under dos. It will work fine under 95/98/Me.
Paul
Under Win32 you can use FindFirstFile etc. Under DOS you can use the equivalent under assembly:
// Windows structures for long file name handling.
#ifndef WIN32
// Look for '714e' in MSDN to find the descriptions.
typedef struct FILETIME
{
ulong dwLowDateTime;
ulong dwHighDateTime;
}FILETIME;
typedef struct WIN32_FIND_DATA
{
ulong dwFileAttributes;
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
ulong nFileSizeHigh;
ulong nFileSizeLow;
ulong dwReserved0;
ulong dwReserved1;
char cFileName[ _MAX_PATH ];
char cAlternateFileName[ 14 ];
} WIN32_FIND_DATA;
// The possible file attributes (from WINNT.H).
#define FILE_ATTRIBUTE_READONLY 0x00000001
#define FILE_ATTRIBUTE_HIDDEN 0x00000002
#define FILE_ATTRIBUTE_SYSTEM 0x00000004
#define FILE_ATTRIBUTE_DIRECTORY 0x00000010
#define FILE_ATTRIBUTE_ARCHIVE 0x00000020
#define FILE_ATTRIBUTE_NORMAL 0x00000080
#define FILE_ATTRIBUTE_TEMPORARY 0x00000100
#endif
// The windows (long names) versions;
static unsigned WIN_findfirst(const char * name, unsigned flags, WildFindT * found, long * handle);
static unsigned WIN_findnext(WildFindT * found, long * handle);
static void WIN_findclose(long handle);
// Translate the long found structure into the short.
void WIN_TranslateFileDetails ( WIN32_FIND_DATA * longFound, WildFindT * found);
// Get the short version of a long file name.
void WIN_ShortName ( char * longName, char * shortName );
// The windows (long names) versions;
unsigned WIN_findfirst(const char * name, unsigned flags, WildFindT * found, long * handle)
{
WIN32_FIND_DATA longFound;
bool noMore = true;
#ifdef WIN32
*handle = (long)FindFirstFile ( name, &longFound );
if ( *handle != -1 )
{
// Fill in the found structure.
WIN_TranslateFileDetails ( &longFound, found );
noMore = false;
#ifdef _DEBUG
Finds += 1;
// TFPRINT(("WIN_findfirst '%s'->'%s' (%d) [%d]", name, longFound.cFileName, outregs.x.ax, Finds));
// DBG(Finds);
#endif
}
#else
WIN32_FIND_DATA far * farFound = &longFound;
char far * farName = (char far *)name;
union REGS inregs, outregs;
struct SREGS segregs;
/*
mov ax, 714Eh ; Find First File
mov ch, MustMatchAttrs ; see below
mov cl, SearchAttrs ; see below
mov dx, seg Filename ; see below
mov ds, dx
mov dx, offset Filename
mov di, seg FindData ; see below
mov es, di
mov di, offset FindData
mov si, DateTimeFormat ; see below
int 21h
jc error
mov [Handle], ax ; search handle
mov [ConversionCode], cx ; Unicode to OEM/ANSI conversion OK?
*/
// Start them clear.
Clear (inregs);
Clear (segregs);
// Setup the parameters.
inregs.x.ax = 0x714E; // Find First File
inregs.h.ch = 0; // Match all.
inregs.h.cl = (uchar)flags;
segregs.ds = FP_SEG( farName );
inregs.x.dx = FP_OFF( farName );
segregs.es = FP_SEG( farFound );
inregs.x.di = FP_OFF( farFound );
inregs.x.si = 1; // Date/Time format
intdosx( &inregs, &outregs, &segregs ); // DoIt
if ( outregs.x.cflag == 0 )
{
// Fill in the found structure.
WIN_TranslateFileDetails ( &longFound, found );
// Save the handle.
*handle = outregs.x.ax;
noMore = false;
#ifdef _DEBUG
Finds += 1;
// TFPRINT(("WIN_findfirst '%s'->'%s' (%d) [%d]", name, longFound.cFileName, outregs.x.ax, Finds));
// DBG(Finds);
#endif
}
#endif
return ( noMore );
}
// The windows (long names) versions;
unsigned WIN_findnext(WildFindT * found, long * handle)
{
WIN32_FIND_DATA longFound;
bool noMore = true;
#ifdef WIN32
if ( FindNextFile ( (HANDLE)*handle, &longFound ) )
{
// Fill in the found structure.
WIN_TranslateFileDetails ( &longFound, found );
noMore = false;
}
else
{
// Done with that one.
WIN_findclose(*handle);
// Fill in an invalid handle.
*handle = 0;
}
#else
union REGS inregs, outregs;
struct SREGS segregs;
WIN32_FIND_DATA far * farFound = &longFound;
/*
mov ax, 714Fh ; Find Next File
mov bx, Handle ; see below
mov di, seg FindData ; see below
mov es, di
mov di, offset FindData
mov si, DateTimeFormat ; see below
int 21h
jc error
mov [ConversionCode], cx ; Unicode to OEM/ANSI conversion OK?
*/
// Start them clear.
Clear (inregs);
Clear (segregs);
// Setup the parameters.
inregs.x.ax = 0x714F; // Find First File
inregs.x.bx = (ushort)*handle; // The handle.
segregs.es = FP_SEG( farFound );
inregs.x.di = FP_OFF( farFound );
inregs.x.si = 1; // Date/Time format
intdosx( &inregs, &outregs, &segregs ); // DoIt
if ( outregs.x.cflag == 0 )
{
// TFPRINT(("\tWIN_findnext -> '%s' (%d)", longFound.cFileName, *handle ));
// Fill in the found structure.
WIN_TranslateFileDetails ( &longFound, found );
noMore = false;
}
else
{
// Done with that one.
WIN_findclose(*handle);
// Fill in an invalid handle.
*handle = 0;
}
#endif
return ( noMore );
}
// The windows (long names) versions;
void WIN_findclose(long handle)
{
#ifdef WIN32
FindClose ((HANDLE)handle);
#else
union REGS inregs, outregs;
/*
mov ax, 71A1h ; Find Close
mov bx, Handle ; see below
int 21h
*/
if ( handle != 0 )
{
// Start them clear.
Clear (inregs);
// Setup the parameters.
inregs.x.ax = 0x71A1; // Find close
inregs.x.bx = (ushort)handle; // The handle.
intdos( &inregs, &outregs ); // DoIt
#ifdef _DEBUG
Finds -= 1;
// TFPRINT(("WIN_findclose (%d) [%d]", handle, Finds));
// DBG(Finds);
#endif
}
else
{
TFPRINT(("WIN_findclose BAD!!!"));
}
#endif
}
// Get the short version of a long file name.
void WIN_ShortName ( char * longName, char * shortName )
{
#ifdef WIN32
GetShortPathName( longName, shortName, _MAX_PATH );
#else
union REGS inregs, outregs;
struct SREGS segregs;
char far * farName = longName;
char far * farShortName = shortName;
/*
mov ax, 7160h
mov cl, 1 ; Get Short Path Name
mov ch, SubstExpand ; see below
mov si, seg SourcePath ; see below
mov ds, si
mov si, offset SourcePath
mov di, seg DestPath ; see below
mov es, di
mov di, offset DestPath
int 21h
jc error
*/
// Start them clear.
Clear (inregs);
Clear (segregs);
// Setup the parameters.
inregs.x.ax = 0x7160; // Get Short Path Name
inregs.h.ch = 0x80; // Dont translate SUBST.
inregs.h.cl = 1; // Get Short Path Name (subcode)
segregs.ds = FP_SEG( farName );
inregs.x.si = FP_OFF( farName );
segregs.es = FP_SEG( farShortName );
inregs.x.di = FP_OFF( farShortName );
intdosx( &inregs, &outregs, &segregs ); // DoIt
if ( outregs.x.cflag != 0 )
{
// Bad!
shortName[0] = '\0';
}
#endif
}
// Are long names available?
static bool LongNamesAvailable ( void )
{
#ifdef WIN32
return true;
#else
bool available = true;
// First check dos version (must be >= 7.1).
int dosVer = bdos( 0x30, 0, 0 );
int major = dosVer & 0xff;
int minor = dosVer >> 8;
// Dos version must be >= 7.1
if ( major < 7 || ( major == 7 && minor < 1 ) )
{
// NO!
available = false;
}
/*
Later use 71a0 too.
union REGS inregs, outregs;
But not like this!!! This is dangerous!
_asm {
mov ax,71A0h
int 21h
mov [OurError],al
}
*/
return available;
#endif
}
// Translate the long found structure into the short.
void WIN_TranslateFileDetails ( WIN32_FIND_DATA * longFound, WildFindT * found)
{
//struct tm time;
// Translate the attributes.
found->attrib = (char)(longFound->dwFileAt
// Translate the date and time.
found->wr_date = (ushort)(longFound->ftLast
found->wr_time = (ushort)(longFound->ftLast
// The file size.
if ( longFound->nFileSizeHigh == 0 )
{
// Give them the low file size.
found->size = longFound->nFileSizeLow;
}
else
{
// Give them max.
found->size = 0x7fffffffL;
}
// The name.
strcpy ( found->name, longFound->cFileName );
}
// Find the first/next file.
bool FindFile ( bool first, Wild * stack, bool longNames, int findFlags )
{
bool noMore = true;
#ifndef WIN32
if ( longNames )
{
#endif
// Windows one ( if we can ).
noMore = (first ? WIN_findfirst( stack->fullName,
findFlags,
&stack->search[stack->dept
&stack->search[stack->dept
WIN_findnext( &stack->search[stack->dept
&stack->search[stack->dept
#ifndef WIN32
}
else
{
// Normal DOS one.
noMore = (first ? _dos_findfirst( stack->fullName,
findFlags,
(struct find_t *)&stack->search[stack->de
_dos_findnext( (struct find_t *)&stack->search[stack->de
// Short name is same as long name.
strcpy ( stack->search[stack->depth
stack->search[stack->depth
}
#endif
return noMore;
}
Sorry but there is more code here than I intended but I hope some of it is of use. Note that this process will still not work under NT ore XP or 2K. Only the standard 32bit calls will work there as this functionality is provided by DLLs which are not available under dos. It will work fine under 95/98/Me.
Paul
See GetShortPathName function.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
What compiler are you on?
You could try system("dir/b >>dir.txt"); if on windows platform.
and read from that text file.One filename on one line.
dir/b gives you the bare filenames without the size etc. details and i redirect the output to a file dir.txt