Fix for 95128 - OS/2 build issue with DBM
authorjpierre%netscape.com
Thu, 22 Nov 2001 00:13:56 +0000
changeset 2364 a714f6a7884f6570f466e2c10051c5e443ca7428
parent 2363 e41ac1061dfdee492eeaf28f95bfb0e09deb447b
child 2365 5dca0bdef1589227036f44dc07655f6eb6a27e72
push idunknown
push userunknown
push dateunknown
bugs95128
Fix for 95128 - OS/2 build issue with DBM
security/dbm/src/dirent.c
security/dbm/src/dirent.h
security/dbm/src/manifest.mn
new file mode 100644
--- /dev/null
+++ b/security/dbm/src/dirent.c
@@ -0,0 +1,348 @@
+#ifdef OS2
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <dirent.h>
+#include <errno.h>
+
+/*#ifndef __EMX__ 
+#include <libx.h>
+#endif */
+
+#define INCL_DOSFILEMGR
+#define INCL_DOSERRORS
+#include <os2.h>
+
+#if OS2 >= 2
+# define FFBUF	FILEFINDBUF3
+# define Word	ULONG
+  /*
+   * LS20 recommends a request count of 100, but according to the
+   * APAR text it does not lead to missing files, just to funny
+   * numbers of returned entries.
+   *
+   * LS30 HPFS386 requires a count greater than 2, or some files
+   * are missing (those starting with a character less that '.').
+   *
+   * Novell looses entries which overflow the buffer. In previous
+   * versions of dirent2, this could have lead to missing files
+   * when the average length of 100 directory entries was 40 bytes
+   * or more (quite unlikely for files on a Novell server).
+   *
+   * Conclusion: Make sure that the entries all fit into the buffer
+   * and that the buffer is large enough for more than 2 entries
+   * (each entry is at most 300 bytes long). And ignore the LS20
+   * effect.
+   */
+# define Count	25
+# define BufSz	(25 * (sizeof(FILEFINDBUF3)+1))
+#else
+# define FFBUF	FILEFINDBUF
+# define Word	USHORT
+# define BufSz	1024
+# define Count	3
+#endif
+
+#if defined(__IBMC__) || defined(__IBMCPP__)
+  #define error(rc) _doserrno = rc, errno = EOS2ERR
+#elif defined(MICROSOFT)
+  #define error(rc) _doserrno = rc, errno = 255
+#else
+  #define error(rc) errno = 255
+#endif
+
+struct _dirdescr {
+	HDIR		handle;		/* DosFindFirst handle */
+	char		fstype;		/* filesystem type */
+	Word		count;		/* valid entries in <ffbuf> */
+	long		number;		/* absolute number of next entry */
+	int		index;		/* relative number of next entry */
+	FFBUF *		next;		/* pointer to next entry */
+	char		name[MAXPATHLEN+3]; /* directory name */
+	unsigned	attrmask;	/* attribute mask for seekdir */
+	struct dirent	entry;		/* buffer for directory entry */
+	BYTE		ffbuf[BufSz];
+};
+
+/*
+ * Return first char of filesystem type, or 0 if unknown.
+ */
+static char
+getFSType(const char *path)
+{
+	static char cache[1+26];
+	char drive[3], info[512];
+	Word unit, infolen;
+	char r;
+
+	if (isalpha(path[0]) && path[1] == ':') {
+		unit = toupper(path[0]) - '@';
+		path += 2;
+	} else {
+		ULONG driveMap;
+#if OS2 >= 2
+		if (DosQueryCurrentDisk(&unit, &driveMap))
+#else
+		if (DosQCurDisk(&unit, &driveMap))
+#endif
+			return 0;
+	}
+
+	if ((path[0] == '\\' || path[0] == '/')
+	 && (path[1] == '\\' || path[1] == '/'))
+		return 0;
+
+	if (cache [unit])
+		return cache [unit];
+
+	drive[0] = '@' + unit;
+	drive[1] = ':';
+	drive[2] = '\0';
+	infolen = sizeof info;
+#if OS2 >= 2
+	if (DosQueryFSAttach(drive, 0, FSAIL_QUERYNAME, (PVOID)info, &infolen))
+		return 0;
+	if (infolen >= sizeof(FSQBUFFER2)) {
+		FSQBUFFER2 *p = (FSQBUFFER2 *)info;
+		r = p->szFSDName[p->cbName];
+	} else
+#else
+	if (DosQFSAttach((PSZ)drive, 0, FSAIL_QUERYNAME, (PVOID)info, &infolen, 0))
+		return 0;
+	if (infolen >= 9) {
+		char *p = info + sizeof(USHORT);
+		p += sizeof(USHORT) + *(USHORT *)p + 1 + sizeof(USHORT);
+		r = *p;
+	} else
+#endif
+		r = 0;
+	return cache [unit] = r;
+}
+
+char *
+abs_path(const char *name, char *buffer, int len)
+{
+	char buf[4];
+	if (isalpha(name[0]) && name[1] == ':' && name[2] == '\0') {
+		buf[0] = name[0];
+		buf[1] = name[1];
+		buf[2] = '.';
+		buf[3] = '\0';
+		name = buf;
+	}
+#if OS2 >= 2
+	if (DosQueryPathInfo((PSZ)name, FIL_QUERYFULLNAME, buffer, len))
+#else
+	if (DosQPathInfo((PSZ)name, FIL_QUERYFULLNAME, (PBYTE)buffer, len, 0L))
+#endif
+		return NULL;
+	return buffer;
+}
+
+DIR *
+openxdir(const char *path, unsigned att_mask)
+{
+	DIR *dir;
+	char name[MAXPATHLEN+3];
+	Word rc;
+
+	dir = malloc(sizeof(DIR));
+	if (dir == NULL) {
+		errno = ENOMEM;
+		return NULL;
+	}
+
+	strncpy(name, path, MAXPATHLEN);
+	name[MAXPATHLEN] = '\0';
+	switch (name[strlen(name)-1]) {
+	default:
+		strcat(name, "\\");
+	case '\\':
+	case '/':
+	case ':':
+		;
+	}
+	strcat(name, ".");
+	if (!abs_path(name, dir->name, MAXPATHLEN+1))
+		strcpy(dir->name, name);
+	if (dir->name[strlen(dir->name)-1] == '\\')
+		strcat(dir->name, "*");
+	else
+		strcat(dir->name, "\\*");
+
+	dir->fstype = getFSType(dir->name);
+	dir->attrmask = att_mask | A_DIR;
+
+	dir->handle = HDIR_CREATE;
+	dir->count = 100;
+#if OS2 >= 2
+	rc = DosFindFirst(dir->name, &dir->handle, dir->attrmask,
+		dir->ffbuf, sizeof dir->ffbuf, &dir->count, FIL_STANDARD);
+#else
+	rc = DosFindFirst((PSZ)dir->name, &dir->handle, dir->attrmask,
+		(PFILEFINDBUF)dir->ffbuf, sizeof dir->ffbuf, &dir->count, 0);
+#endif
+	switch (rc) {
+	default:
+		free(dir);
+		error(rc);
+		return NULL;
+	case NO_ERROR:
+	case ERROR_NO_MORE_FILES:
+		;
+	}
+
+	dir->number = 0;
+	dir->index = 0;
+	dir->next = (FFBUF *)dir->ffbuf;
+
+	return (DIR *)dir;
+}
+
+DIR *
+opendir(const char *pathname)
+{
+	return openxdir(pathname, 0);
+}
+
+struct dirent *
+readdir(DIR *dir)
+{
+	static int dummy_ino = 2;
+
+	if (dir->index == dir->count) {
+		Word rc;
+		dir->count = 100;
+#if OS2 >= 2
+		rc = DosFindNext(dir->handle, dir->ffbuf,
+			sizeof dir->ffbuf, &dir->count);
+#else
+		rc = DosFindNext(dir->handle, (PFILEFINDBUF)dir->ffbuf,
+			sizeof dir->ffbuf, &dir->count);
+#endif
+		if (rc) {
+			error(rc);
+			return NULL;
+		}
+
+		dir->index = 0;
+		dir->next = (FFBUF *)dir->ffbuf;
+	}
+
+	if (dir->index == dir->count)
+		return NULL;
+
+	memcpy(dir->entry.d_name, dir->next->achName, dir->next->cchName);
+	dir->entry.d_name[dir->next->cchName] = '\0';
+	dir->entry.d_ino = dummy_ino++;
+	dir->entry.d_reclen = dir->next->cchName;
+	dir->entry.d_namlen = dir->next->cchName;
+	dir->entry.d_size = dir->next->cbFile;
+	dir->entry.d_attribute = dir->next->attrFile;
+	dir->entry.d_time = *(USHORT *)&dir->next->ftimeLastWrite;
+	dir->entry.d_date = *(USHORT *)&dir->next->fdateLastWrite;
+
+	switch (dir->fstype) {
+	case 'F': /* FAT */
+	case 'C': /* CDFS */
+		if (dir->next->attrFile & FILE_DIRECTORY)
+			strupr(dir->entry.d_name);
+		else
+			strlwr(dir->entry.d_name);
+	}
+
+#if OS2 >= 2
+	dir->next = (FFBUF *)((BYTE *)dir->next + dir->next->oNextEntryOffset);
+#else
+	dir->next = (FFBUF *)((BYTE *)dir->next->achName + dir->next->cchName + 1);
+#endif
+	++dir->number;
+	++dir->index;
+
+	return &dir->entry;
+}
+
+long
+telldir(DIR *dir)
+{
+	return dir->number;
+}
+
+void
+seekdir(DIR *dir, long off)
+{
+	if (dir->number > off) {
+		char name[MAXPATHLEN+2];
+		Word rc;
+
+		DosFindClose(dir->handle);
+
+		strcpy(name, dir->name);
+		strcat(name, "*");
+
+		dir->handle = HDIR_CREATE;
+		dir->count = 32767;
+#if OS2 >= 2
+		rc = DosFindFirst(name, &dir->handle, dir->attrmask,
+			dir->ffbuf, sizeof dir->ffbuf, &dir->count, FIL_STANDARD);
+#else
+		rc = DosFindFirst((PSZ)name, &dir->handle, dir->attrmask,
+			(PFILEFINDBUF)dir->ffbuf, sizeof dir->ffbuf, &dir->count, 0);
+#endif
+		switch (rc) {
+		default:
+			error(rc);
+			return;
+		case NO_ERROR:
+		case ERROR_NO_MORE_FILES:
+			;
+		}
+
+		dir->number = 0;
+		dir->index = 0;
+		dir->next = (FFBUF *)dir->ffbuf;
+	}
+
+	while (dir->number < off && readdir(dir))
+		;
+}
+
+void
+closedir(DIR *dir)
+{
+	DosFindClose(dir->handle);
+	free(dir);
+}
+
+/*****************************************************************************/
+
+#ifdef TEST
+
+main(int argc, char **argv)
+{
+	int i;
+	DIR *dir;
+	struct dirent *ep;
+
+	for (i = 1; i < argc; ++i) {
+		dir = opendir(argv[i]);
+		if (!dir)
+			continue;
+		while (ep = readdir(dir))
+			if (strchr("\\/:", argv[i] [strlen(argv[i]) - 1]))
+				printf("%s%s\n", argv[i], ep->d_name);
+			else
+				printf("%s/%s\n", argv[i], ep->d_name);
+		closedir(dir);
+	}
+
+	return 0;
+}
+
+#endif
+
+#endif /* OS2 */
+
new file mode 100644
--- /dev/null
+++ b/security/dbm/src/dirent.h
@@ -0,0 +1,97 @@
+#ifndef __DIRENT_H__
+#define __DIRENT_H__
+/*
+ * @(#)msd_dir.h 1.4 87/11/06   Public Domain.
+ *
+ *  A public domain implementation of BSD directory routines for
+ *  MS-DOS.  Written by Michael Rendell ({uunet,utai}michael@garfield),
+ *  August 1897
+ *
+ *  Extended by Peter Lim (lim@mullian.oz) to overcome some MS DOS quirks
+ *  and returns 2 more pieces of information - file size & attribute.
+ *  Plus a little reshuffling of some #define's positions    December 1987
+ *
+ *  Some modifications by Martin Junius                      02-14-89
+ *
+ *	AK900712
+ *	AK910410	abs_path - make absolute path
+ *
+ */
+
+#ifdef __EMX__
+#include <sys/param.h>
+#else
+#if defined(__IBMC__) || defined(__IBMCPP__) || defined(XP_W32_MSVC)
+#include <stdio.h>
+#ifdef MAXPATHLEN
+	#undef MAXPATHLEN
+#endif
+#define MAXPATHLEN (FILENAME_MAX*4)
+#define MAXNAMLEN FILENAME_MAX
+
+#else
+#include <param.h>
+#endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* attribute stuff */
+#ifndef A_RONLY
+# define A_RONLY   0x01
+# define A_HIDDEN  0x02
+# define A_SYSTEM  0x04
+# define A_LABEL   0x08
+# define A_DIR     0x10
+# define A_ARCHIVE 0x20
+#endif
+
+struct dirent {
+#if defined(OS2) || defined(WIN32)        /* use the layout of EMX to avoid trouble */
+    int            d_ino;                 /* Dummy */
+    int            d_reclen;		  /* Dummy, same as d_namlen */
+    int            d_namlen;              /* length of name */
+    char           d_name[MAXNAMLEN + 1];
+    unsigned long  d_size;
+    unsigned short d_attribute;           /* attributes (see above) */
+    unsigned short d_time;                /* modification time */
+    unsigned short d_date;                /* modification date */
+#else
+    char	   d_name[MAXNAMLEN + 1]; /* garentee null termination */
+    char	   d_attribute;		  /* .. extension .. */
+    unsigned long  d_size;		  /* .. extension .. */
+#endif
+};
+
+typedef struct _dirdescr DIR;
+/* the structs do not have to be defined here */
+
+extern DIR		*opendir(const char *);
+extern DIR		*openxdir(const char *, unsigned);
+extern struct dirent	*readdir(DIR *);
+extern void		seekdir(DIR *, long);
+extern long		telldir(DIR *);
+extern void 		closedir(DIR *);
+#define			rewinddir(dirp) seekdir(dirp, 0L)
+
+extern char *		abs_path(const char *name, char *buffer, int len);
+
+#ifndef S_IFMT
+#define S_IFMT ( S_IFDIR | S_IFREG )
+#endif
+
+#ifndef S_ISDIR
+#define S_ISDIR( m )                    (((m) & S_IFMT) == S_IFDIR)
+#endif
+
+#ifndef S_ISREG
+#define S_ISREG( m )                    (((m) & S_IFMT) == S_IFREG)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- a/security/dbm/src/manifest.mn
+++ b/security/dbm/src/manifest.mn
@@ -50,11 +50,12 @@ CSRCS = db.c	   \
 	h_log2.c   \
 	h_page.c   \
 	hash.c	   \
 	hash_buf.c \
 	hsearch.c  \
 	mktemp.c   \
 	ndbm.c	   \
 	nsres.c	   \
+	dirent.c	   \
 	$(NULL)
 
 LIBRARY_NAME = dbm