diff --git a/src/sbbs3/bat_xfer.cpp b/src/sbbs3/bat_xfer.cpp
index 461eb982c9ff21038ca494293bbe88546b45e07c..0256b69d488d93e3ac698ae6322041eda1873aa2 100644
--- a/src/sbbs3/bat_xfer.cpp
+++ b/src/sbbs3/bat_xfer.cpp
@@ -552,8 +552,8 @@ void sbbs_t::batch_upload()
     char	str1[256],str2[256];
 	uint	i,j,x,y;
     file_t	f;
-    struct	_finddata_t ff;
-	long	ff_handle;
+	DIR*	dir;
+	DIRENT*	dirent;
 
 	for(i=0;i<batup_total;) {
 		curdirnum=batup_dir[i]; 			/* for ARS */
@@ -584,33 +584,33 @@ void sbbs_t::batch_upload()
 		else i++; }
 	if(cfg.upload_dir==INVALID_DIR)
 		return;
-	sprintf(str1,"%s*.*",cfg.temp_dir);
-	ff_handle=_findfirst(str1,&ff);
-	while(ff_handle!=-1) {
-		if(!(ff.attrib&_A_SUBDIR)) {
-			memset(&f,0,sizeof(file_t));
-			f.dir=cfg.upload_dir;
-			padfname(ff.name,f.name);
-			strupr(f.name);
-			sprintf(str1,"%s%s",cfg.temp_dir,ff.name);
-			for(x=0;x<usrlibs;x++) {
-				for(y=0;y<usrdirs[x];y++)
-					if(cfg.dir[usrdir[x][y]]->misc&DIR_DUPES
-						&& findfile(&cfg,usrdir[x][y],f.name))
-						break;
-				if(y<usrdirs[x])
-					break; }
-			sprintf(str2,"%s%s",cfg.dir[f.dir]->path,ff.name);
-			if(x<usrlibs || fexist(str2)) {
-				bprintf(text[FileAlreadyOnline],f.name);
-				remove(str1); }
-			else {
-				mv(str1,str2,0);
-				uploadfile(&f); }
+	dir=opendir(cfg.temp_dir);
+	while((dirent=readdir(dir))!=NULL) {
+		sprintf(str1,"%s%s",cfg.temp_dir,dirent->d_name);
+		if(isdir(str1))
+			continue;
+		memset(&f,0,sizeof(file_t));
+		f.dir=cfg.upload_dir;
+		padfname(dirent->d_name,f.name);
+		strupr(f.name);
+		for(x=0;x<usrlibs;x++) {
+			for(y=0;y<usrdirs[x];y++)
+				if(cfg.dir[usrdir[x][y]]->misc&DIR_DUPES
+					&& findfile(&cfg,usrdir[x][y],f.name))
+					break;
+			if(y<usrdirs[x])
+				break; 
 		}
-		if(_findnext(ff_handle, &ff)!=0) {
-			_findclose(ff_handle);
-			ff_handle=-1; } }
+		sprintf(str2,"%s%s",cfg.dir[f.dir]->path,dirent->d_name);
+		if(x<usrlibs || fexist(str2)) {
+			bprintf(text[FileAlreadyOnline],f.name);
+			remove(str1); 
+		} else {
+			mv(str1,str2,0);
+			uploadfile(&f); 
+		}
+	}
+	closedir(dir);
 }
 
 /****************************************************************************/
diff --git a/src/sbbs3/file.cpp b/src/sbbs3/file.cpp
index fe4d8162ec659259919a4adacf7099c6bb1aadb7..66bd282192b5956454bd74e761ec5d5415db7076 100644
--- a/src/sbbs3/file.cpp
+++ b/src/sbbs3/file.cpp
@@ -272,30 +272,26 @@ BOOL filematch(char *filename, char *filespec)
 /****************************************************************************/
 /* Deletes all files in dir 'path' that match file spec 'spec'              */
 /****************************************************************************/
-int sbbs_t::delfiles(char *inpath, char *spec)
+uint sbbs_t::delfiles(char *inpath, char *spec)
 {
-	char	str[256],path[128];
-    int		files=0;
-    struct	_finddata_t ff;
-	long	ff_handle;
-
+	char	path[MAX_PATH];
+    uint	i,files=0;
+	glob_t	g;
 
 	strcpy(path,inpath);
 	backslash(path);
-	sprintf(str,"%s%s",path,spec);
-	ff_handle=_findfirst(str,&ff);
-	while(ff_handle!=-1) {
-		if(!(ff.attrib&_A_SUBDIR)) { /* not a directory */
-			sprintf(str,"%s%s",path,ff.name);
-			CHMOD(str,S_IWRITE);	// Incase it's been marked RDONLY
-			if(remove(str))
-				errormsg(WHERE,ERR_REMOVE,str,0);
-			else
-				files++;
-		}
-		if(_findnext(ff_handle,&ff)!=0) {
-			_findclose(ff_handle);
-			ff_handle=-1; } }
+	strcat(path,spec);
+	glob(path,0,NULL,&g);
+	for(i=0;i<g.gl_pathc;i++) {
+		if(isdir(g.gl_pathv[i]))
+			continue;
+		CHMOD(g.gl_pathv[i],S_IWRITE);	// Incase it's been marked RDONLY
+		if(remove(g.gl_pathv[i]))
+			errormsg(WHERE,ERR_REMOVE,g.gl_pathv[i],0);
+		else
+			files++;
+	}
+	globfree(&g);
 	return(files);
 }
 
diff --git a/src/sbbs3/ftpsrvr.c b/src/sbbs3/ftpsrvr.c
index 2d5e3d17b821b4a9e74acce4acbde75cc2f4994a..ab1b766abce968e9d329ea7be44dc3282c9c0f82 100644
--- a/src/sbbs3/ftpsrvr.c
+++ b/src/sbbs3/ftpsrvr.c
@@ -37,7 +37,6 @@
 
 /* Platform-specific headers */
 #ifdef _WIN32
-	#include <io.h>			/* _findfirst */
 	#include <share.h>		/* SH_DENYNO */
 	#include <direct.h>		/* _mkdir/_rmdir() */
 	#include <process.h>	/* _beginthread */
@@ -1203,13 +1202,12 @@ static void ctrl_thread(void* arg)
 	time_t		logintime;
 	time_t		lastactive;
 	file_t		f;
+	glob_t		g;
 	node_t		node;
 	client_t	client;
 	struct tm	tm;
 	struct tm *	tm_p;
 	struct tm 	cur_tm;
-	long		ff_handle;
-    struct _finddata_t ff;
 
 	thread_up();
 
@@ -1730,36 +1728,34 @@ static void ctrl_thread(void* arg)
 				sprintf(path,"%s%s",local_dir, *p ? p : "*.*");
 				lprintf("%04d %s listing: %s", sock, user.alias, path);
 				sockprintf(sock, "150 Directory of %s%s", local_dir, p);
-
-				ff_handle=_findfirst(path,&ff);
-				while(ff_handle!=-1) {
+			
+				glob(path,0,NULL,&g);
+				for(i=0;i<(int)g.gl_pathc;i++) {
 					if(detail) {
-						f.size=ff.size;
-						tm_p=localtime(&ff.time_write);
+						f.size=flength(g.gl_pathv[i]);
+						t=fdate(g.gl_pathv[i]);
+						tm_p=localtime(&t);
 						if(tm_p==NULL)
 							memset(&tm,0,sizeof(tm));
 						else
 							tm=*tm_p;
 						fprintf(fp,"%crw-r--r--   1 %-8s local %9ld %s %2d "
-							,ff.attrib&_A_SUBDIR ? 'd':'-'
+							,isdir(g.gl_pathv[i]) ? 'd':'-'
 							,scfg.sys_id
 							,f.size
 							,mon[tm.tm_mon],tm.tm_mday);
 						if(tm.tm_year==cur_tm.tm_year)
 							fprintf(fp,"%02d:%02d %s\r\n"
 								,tm.tm_hour,tm.tm_min
-								,ff.name);
+								,getfname(g.gl_pathv[i]));
 						else
 							fprintf(fp,"%5d %s\r\n"
 								,1900+tm.tm_year
-								,ff.name);
+								,getfname(g.gl_pathv[i]));
 					} else
-						fprintf(fp,"%s\r\n",ff.name);
-					if(_findnext(ff_handle,&ff)!=0) {
-						_findclose(ff_handle);
-						ff_handle=-1; 
-					} 
+						fprintf(fp,"%s\r\n",g.gl_pathv[i]);
 				}
+				globfree(&g);
 				fclose(fp);
 				filexfer(&data_addr,sock,pasv_sock,&data_sock,fname,0L
 					,&transfer_inprogress,&transfer_aborted,TRUE,TRUE
@@ -2184,49 +2180,48 @@ static void ctrl_thread(void* arg)
 					,sock,user.alias,scfg.lib[lib]->sname,scfg.dir[dir]->code);
 
 				sprintf(path,"%s%s",scfg.dir[dir]->path,*p ? p : "*");
-				ff_handle=_findfirst(path,&ff);
-				while(ff_handle!=-1) {
-					sprintf(path,"%s%s",scfg.dir[dir]->path,ff.name);
-					GetShortPathName(path, str, sizeof(str));
-					p=strrchr(str,'\\');
-					if(p==NULL) p=str;
-					else p++;
-					padfname(p,f.name);
+				glob(path,0,NULL,&g);
+				for(i=0;i<(int)g.gl_pathc;i++) {
+					if(isdir(g.gl_pathv[i]))
+						continue;
+#ifdef _WIN32
+					GetShortPathName(g.gl_pathv[i], str, sizeof(str));
+#else
+					strcpy(str,g.gl_pathv[i]);
+#endif
+					padfname(getfname(str),f.name);
 					strupr(f.name);
 					f.dir=dir;
-					if(!(ff.attrib&_A_SUBDIR) /* not a directory */
-						&& ((filedat=getfileixb(&scfg,&f))==TRUE 
-							|| startup->options&FTP_OPT_DIR_FILES)) { 
-						if(detail) {
-							f.size=ff.size;
-							getfiledat(&scfg,&f);
-							tm_p=localtime(&ff.time_write);
-							if(tm_p==NULL)
-								memset(&tm,0,sizeof(tm));
-							else
-								tm=*tm_p;
-							fprintf(fp,"-rw-r--r--   1 %-*s %-8s %9ld %s %2d "
-								,NAME_LEN
-								,filedat ? dotname(f.uler,str) : scfg.sys_id
-								,scfg.dir[dir]->code
-								,f.size
-								,mon[tm.tm_mon],tm.tm_mday);
-							if(tm.tm_year==cur_tm.tm_year)
-								fprintf(fp,"%02d:%02d %s\r\n"
-									,tm.tm_hour,tm.tm_min
-									,ff.name);
-							else
-								fprintf(fp,"%5d %s\r\n"
-									,1900+tm.tm_year
-									,ff.name);
-						} else
-							fprintf(fp,"%s\r\n",ff.name);
-					}
-					if(_findnext(ff_handle,&ff)!=0) {
-						_findclose(ff_handle);
-						ff_handle=-1; 
-					} 
+					if((filedat=getfileixb(&scfg,&f))==FALSE
+						&& !(startup->options&FTP_OPT_DIR_FILES))
+						continue;
+					if(detail) {
+						f.size=flength(g.gl_pathv[i]);
+						getfiledat(&scfg,&f);
+						t=fdate(g.gl_pathv[i]);
+						tm_p=localtime(&t);
+						if(tm_p==NULL)
+							memset(&tm,0,sizeof(tm));
+						else
+							tm=*tm_p;
+						fprintf(fp,"-rw-r--r--   1 %-*s %-8s %9ld %s %2d "
+							,NAME_LEN
+							,filedat ? dotname(f.uler,str) : scfg.sys_id
+							,scfg.dir[dir]->code
+							,f.size
+							,mon[tm.tm_mon],tm.tm_mday);
+						if(tm.tm_year==cur_tm.tm_year)
+							fprintf(fp,"%02d:%02d %s\r\n"
+								,tm.tm_hour,tm.tm_min
+								,getfname(g.gl_pathv[i]));
+						else
+							fprintf(fp,"%5d %s\r\n"
+								,1900+tm.tm_year
+								,getfname(g.gl_pathv[i]));
+					} else
+						fprintf(fp,"%s\r\n",getfname(g.gl_pathv[i]));
 				}
+				globfree(&g);
 			} else
 				strcpy(fname,"NUL");
 
@@ -2433,26 +2428,26 @@ static void ctrl_thread(void* arg)
 					}
 				} else {
 					sprintf(cmd,"%s*.*",scfg.dir[dir]->path);
-					ff_handle=_findfirst(cmd,&ff);
-					while(ff_handle!=-1) {
-						sprintf(cmd,"%s%s",scfg.dir[dir]->path,ff.name);
-						GetShortPathName(cmd, str, sizeof(str));
-						p=strrchr(str,'\\');
-						if(p==NULL) p=str;
-						else p++;
-						padfname(p,f.name);
+					glob(cmd,0,NULL,&g);
+					for(i=0;i<(int)g.gl_pathc;i++) {
+						if(isdir(g.gl_pathv[i]))
+							continue;
+#ifdef _WIN32
+						GetShortPathName(g.gl_pathv[i], str, sizeof(str));
+#else
+						strcpy(str,g.gl_pathv[i]);
+#endif
+						padfname(getfname(str),f.name);
 						strupr(f.name);
 						f.dir=dir;
-						if(!(ff.attrib&_A_SUBDIR) && getfileixb(&scfg,&f)) { /* not a directory */
-							f.size=ff.size;
+						if(getfileixb(&scfg,&f)) {
+							f.size=flength(g.gl_pathv[i]);
 							getfiledat(&scfg,&f);
-							fprintf(fp,"%-*s %s\r\n",INDEX_FNAME_LEN,ff.name,f.desc);
+							fprintf(fp,"%-*s %s\r\n",INDEX_FNAME_LEN
+								,getfname(g.gl_pathv[i]),f.desc);
 						}
-						if(_findnext(ff_handle,&ff)!=0) {
-							_findclose(ff_handle);
-							ff_handle=-1; 
-						} 
 					}
+					globfree(&g);
 				}
 				fclose(fp);
 			} else if(dir>=0) {
diff --git a/src/sbbs3/load_cfg.c b/src/sbbs3/load_cfg.c
index cf0565cfdfc5fc44b7bdc21682cf3a93d16ce9ca..0b67115358adb116a9403020f36e1f40e63a6b48 100644
--- a/src/sbbs3/load_cfg.c
+++ b/src/sbbs3/load_cfg.c
@@ -110,18 +110,19 @@ BOOL DLLCALL load_cfg(scfg_t* cfg, char* text[])
 /****************************************************************************/
 BOOL md(char *path)
 {
-	struct	_finddata_t ff;
-	long	ff_handle;
+	DIR*	dir;
 
-	ff_handle=_findfirst(path,&ff);
-	if (ff_handle==-1) {
+	dir=opendir(path);
+	if(dir==NULL) {
 		lprintf("Creating Directory %s... ",path);
 		if(_mkdir(path)) {
 			lprintf("!Fix configuration or make directory by "
 				"hand.");
-			return(FALSE); } }
+			return(FALSE); 
+		} 
+	}
 	else
-		_findclose(ff_handle);
+		closedir(dir);
 	
 	return(TRUE);
 }
diff --git a/src/sbbs3/pack_qwk.cpp b/src/sbbs3/pack_qwk.cpp
index 4b03aa23204be267e92fd3a277c3482b1df8a4ed..619bee8057a70b8699462ad1006b891341ad8c8b 100644
--- a/src/sbbs3/pack_qwk.cpp
+++ b/src/sbbs3/pack_qwk.cpp
@@ -45,6 +45,7 @@
 bool sbbs_t::pack_qwk(char *packet, ulong *msgcnt, bool prepack)
 {
 	char	str[256],tmp2[256],ch,*p;
+	char*	fname;
 	int 	file,mode;
 	uint	i,j,k,conf;
 	long	l,size,msgndx,posts,ex;
@@ -56,12 +57,14 @@ bool sbbs_t::pack_qwk(char *packet, ulong *msgcnt, bool prepack)
 	node_t	node;
 	mail_t	*mail;
 	post_t	HUGE16 *post;
+	glob_t	g;
 	FILE	*stream,*qwk,*personal,*ndx;
-    struct	_finddata_t ff;
-	long	ff_handle;
+	DIR*	dir;
+	DIRENT*	dirent;
 	struct	tm* tm;
 	smbmsg_t msg;
 
+
 	ex=EX_OUTL|EX_OUTR;
 	if(prepack)
 		ex|=EX_OFFLINE;
@@ -440,22 +443,20 @@ bool sbbs_t::pack_qwk(char *packet, ulong *msgcnt, bool prepack)
 		return(false);
 
 	if(/*!prepack && */ useron.rest&FLAG('Q')) { /* If QWK Net node, check for files */
-		sprintf(str,"%sQNET/%s.OUT/*.*",cfg.data_dir,useron.alias);
-		ff_handle=_findfirst(str,&ff);
-		while(ff_handle!=-1) {                 /* Move files into temp dir */
-			if(!(ff.attrib&_A_SUBDIR)) {
-				sprintf(str,"%sQNET/%s.OUT/%s",cfg.data_dir,useron.alias,ff.name);
-				strupr(str);
-				sprintf(tmp2,"%s%s",cfg.temp_dir,ff.name);
-				lncntr=0;	/* Default pause */
-				lprintf("Including %s in packet",str);
-				bprintf(text[RetrievingFile],str);
-				if(!mv(str,tmp2,1))
-					netfiles++;
-			}
-			if(_findnext(ff_handle,&ff)!=0) {
-				_findclose(ff_handle);
-				ff_handle=-1; } }
+		sprintf(str,"%sQNET/%s.OUT/",cfg.data_dir,useron.alias);
+		dir=opendir(str);
+		while((dirent=readdir(dir))!=NULL) {    /* Move files into temp dir */
+			sprintf(str,"%sQNET/%s.OUT/%s",cfg.data_dir,useron.alias,dirent->d_name);
+			if(isdir(str))
+				continue;
+			sprintf(tmp2,"%s%s",cfg.temp_dir,dirent->d_name);
+			lncntr=0;	/* Default pause */
+			lprintf("Including %s in packet",str);
+			bprintf(text[RetrievingFile],str);
+			if(!mv(str,tmp2,1))
+				netfiles++;
+		}
+		closedir(dir);
 		if(netfiles)
 			CRLF; }
 
@@ -513,16 +514,18 @@ bool sbbs_t::pack_qwk(char *packet, ulong *msgcnt, bool prepack)
 			sprintf(tmp2,"%sGOODBYE",cfg.temp_dir);
 			mv(str,tmp2,1); }
 		sprintf(str,"%sQWK/BLT-*.*",cfg.text_dir);
-		ff_handle=_findfirst(str,&ff);
-		while(ff_handle!=-1) { 			/* Copy BLT-*.* files */
-			padfname(ff.name,str);
+		glob(str,0,NULL,&g);
+		for(i=0;i<g.gl_pathc;i++) { 			/* Copy BLT-*.* files */
+			fname=getfname(g.gl_pathv[i]);
+			padfname(fname,str);
 			if(isdigit(str[4]) && isdigit(str[9])) {
-				sprintf(str,"%sQWK/%s",cfg.text_dir,ff.name);
-				sprintf(tmp2,"%s%s",cfg.temp_dir,ff.name);
-				mv(str,tmp2,1); }
-			if(_findnext(ff_handle, &ff)!=0) {
-				_findclose(ff_handle);
-				ff_handle=-1; } } }
+				sprintf(str,"%sQWK/%s",cfg.text_dir,fname);
+				sprintf(tmp2,"%s%s",cfg.temp_dir,fname);
+				mv(str,tmp2,1); 
+			}
+		}
+		globfree(&g);
+	}
 
 	if(prepack) {
 		for(i=1;i<=cfg.sys_nodes;i++) {
@@ -561,19 +564,21 @@ bool sbbs_t::pack_qwk(char *packet, ulong *msgcnt, bool prepack)
 	CRLF;
 	if(!(useron.exempt&FLAG('T')) && i>timeleft) {
 		bputs(text[NotEnoughTimeToDl]);
-		return(false); }
+		return(false); 
+	}
 
 	if(useron.rest&FLAG('Q')) {
 		sprintf(str,"%s.QWK",cfg.sys_id);
-		sprintf(tmp,"%s*.*",cfg.temp_dir);
-		ff_handle=_findfirst(tmp,&ff);
-		while(ff_handle!=-1) {
-			if(!(ff.attrib&_A_SUBDIR) && stricmp(str,ff.name)) {
-				sprintf(tmp,"%s%s",cfg.temp_dir,ff.name);
-				remove(tmp); }
-			if(_findnext(ff_handle, &ff)!=0) {
-				_findclose(ff_handle);
-				ff_handle=-1; } } }
+		dir=opendir(cfg.temp_dir);
+		while((dirent=readdir(dir))!=NULL) {
+			if(!stricmp(str,dirent->d_name))	/* QWK packet */
+				continue;
+			sprintf(tmp,"%s%s",cfg.temp_dir,dirent->d_name);
+			if(!isdir(tmp))
+				remove(tmp); 
+		}
+		closedir(dir);
+	}
 
 	return(true);
 }
diff --git a/src/sbbs3/pack_rep.cpp b/src/sbbs3/pack_rep.cpp
index 7ec1394e1f33490cb4a6d3832306279112ad6ded..a2317c7d473a5769e3e9c63414b96cc566c17c9f 100644
--- a/src/sbbs3/pack_rep.cpp
+++ b/src/sbbs3/pack_rep.cpp
@@ -53,9 +53,9 @@ bool sbbs_t::pack_rep(uint hubnum)
 	ulong	last,msgs;
 	post_t	HUGE16 *post;
 	mail_t	*mail;
-    struct	_finddata_t ff;
-	long	ff_handle;
-	FILE	*rep;
+	FILE*	rep;
+	DIR*	dir;
+	DIRENT*	dirent;
 	smbmsg_t msg;
 
 	msgcnt=0L;
@@ -193,19 +193,18 @@ bool sbbs_t::pack_rep(uint hubnum)
 	fclose(rep);			/* close MESSAGE.DAT */
 	CRLF;
 							/* Look for extra files to send out */
-	sprintf(str,"%sQNET/%s.OUT/*.*",cfg.data_dir,cfg.qhub[hubnum]->id);
-	ff_handle=_findfirst(str,&ff);
-	while(ff_handle!=-1) {
-		if(!(ff.attrib&_A_SUBDIR)) {
-			sprintf(str,"%sQNET/%s.OUT/%s",cfg.data_dir,cfg.qhub[hubnum]->id,ff.name);
-			sprintf(tmp2,"%s%s",cfg.temp_dir,ff.name);
-			lprintf(remove_ctrl_a(text[RetrievingFile],tmp),str);
-			if(!mv(str,tmp2,1))
-				netfiles++;
-		}
-		if(_findnext(ff_handle,&ff)!=0) {
-			_findclose(ff_handle);
-			ff_handle=-1; } }
+	sprintf(str,"%sQNET/%s.OUT",cfg.data_dir,cfg.qhub[hubnum]->id);
+	dir=opendir(str);
+	while((dirent=readdir(dir))!=NULL) {
+		sprintf(str,"%sQNET/%s.OUT/%s",cfg.data_dir,cfg.qhub[hubnum]->id,dirent->d_name);
+		if(isdir(str))
+			continue;
+		sprintf(tmp2,"%s%s",cfg.temp_dir,dirent->d_name);
+		lprintf(remove_ctrl_a(text[RetrievingFile],tmp),str);
+		if(!mv(str,tmp2,1))
+			netfiles++;
+	}
+	closedir(dir);
 	if(netfiles)
 		CRLF;
 
diff --git a/src/sbbs3/tmp_xfer.cpp b/src/sbbs3/tmp_xfer.cpp
index 215c7332a8457e16c1a3c96c865370838e890b1d..f2b5b5b59ce27d15b7b8ee33a8b86688bab806b1 100644
--- a/src/sbbs3/tmp_xfer.cpp
+++ b/src/sbbs3/tmp_xfer.cpp
@@ -49,9 +49,8 @@ void sbbs_t::temp_xfer()
 	ulong space;
     time_t start,end,t;
     file_t f;
+	glob_t g;
 	struct	tm * tm;
-    struct	_finddata_t ff;
-	long	ff_handle;
 
 	if(!usrlibs)
 		return;
@@ -216,17 +215,16 @@ void sbbs_t::temp_xfer()
 				bytes=files=0L;
 				CRLF;
 				sprintf(tmp2,"%s%s",cfg.temp_dir,str);
-				ff_handle=_findfirst(tmp2,&ff);
-				while(ff_handle!=-1 && !msgabort()) {
-            		if(!(ff.attrib&_A_SUBDIR)) {
-						bprintf("%s %10s\r\n",padfname(ff.name,str)
-							,ultoac(ff.size,tmp));
-						files++;
-						bytes+=ff.size;
-					}
-					if(_findnext(ff_handle, &ff)!=0) {
-						_findclose(ff_handle);
-						ff_handle=-1; } }
+				glob(tmp2,0,NULL,&g);
+				for(i=0;i<g.gl_pathc && !msgabort();i++) {
+					if(isdir(g.gl_pathv[i]))
+						continue;
+					bprintf("%s %15s\r\n",padfname(getfname(g.gl_pathv[i]),str)
+						,ultoac(flength(g.gl_pathv[i]),tmp));
+					files++;
+					bytes+=flength(g.gl_pathv[i]);
+				}
+				globfree(&g);
 				if(!files)
 					bputs(text[EmptyDir]);
 				else if(files>1)
@@ -280,8 +278,8 @@ void sbbs_t::extract(uint dirnum)
     uint	i,j;
 	ulong	space;
     file_t	f;
-    struct	_finddata_t ff;
-	long	ff_handle;
+	DIR*	dir;
+	DIRENT*	dirent;
 
 	temp_dirnum=curdirnum=dirnum;
 	if(!strcmp(cfg.dir[dirnum]->code,"TEMP"))
@@ -303,16 +301,16 @@ void sbbs_t::extract(uint dirnum)
 		sprintf(str,"%s*.*",cfg.temp_dir);
 		if(fexist(str)) {
 			bputs(text[RemovingTempFiles]);
-			ff_handle=_findfirst(str,&ff);
-			while(ff_handle!=-1) {
-        		if(!(ff.attrib&_A_SUBDIR)) {
-					sprintf(str,"%s%s",cfg.temp_dir,ff.name);
+			dir=opendir(cfg.temp_dir);
+			while((dirent=readdir(dir))!=NULL) {
+				sprintf(str,"%s%s",cfg.temp_dir,dirent->d_name);
+        		if(!isdir(str))
 					remove(str);
-				}
-				if(_findnext(ff_handle, &ff)!=0) {
-					_findclose(ff_handle);
-					ff_handle=-1; } }
-			CRLF; } }
+			}
+			closedir(dir);
+			CRLF; 
+		} 
+	}
 	bputs(text[ExtractFrom]);
 	if(!getstr(fname,12,K_UPPER) || !checkfname(fname) || strchr(fname,'*')
 		|| strchr(fname,'?'))
diff --git a/src/sbbs3/un_qwk.cpp b/src/sbbs3/un_qwk.cpp
index 0ffc8c5a6f5dada6c903d099b25be28f93906596..21dc900a2db51214145d0212ee25fabf2480f6ce 100644
--- a/src/sbbs3/un_qwk.cpp
+++ b/src/sbbs3/un_qwk.cpp
@@ -49,9 +49,9 @@ void sbbs_t::unpack_qwk(char *packet,uint hubnum)
 	uint	i,j,n,lastsub=INVALID_SUB;
 	uint	blocks;
 	long	l,size,misc;
-    struct	_finddata_t ff;
-	long	ff_handle;
-	FILE	*qwk;
+	DIR*	dir;
+	DIRENT*	dirent;
+	FILE*	qwk;
 
 	#if 0
 	useron.number=1;
@@ -241,24 +241,22 @@ void sbbs_t::unpack_qwk(char *packet,uint hubnum)
 	sprintf(str,"%sNETFLAGS.DAT",cfg.temp_dir);
 	remove(str);
 
-	sprintf(str,"%s*.*",cfg.temp_dir);
-	ff_handle=_findfirst(str,&ff);
-	while(ff_handle!=-1) {
-		if(!(ff.attrib&_A_SUBDIR)) {
-			// Create directory if necessary
-			sprintf(str,"%sQNET/%s.IN",cfg.data_dir,cfg.qhub[hubnum]->id);
-			_mkdir(str);
-			// Copy files
-			sprintf(str,"%s%s",cfg.temp_dir,ff.name);
-			sprintf(fname,"%sQNET/%s.IN/%s",cfg.data_dir,cfg.qhub[hubnum]->id,ff.name);
-			mv(str,fname,1 /* overwrite */);
-			sprintf(str,text[ReceivedFileViaQWK],ff.name,cfg.qhub[hubnum]->id);
-			putsmsg(&cfg,1,str);
-			lprintf("Received %s from %s", ff.name, cfg.qhub[hubnum]->id);
-		}
-		if(_findnext(ff_handle,&ff)!=0) {
-			_findclose(ff_handle);
-			ff_handle=-1; } }
+	dir=opendir(cfg.temp_dir);
+	while((dirent=readdir(dir))!=NULL) {
+		// Create directory if necessary
+		sprintf(str,"%sQNET/%s.IN",cfg.data_dir,cfg.qhub[hubnum]->id);
+		_mkdir(str);
+		sprintf(str,"%s%s",cfg.temp_dir,dirent->d_name);
+		if(isdir(str))	/* sub-dir */
+			continue;
+		// Copy files
+		sprintf(fname,"%sQNET/%s.IN/%s",cfg.data_dir,cfg.qhub[hubnum]->id,dirent->d_name);
+		mv(str,fname,1 /* overwrite */);
+		sprintf(str,text[ReceivedFileViaQWK],dirent->d_name,cfg.qhub[hubnum]->id);
+		putsmsg(&cfg,1,str);
+		lprintf("Received %s from %s", dirent->d_name, cfg.qhub[hubnum]->id);
+	}
+	closedir(dir);
 
 	lprintf("Finished Importing QWK Network Packet: %s",packet);
 	remove(packet);
diff --git a/src/sbbs3/un_rep.cpp b/src/sbbs3/un_rep.cpp
index feb3fe92deb7b7c2d83f6af8e34fccbd4ab198c3..282fcffff2a14d6c108714cd3baf1e7df733f571 100644
--- a/src/sbbs3/un_rep.cpp
+++ b/src/sbbs3/un_rep.cpp
@@ -52,9 +52,9 @@ bool sbbs_t::unpack_rep(char* repfile)
 	ulong	n;
 	ulong	ex;
 	node_t	node;
-    struct	_finddata_t ff;
-	long	ff_handle;
-	FILE	*rep;
+	FILE*	rep;
+	DIR*	dir;
+	DIRENT*	dirent;
 
 	if(repfile!=NULL)
 		strcpy(str,repfile);
@@ -411,25 +411,21 @@ bool sbbs_t::unpack_rep(char* repfile)
 		sprintf(str,"%s%s.REP",cfg.temp_dir,cfg.sys_id);
 		remove(str);
 
-		sprintf(str,"%s*.*",cfg.temp_dir);
-		ff_handle=_findfirst(str,&ff);
-		while(ff_handle!=-1) {					/* Extra files */
-			if(!(ff.attrib&_A_SUBDIR)) {
-				// Create directory if necessary
-				sprintf(str,"%sQNET/%s.IN",cfg.data_dir,useron.alias);
-				_mkdir(str); 
-				// Move files
-				sprintf(str,"%s%s",cfg.temp_dir,ff.name);
-				sprintf(fname,"%sQNET/%s.IN/%s",cfg.data_dir,useron.alias,ff.name);
-				mv(str,fname,1);
-				sprintf(str,text[ReceivedFileViaQWK],ff.name,useron.alias);
-				putsmsg(&cfg,1,str);
-			}
-			if(_findnext(ff_handle,&ff)!=0) {
-				_findclose(ff_handle);
-				ff_handle=-1; 
-			} 
+		dir=opendir(cfg.temp_dir);
+		while((dirent=readdir(dir))!=NULL) {				/* Extra files */
+			// Create directory if necessary
+			sprintf(str,"%sQNET/%s.IN",cfg.data_dir,useron.alias);
+			_mkdir(str); 
+			// Move files
+			sprintf(str,"%s%s",cfg.temp_dir,dirent->d_name);
+			if(isdir(str))
+				continue;
+			sprintf(fname,"%sQNET/%s.IN/%s",cfg.data_dir,useron.alias,dirent->d_name);
+			mv(str,fname,1);
+			sprintf(str,text[ReceivedFileViaQWK],dirent->d_name,useron.alias);
+			putsmsg(&cfg,1,str);
 		} 
+		closedir(dir);
 		sprintf(str,"%sQNET-REP.NOW",cfg.data_dir);
 		if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))!=-1)
 			close(file);
diff --git a/src/sbbs3/upload.cpp b/src/sbbs3/upload.cpp
index 991b1edf583116fe24e3a9db814bf8d938ad1f5a..02f481e5b2355e8ea1d53604c96ef1966d47f009 100644
--- a/src/sbbs3/upload.cpp
+++ b/src/sbbs3/upload.cpp
@@ -503,13 +503,12 @@ void sbbs_t::upload(uint dirnum)
 /****************************************************************************/
 bool sbbs_t::bulkupload(uint dirnum)
 {
-	char*	p;
     char	str[MAX_PATH];
 	char	path[MAX_PATH];
 	char	spath[MAX_PATH];
     file_t	f;
-    struct	_finddata_t ff;
-	long	ff_handle;
+	DIR*	dir;
+	DIRENT*	dirent;
 
 	memset(&f,0,sizeof(file_t));
 	f.dir=dirnum;
@@ -517,35 +516,37 @@ bool sbbs_t::bulkupload(uint dirnum)
 	bprintf(text[BulkUpload],cfg.lib[cfg.dir[dirnum]->lib]->sname,cfg.dir[dirnum]->sname);
 	strcpy(path,altul>0 && altul<=cfg.altpaths ? cfg.altpath[altul-1]
 		: cfg.dir[dirnum]->path);
-	sprintf(str,"%s*.*",path);
-	ff_handle=_findfirst(str,&ff);
 	action=NODE_ULNG;
 	SYNC;
-	while(ff_handle!=-1 && !msgabort()) {
-		if(!(ff.attrib&_A_SUBDIR)) {
-			if(gettotalfiles(dirnum)>cfg.dir[dirnum]->maxfiles) {
-				bputs(text[DirFull]);
-				return(false); }
-			sprintf(str,"%s%s",path,ff.name);
-			GetShortPathName(str,spath,sizeof(spath));
-			p=strrchr(spath,'\\');
-			if(p) p++;
-			else p=spath;
-	//        strupr(ff.name);
-			padfname(p,str);
-			if(findfile(&cfg,f.dir,str)==0) {
-				strcpy(f.name,str);
-				f.cdt=ff.size;
-				bprintf(text[BulkUploadDescPrompt],f.name,f.cdt);
-				getstr(f.desc,LEN_FDESC,K_LINE);
-				if(sys_status&SS_ABORT)
-					return(true);
-				uploadfile(&f); }	/* used to abort here if the file failed upload */
+	dir=opendir(path);
+	while((dirent=readdir(dir))!=NULL && !msgabort()) {
+		if(gettotalfiles(dirnum)>cfg.dir[dirnum]->maxfiles) {
+			bputs(text[DirFull]);
+			break; 
 		}
-		if(_findnext(ff_handle, &ff)!=0) {
-			_findclose(ff_handle);
-			ff_handle=-1; } }
+		sprintf(str,"%s%s",path,dirent->d_name);
+		if(isdir(str))
+			continue;
+#ifdef _WIN32
+		GetShortPathName(str,spath,sizeof(spath));
+#else
+		strcpy(spath,str);
+#endif
+		padfname(getfname(spath),str);
 
+		if(findfile(&cfg,f.dir,str)==0) {
+			strcpy(f.name,str);
+			f.cdt=flength(spath);
+			bprintf(text[BulkUploadDescPrompt],f.name,f.cdt);
+			getstr(f.desc,LEN_FDESC,K_LINE);
+			if(sys_status&SS_ABORT)
+				break;
+			uploadfile(&f); 
+		}
+	}
+	closedir(dir);
+	if(sys_status&SS_ABORT)
+		return(true);
 	return(false);
 }