delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/2013/03/23/06:15:20

X-Authentication-Warning: delorie.com: mail set sender to djgpp-bounces using -f
X-Received: by 10.224.185.79 with SMTP id cn15mr2026319qab.4.1364032694846;
Sat, 23 Mar 2013 02:58:14 -0700 (PDT)
X-Received: by 10.49.84.35 with SMTP id v3mr323767qey.16.1364032694818; Sat,
23 Mar 2013 02:58:14 -0700 (PDT)
Newsgroups: comp.os.msdos.djgpp
Date: Sat, 23 Mar 2013 02:58:14 -0700 (PDT)
Complaints-To: groups-abuse AT google DOT com
Injection-Info: glegroupsg2000goo.googlegroups.com; posting-host=2.173.27.66; posting-account=v5xbdQoAAAAOGc9Ccc-kLZyobvPlN3Qr
NNTP-Posting-Host: 2.173.27.66
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <261476b1-c137-495d-95df-a92075cd9960@googlegroups.com>
Subject: DJGPP scandir and alphasort example code
From: Georg Potthast <dosusb AT googlemail DOT com>
Injection-Date: Sat, 23 Mar 2013 09:58:14 +0000
Bytes: 6238
Lines: 199
To: djgpp AT delorie DOT com
DJ-Gateway: from newsgroup comp.os.msdos.djgpp
Reply-To: djgpp AT delorie DOT com

- DJGPP scandir and alphasort example code -

I was converting a program from Linux to DOS and this frequently used the scandir command. AFAIK this is not available with djgpp and so I wrote that function myself with help of examples I found via Google.

Since I assume this command may be of interest to other programmers too I post it here. HTH

1. First the libscandir.a library:

Compile with:
gcc -g -s -c libscandir.c
ar rcs libscandir.a libscandir.o


#include <stdio.h>
#include <string.h>

#include <glob.h>

#include <sys/types.h>
#include <stdlib.h>
#include <malloc.h>
#include <dirent.h>
#include <limits.h>


/* Alphabetic order comparison routine */
int alphasort(const void *d1, const void *d2)
{
	return(strcmp((*(struct dirent **)d1)->d_name,
	    (*(struct dirent **)d2)->d_name));
}


/*
 arg1 = directory name
 arg2 = unallocated array of pointers to dirent(direct) strctures
 arg3 = pointer to function to specify which files to include
 arg4 = pointer to sorting function to qsort, e.g. alphasort
 */
int scandir(char *dirname, struct dirent *(*namelist[]), 
 	   int (*sd_select)(const struct dirent *), int (*dcomp)(const void *, const void *))
{
	DIR *dirptr;
	struct dirent *dir_entry;
	int tdirsize = sizeof(struct dirent);
	register int i=0;
	int si=0;
	size_t cnt;
        glob_t glob_results;
        char *wildcard;
	char *wildcardpos;
	wildcard=calloc(_POSIX_PATH_MAX,sizeof(char));

	if ((dirptr = opendir(dirname)) == NULL)
		return -1;

	//read number of entries in directory
	strcpy(wildcard,dirname);
	//remove trailing slash
	wildcardpos=strrchr(wildcard,'\\');
	if (strlen(wildcardpos)==strlen(wildcard)) wildcard[strlen(wildcard)-1]='\0'; 
	//add * for all entries
	strcat(wildcard,"\\*");
	if(glob(wildcard, GLOB_NOESCAPE|GLOB_NOCHECK|GLOB_NOSORT, NULL, &glob_results) == 0)
	cnt = glob_results.gl_pathc +2; //add two for . and ..
	globfree(&glob_results);
	free(wildcard);
	
	//dynamic tdir array allocation
	static struct dirent *tdir;
	tdir = (struct dirent*) calloc(cnt,sizeof(struct dirent));

	if ((*namelist = (struct dirent **) calloc(cnt, sizeof(struct dirent *)))
		== NULL)
		return -1;

	if ((dir_entry = (struct dirent *) malloc(tdirsize + _POSIX_PATH_MAX)) == NULL)
		return -1;

	while (dir_entry = readdir(dirptr)) {
		if (sd_select == NULL){
			si=1; //no select routine specified, return all
		} else { 
			si = sd_select(dir_entry);
		}
		if (si) {
			if (((*namelist)[i] = (struct dirent *) 
				malloc(tdirsize + _POSIX_PATH_MAX)) == NULL)
				return -1;
			memcpy((*namelist)[i], dir_entry, sizeof(dir_entry)+_POSIX_PATH_MAX);
			i++;
		}
	}

	if (dcomp != NULL)
		qsort((char *) &((*namelist)[0]), i, sizeof(struct dirent *), dcomp);

	return i;
}

2. the header file for this library:

#ifndef scandir_h
#define scandir_h

#ifdef __cplusplus
extern "C" {
#endif

#include <sys/types.h>
#include <stdlib.h>
#include <malloc.h>
#include <dirent.h>
#include <limits.h>

/* example select routine */
#if 0
int sd_select(struct dirent *entry)
//remove . and .. from directory list
{	if ((strcmp(entry->d_name,".") == 0) ||
	    (strcmp(entry->d_name,"..") == 0))
	{ 
		return (0); 
	} else { 
		return (1); 
	}
}
#endif

/* Alphabetic order comparison routine */
int alphasort(const void *d1, const void *d2);

/*
 * rewrite of BSD scandir.
 * arg1 = directory name
 * arg2 = unallocated array of pointers to dirent(direct) strctures
 * arg3 = specifier for which objects to pick (pointer to function)
 * arg4 = sorting function pointer to pass to qsort
 */
int scandir(char *dirname, struct dirent *(*namelist[]), 
  int (*sd_select)(const struct dirent *), int (*dcomp)(const void *, const void *));

#ifdef __cplusplus
}
#endif

#endif //!scandir_h

3. a test program for this libary:

if all files are in one directory compile with:
gcc -g scandirtest.c -o scandirtest.exe libscandir.a

or copy libscandir.a into djgpp\lib and scandir.h into djgpp\include:
gcc -g scandirtest.c -o scandirtest.exe -lscandir
(you then would use #include <scandir.h> below instead)

#include <stdio.h>
#include <string.h>
#include "scandir.h"

/* select routine */
int sd_select(const struct dirent *entry)
//remove . and .. from directory list
{	if ((strcmp(entry->d_name,".") == 0) ||
	    (strcmp(entry->d_name,"..") == 0))
	{ 
		return (0); 
	} else { 
		return (1); 
	}
}

int main(void)
{
   struct dirent **namelist;
   int n,i;

   /* all entries in current directory unsorted */
   //n = scandir((char*)".", &namelist, 0, 0);

   /* all entries in current directory sorted */
   //n = scandir((char*)".", &namelist, 0, alphasort); 

   /* all entries in root sorted with "." and ".." entries removed*/
   n = scandir((char*)"/", &namelist, sd_select, alphasort); 
   
   if (n < 0)
        perror("scandir");
   else {
	for(i = 0; i < n; i++)  {
	printf("%02d: %s\n", i+1, namelist[i]->d_name);
	}
	//release memory allocated
	while (n--) {
		free(namelist[n]);
        }
	free(namelist);
   }
}

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019