This repository has been archived on 2023-07-11. You can view files and clone it, but cannot push or open issues or pull requests.
fte/s_direct.cpp

436 lines
11 KiB
C++
Raw Permalink Normal View History

/* s_direct.cpp
*
* Copyright (c) 1994-1996, Marko Macek
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
*/
// TODO: on OS/2 choose between UNIX and OS/2 style patterns (now OS/2 only)
// TODO: on OS/2 fetch multiple entries at once and cache them for speed
#include "fte.h"
#ifdef OS2
#define INCL_BASE
#include <os2.h>
#endif
#ifdef NT
#define WIN32_LEAN_AND_MEAN 1
#include <windows.h>
#endif
#if defined(DOSP32) || (defined(NT) && defined(USE_DIRENT)) // NT ?
# include "port.h"
#endif
#ifdef DJGPP
#include <sys/stat.h>
static int my_stat(const char *name, struct stat *s)
{
unsigned short f = _djstat_flags;
// speed up directory access by turning off unused stat functionality
_djstat_flags |= _STAT_INODE;
_djstat_flags |= _STAT_EXEC_EXT;
_djstat_flags |= _STAT_EXEC_MAGIC;
_djstat_flags |= _STAT_DIRSIZE;
//_djstat_flags |= _STAT_ROOT_TIME;
_djstat_flags &= ~_STAT_ROOT_TIME;
_djstat_flags |= _STAT_WRITEBIT;
int r = stat(name,s);
_djstat_flags = f;
return r;
}
#endif
FileInfo::FileInfo(char *Name, int Type, off_t Size, time_t MTime) {
name = new char[strlen (Name) + 1];
if (name)
strcpy(name, Name);
size = Size;
type = Type;
mtime = MTime;
}
FileInfo::~FileInfo() {
delete [] name;
}
FileFind::FileFind(const char *aDirectory, const char *aPattern, int aFlags) {
Directory = new char[strlen(aDirectory) + 1];
if (Directory) {
strcpy(Directory, aDirectory);
Slash(Directory, 0);
}
if (aPattern) {
Pattern = new char[strlen(aPattern) + 1];
if (Pattern)
strcpy(Pattern, aPattern);
} else {
Pattern = 0;
}
Flags = aFlags;
#if defined(USE_DIRENT)
//#if defined(UNIX) || defined(DOSP32) || defined(NT)
dir = 0;
#elif defined(OS2) && !defined(USE_DIRENT)
dir = 0;
#elif defined(NT) && !defined(USE_DIRENT)
dir = 0;
#endif
}
FileFind::~FileFind() {
delete [] Directory;
if (Pattern)
delete [] Pattern;
//#if defined(UNIX) || defined(DOSP32) || defined(NT)
#if defined(USE_DIRENT)
if (dir)
closedir(dir);
#elif defined(OS2) && !defined(USE_DIRENT)
if (dir)
DosFindClose(dir);
#elif defined(NT) && !defined(USE_DIRENT)
if (dir)
FindClose((HANDLE)dir);
#endif
}
int FileFind::FindFirst(FileInfo **fi) {
//#if defined(UNIX) || defined(NT) || defined(DOSP32)
#if defined(USE_DIRENT)
if (dir)
closedir(dir);
if ((dir = opendir(Directory)) == 0)
return -1;
return FindNext(fi);
#elif defined(OS2) && !defined(USE_DIRENT)
char fullpattern[MAXPATH];
HDIR hdir = HDIR_CREATE;
ULONG attr = FILE_ARCHIVED | FILE_READONLY;
ULONG count = 1;
FILEFINDBUF3 find; // need to improve to fetch multiple entries at once
char fullpath[MAXPATH];
char *name;
struct tm t;
int rc;
if (dir)
DosFindClose(dir);
if (Flags & ffDIRECTORY)
attr |= FILE_DIRECTORY;
if (Flags & ffHIDDEN)
attr |= FILE_HIDDEN | FILE_SYSTEM; // separate ?
if (Pattern)
JoinDirFile(fullpattern, Directory, Pattern);
else
JoinDirFile(fullpattern, Directory, "*");
if ((rc = DosFindFirst(fullpattern,
&hdir,
attr,
&find, sizeof(find),
&count,
FIL_STANDARD)) != 0)
{
//fprintf(stderr, "%s: %d\n\n", fullpattern, rc);
return -1;
}
dir = hdir;
if (count != 1)
return -1;
name = find.achName;
if (Flags & ffFULLPATH) {
JoinDirFile(fullpath, Directory, name);
name = fullpath;
}
memset((void *)&t, 0, sizeof(t));
t.tm_year = find.fdateLastWrite.year + 80; // ugh!
t.tm_mon = find.fdateLastWrite.month - 1;
t.tm_mday = find.fdateLastWrite.day;
t.tm_hour = find.ftimeLastWrite.hours;
t.tm_min = find.ftimeLastWrite.minutes;
t.tm_sec = find.ftimeLastWrite.twosecs * 2; // ugh!
t.tm_isdst = -1;
*fi = new FileInfo(name,
(find.attrFile & FILE_DIRECTORY) ? fiDIRECTORY : fiFILE,
find.cbFile,
mktime(&t));
return 0;
#elif defined(NT) && !defined(USE_DIRENT)
#if defined(USE_VCFIND)
char fullpattern[MAXPATH];
_finddata_t find; // need to improve to fetch multiple entries at once
char fullpath[MAXPATH];
char *name;
struct tm t;
int rc;
if (dir)
_findclose(dir);
/*if (Flags & ffDIRECTORY)
attr |= FILE_DIRECTORY;
if (Flags & ffHIDDEN)
attr |= FILE_HIDDEN | FILE_SYSTEM; // separate ?
*/
if (Pattern)
JoinDirFile(fullpattern, Directory, Pattern);
else
JoinDirFile(fullpattern, Directory, "*");
if ((rc = _findfirst(fullpattern, &find)) == -1)
{
// fprintf(stderr, "%s: %d\n\n", fullpattern, rc);
return -1;
}
dir = rc;
name = find.name;
if (Flags & ffFULLPATH) {
JoinDirFile(fullpath, Directory, name);
name = fullpath;
}
*fi = new FileInfo(name,
(find.attrib & _A_SUBDIR) ? fiDIRECTORY : fiFILE,
find.size,
find.time_create);
return 0;
#else
char fullpattern[MAXPATH];
WIN32_FIND_DATA find; // need to improve to fetch multiple entries at once
char fullpath[MAXPATH];
char *name;
struct tm t;
SYSTEMTIME st;
FILETIME localft; // needed for time conversion
int rc;
if (dir)
_findclose(dir);
/*if (Flags & ffDIRECTORY)
attr |= FILE_DIRECTORY;
if (Flags & ffHIDDEN)
attr |= FILE_HIDDEN | FILE_SYSTEM; // separate ?
*/
if (Pattern)
JoinDirFile(fullpattern, Directory, Pattern);
else
JoinDirFile(fullpattern, Directory, "*");
if ((rc = (int) FindFirstFile(fullpattern, &find)) < 0)
{
//fprintf(stderr, "%s: %d\n\n", fullpattern, rc);
return -1;
}
dir = rc;
name = find.cFileName;
if (Flags & ffFULLPATH) {
JoinDirFile(fullpath, Directory, name);
name = fullpath;
}
/*
* since filetime is in UTC format we need to convert it first to
* localtime and when we have "correct" time we can use it.
*/
FileTimeToLocalFileTime(&find.ftLastWriteTime, &localft);
FileTimeToSystemTime(&localft, &st);
t.tm_year = st.wYear - 1900;
t.tm_mon = st.wMonth - 1; // in system time january is 1...
t.tm_mday = st.wDay;
t.tm_hour = st.wHour;
t.tm_min = st.wMinute;
t.tm_sec = st.wSecond;
t.tm_isdst = -1;
*fi = new FileInfo(name,
(find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? fiDIRECTORY : fiFILE,
find.nFileSizeLow, // !!!
mktime(&t));
return 0;
#endif
#endif
}
int FileFind::FindNext(FileInfo **fi) {
//#if defined(UNIX) || defined(NT) || defined(DOSP32)
#if defined(USE_DIRENT)
struct dirent *dent;
char fullpath[MAXPATH];
char *name;
*fi = 0;
again:
if ((dent = readdir(dir)) == NULL)
return -1;
name = dent->d_name;
if (name[0] == '.')
if (!(Flags & ffHIDDEN))
goto again;
if (Pattern && fnmatch(Pattern, dent->d_name, 0) != 0)
goto again;
if (Flags & ffFULLPATH) {
JoinDirFile(fullpath, Directory, dent->d_name);
name = fullpath;
}
if (Flags & ffFAST) {
*fi = new FileInfo(name, fiUNKNOWN, 0, 0);
} else {
struct stat st;
if (!(Flags & ffFULLPATH)) // need it now
JoinDirFile(fullpath, Directory, dent->d_name);
if (
#if defined(DJGPP)
my_stat
#elif defined(UNIX) // must use lstat if available
lstat
#else
stat
#endif
(fullpath, &st) != 0 && 0)
goto again;
if (!(Flags & ffDIRECTORY) && S_ISDIR(st.st_mode))
goto again;
*fi = new FileInfo(name,
S_ISDIR(st.st_mode) ? fiDIRECTORY : fiFILE,
st.st_size,
st.st_mtime);
}
//printf("ok\n");
return 0;
#elif defined(OS2) && !defined(USE_DIRENT)
ULONG count = 1;
FILEFINDBUF3 find; // need to improve to fetch multiple entries at once
char fullpath[MAXPATH];
char *name;
struct tm t;
int rc;
if ((rc = DosFindNext(dir,
&find, sizeof(find),
&count)) != 0)
{
//fprintf(stderr, "%d\n\n", rc);
return -1;
}
if (count != 1)
return -1;
name = find.achName;
if (Flags & ffFULLPATH) {
JoinDirFile(fullpath, Directory, name);
name = fullpath;
}
memset((void *)&t, 0, sizeof(t));
t.tm_year = find.fdateLastWrite.year + 80;
t.tm_mon = find.fdateLastWrite.month - 1;
t.tm_mday = find.fdateLastWrite.day;
t.tm_hour = find.ftimeLastWrite.hours;
t.tm_min = find.ftimeLastWrite.minutes;
t.tm_sec = find.ftimeLastWrite.twosecs * 2; // ugh!
t.tm_isdst = -1;
*fi = new FileInfo(name,
(find.attrFile & FILE_DIRECTORY) ? fiDIRECTORY : fiFILE,
find.cbFile,
mktime(&t));
return 0;
#elif defined(NT) && !defined(USE_DIRENT)
#if defined(USE_VCFIND)
_finddata_t find;
char fullpath[MAXPATH];
char *name;
struct tm t;
int rc;
if ((rc = _findnext(dir,
&find)) != 0)
{
// fprintf(stderr, "%d\n\n", rc);
return -1;
}
name = find.name;
if (Flags & ffFULLPATH) {
JoinDirFile(fullpath, Directory, name);
name = fullpath;
}
*fi = new FileInfo(name,
(find.attrib & _A_SUBDIR) ? fiDIRECTORY : fiFILE,
find.size,
find.time_create);
return 0;
#else
WIN32_FIND_DATA find;
char fullpath[MAXPATH];
char *name;
struct tm t;
SYSTEMTIME st;
FILETIME localft; // needed for time conversion
int rc;
if ((rc = FindNextFile((HANDLE)dir,
&find)) != TRUE)
{
//fprintf(stderr, "%d\n\n", rc);
return -1;
}
name = find.cFileName;
if (Flags & ffFULLPATH) {
JoinDirFile(fullpath, Directory, name);
name = fullpath;
}
/*
* since filetime is in UTC format we need to convert it first to
* localtime and when we have "correct" time we can use it.
*/
FileTimeToLocalFileTime(&find.ftLastWriteTime, &localft);
FileTimeToSystemTime(&localft, &st);
t.tm_year = st.wYear - 1900;
t.tm_mon = st.wMonth - 1; // in system time january is 1...
t.tm_mday = st.wDay;
t.tm_hour = st.wHour;
t.tm_min = st.wMinute;
t.tm_sec = st.wSecond;
t.tm_isdst = -1;
*fi = new FileInfo(name,
(find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? fiDIRECTORY : fiFILE,
find.nFileSizeLow,
mktime(&t));
return 0;
#endif
// put code here
#endif
}