[Mimedefang] 2.23 configure and rm_r.c problems on Solaris

Heidi Hornstein heidi at cmf.nrl.navy.mil
Tue Oct 22 11:51:01 EDT 2002


Sun's compiler doesn't have a -pthread option.  The configure test for 
the pthread option ends up succeeding, because the various letters of
"pthread" are acccepted as options.  This eventually causes the make 
to error with:

cc -g -pthread -o mimedefang mimedefang.o drop_privs_threaded.o utils.o rm_r.o /opt/LOCALsendmail/lib/libmilter.a -lpth
read -lnsl -lsocket -lresolv 
ld: fatal: option -h and building a dynamic executable are incompatible
ld: fatal: Flags processing errors

Under non Linux operating systems struct dirent is declared as:

typedef struct dirent {
        ino_t           d_ino;          /* "inode number" of entry */
        off_t           d_off;          /* offset of disk directory entry */
        unsigned short  d_reclen;       /* length of this record */
        char            d_name[1];      /* name of file */
} dirent_t;

Note that since the last member is a char[1], there is no storage 
allocated in this structure for the directory name.  This isn't a problem
when using readdir(). When using readdir_r the space needs to be allocated, 
declaring just a struct dirent does not allocate enough storage.  

The following the patch solves the problem under Solaris and probably 
other operating systems as well.  This code should probably work fine under
Linux; however, I have not tested on anything other than Solaris.

--Heidi

--- mimedefang-2.23/rm_r.c	Tue Oct  1 17:10:31 2002
+++ /afs/cmf/system/src/local/mdefang/002/mimedefang-2.23/rm_r.c	Mon Oct 21 19:45:53 2002
@@ -46,7 +46,7 @@
     char buf[SMALLBUF];
     struct stat sbuf;
     DIR *d;
-    struct dirent entry;
+    struct dirent *entry;
     struct dirent *result = NULL;
     int n;
 
@@ -64,35 +64,46 @@
 	return 0;
     }
 
+    entry = (struct dirent *) malloc(sizeof(struct dirent) + pathconf(dir, _PC_NAME_MAX) + 1);
+
+    if (! entry) {
+	syslog(LOG_WARNING, "Unable to malloc dirent entry: %m");
+	return -1;
+    }
+
     d = opendir(dir);
     if (!d) {
 	syslog(LOG_WARNING, "opendir(%s) failed: %m", dir);
+	free(entry);
 	return -1;
     }
 
     for (;;) {
-	n = readdir_r(d, &entry, &result);
-	if (n < 0) {
+	n = readdir_r(d, entry, &result);
+	if (n != 0) {
 	    int errno_save = errno;
 	    syslog(LOG_WARNING, "readdir_r failed: %m");
 	    closedir(d);
 	    errno = errno_save;
+	    free(entry);
 	    return -1;
 	}
 	if (!result) break;
-	if (!strcmp(entry.d_name, ".") ||
-	    !strcmp(entry.d_name, "..")) {
+	if (!strcmp(entry->d_name, ".") ||
+	    !strcmp(entry->d_name, "..")) {
 	    continue;
 	}
-	snprintf(buf, sizeof(buf), "%s/%s", dir, entry.d_name);
+	snprintf(buf, sizeof(buf), "%s/%s", dir, entry->d_name);
 	if (rm_r(buf) < 0) {
 	    int errno_save = errno;
 	    closedir(d);
+	    free(entry);
 	    errno = errno_save;
 	    return -1;
 	}
     }
     closedir(d);
+    free(entry);
     if (rmdir(dir) < 0) {
 	syslog(LOG_WARNING, "rmdir(%s) failed: %m", dir);
 	return -1;



More information about the MIMEDefang mailing list