/*******************************************************************************
 *	BDir.cc	BEAM BDir access class
 *			T.Barnaby,	BEAM Ltd,	8/10/96
 * 	updated by	D.Korchagin,	CERN AB-BI-SW,	2007-08-31
 *******************************************************************************
 */
#include	<BDir.h>
#include	<dirent.h>
#include	<stdlib.h>
#include	<errno.h>
#include	<string.h>

#ifndef __Lynx__
static BString wildString;

static int wild(const dirent* e){
	BString	s = e->d_name;

	return s.compareWild(wildString);
}
#else
#endif

BDir::BDir(){
	osort = 0;
}

BDir::BDir(BString name){
	osort = 0;
	odirname = name;
	oerror = read();
}

BDir::~BDir(){
	clear();
}

void BDir::clear(){
	BIter	i;
	
	for(i = begin(); !isEnd(i); del(i)){
		delete get(i);
	}
}

BError BDir::open(BString name){
	odirname = name;
	oerror = read();
	return oerror;
}

BError BDir::error(){
	return oerror;
}

void BDir::setWild(BString wild){
	owild = wild;
	read();
}

void BDir::setSort(int sort){
	osort = sort;
	read();
}

BError BDir::read(){
	BError		err;
#ifndef __Lynx__
	struct dirent**	e;
	int		n;
	int		v;
	int		(*sel)(const struct dirent*) = 0;
#if __GNUC_MINOR__ >= 4
	int		(*cmp)(const dirent**, const dirent**) = 0;
#else
	int		(*cmp)(const void*, const void*) = 0;
#endif
#else
	struct dirent*	e;
#endif

	clear();

#ifndef __Lynx__
	if(owild != ""){
		wildString = owild;
		sel = wild;
	}
	if(osort == 1)
		cmp = alphasort;

	if((n = scandir(odirname, &e, sel, cmp)) < 0)
		return BError(strerror(errno));

	for(v = 0; v < n; v++){
		append(e[v]);
	}
	free(e);
	return err;
#else
	DIR* d;
	if ((d = opendir(odirname)) == NULL) return BError(strerror(errno));
	while (e = readdir(d)) append(e);
	closedir(d);
	return err;
#endif
}

BString BDir::entryName(BIter i){
	return get(i)->d_name;
}

struct stat BDir::entryStat(BIter i){
	struct stat	s = {0};

	lstat(odirname + "/" + entryName(i), &s);
	return s;
}

struct stat64 BDir::entryStat64(BIter i){
	struct stat64	s = {0};
#ifndef __Lynx__
	lstat64(odirname + "/" + entryName(i), &s);
#else
	// 32-bit limitation (LynxOS)
	struct stat	s32 = {0};
	lstat(odirname + "/" + entryName(i), &s32);
	s.st_dev = s32.st_dev;
	s.st_ino = s32.st_ino;
	s.st_mode = s32.st_mode;
	s.st_nlink = s32.st_nlink;
	s.st_uid = s32.st_uid;
	s.st_gid = s32.st_gid;
	s.st_rdev = s32.st_rdev;
	s.st_size = s32.st_size;
	s.st_atime = s32.st_atime;
	s.st_mtime = s32.st_mtime;
	s.st_ctime = s32.st_ctime;
	s.st_blksize = s32.st_blksize;
	s.st_blocks = s32.st_blocks;
	s.st_attr = 0;
#endif
	return s;
}
