Re: svn commit: r334814 - head/sbin/dump

2018-06-08 Thread Diane Bruce
On Fri, Jun 08, 2018 at 10:08:25AM -0400, Ed Maste wrote:
> On 7 June 2018 at 16:49, Kirk McKusick  wrote:
> > Author: mckusick
> > Date: Thu Jun  7 20:49:01 2018
> > New Revision: 334814
> > URL: https://svnweb.freebsd.org/changeset/base/334814
> >
> > Log:
> >   Ensure proper initialization of superblock.
> >
> ...
> > --- head/sbin/dump/main.c   Thu Jun  7 19:57:55 2018(r334813)
> > +++ head/sbin/dump/main.c   Thu Jun  7 20:49:01 2018(r334814)
> > @@ -433,6 +433,7 @@ main(int argc, char *argv[])
> > msgtail("to %s\n", tape);
> >
> > sync();
> > +   sblock = NULL;
> > if ((ret = sbget(diskfd, &sblock, -1)) != 0) {
> 
> sblock is initialized to NULL at the beginning of ffs_sbget, so I'm

I saw that under lldb when I checked the assembler code. 

> not really sure what's happening here.

ditto. But another data point this morning. I ran stock dump
on a spinning rust portable drive I have with me today. It worked fine.
the disk in the laptop is a SSD SATA. Another data point , the 
bug failed to manifest until my system had been running a few minutes.
e.g. it did the demo mode failure when I tried to show it to jhibbits...

I will boot from the spinning rust and fsck the ssd again. @dteske
and I thoroughly fsck_ufs fsck_ffs etc. yesterday but I'll try again
today from another root disk. That's an obvious one. 


> ___
> svn-src-...@freebsd.org mailing list
> https://lists.freebsd.org/mailman/listinfo/svn-src-all
> To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

-- 
- d...@freebsd.org d...@db.net http://www.db.net/~db
___
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"


svn commit: r334968 - head/sbin/dump

2018-06-11 Thread Diane Bruce
Author: db (ports committer)
Date: Mon Jun 11 19:12:50 2018
New Revision: 334968
URL: https://svnweb.freebsd.org/changeset/base/334968

Log:
  Large file systems with inodes > 512K have been silently overflowing
  c_addr in spcl. So check before we start dumping otherwise we can
  end up with a corrupted dump.
  
  PR:   228807
  Submitted by: db
  Reviewed by:  imp
  Approved by:  imp

Modified:
  head/sbin/dump/main.c   (contents, props changed)

Modified: head/sbin/dump/main.c
==
--- head/sbin/dump/main.c   Mon Jun 11 19:03:49 2018(r334967)
+++ head/sbin/dump/main.c   Mon Jun 11 19:12:50 2018(r334968)
@@ -103,6 +103,7 @@ main(int argc, char *argv[])
int i, ret, anydirskipped, bflag = 0, Tflag = 0, honorlevel = 1;
int just_estimate = 0;
ino_t maxino;
+   int c_count=0;
char *tmsg;
 
spcl.c_date = _time_to_time64(time(NULL));
@@ -433,7 +434,6 @@ main(int argc, char *argv[])
msgtail("to %s\n", tape);
 
sync();
-   sblock = NULL;
if ((ret = sbget(diskfd, &sblock, -1)) != 0) {
switch (ret) {
case ENOENT:
@@ -453,6 +453,9 @@ main(int argc, char *argv[])
quit("TP_BSIZE (%d) is not a power of 2", TP_BSIZE);
maxino = sblock->fs_ipg * sblock->fs_ncg;
mapsize = roundup(howmany(maxino, CHAR_BIT), TP_BSIZE);
+   c_count = howmany(mapsize * sizeof(char), TP_BSIZE);
+   if (c_count > TP_NINDIR)
+   quit("fs is too large for dump!");
usedinomap = (char *)calloc((unsigned) mapsize, sizeof(char));
dumpdirmap = (char *)calloc((unsigned) mapsize, sizeof(char));
dumpinomap = (char *)calloc((unsigned) mapsize, sizeof(char));
___
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"


svn commit: r334997 - in head/sys: arm64/conf conf dev/uart modules/uart

2018-06-12 Thread Diane Bruce
Author: db (ports committer)
Date: Tue Jun 12 13:26:31 2018
New Revision: 334997
URL: https://svnweb.freebsd.org/changeset/base/334997

Log:
  Add a driver for the BCM2835 Mini-UART as seen on the RPi3
  
  Reviewed by:  andrew
  Approved by:  andrew
  Differential Revision:https://reviews.freebsd.org/D15684

Added:
  head/sys/dev/uart/uart_dev_mu.c   (contents, props changed)
Modified:
  head/sys/arm64/conf/GENERIC   (contents, props changed)
  head/sys/conf/files.arm64   (contents, props changed)
  head/sys/modules/uart/Makefile   (contents, props changed)

Modified: head/sys/arm64/conf/GENERIC
==
--- head/sys/arm64/conf/GENERIC Tue Jun 12 11:47:21 2018(r334996)
+++ head/sys/arm64/conf/GENERIC Tue Jun 12 13:26:31 2018(r334997)
@@ -165,6 +165,7 @@ device  dwmmc
 # Serial (COM) ports
 device uart# Generic UART driver
 device uart_msm# Qualcomm MSM UART driver
+device uart_mu # RPI3 aux port
 device uart_mvebu  # Armada 3700 UART driver
 device uart_ns8250 # ns8250-type UART driver
 device uart_snps

Modified: head/sys/conf/files.arm64
==
--- head/sys/conf/files.arm64   Tue Jun 12 11:47:21 2018(r334996)
+++ head/sys/conf/files.arm64   Tue Jun 12 13:26:31 2018(r334997)
@@ -209,6 +209,7 @@ dev/pci/pci_host_generic_fdt.c  optionalpci fdt
 dev/psci/psci.cstandard
 dev/psci/psci_arm64.S  standard
 dev/uart/uart_cpu_arm64.c  optionaluart
+dev/uart/uart_dev_mu.c optionaluart uart_mu
 dev/uart/uart_dev_pl011.c  optionaluart pl011
 dev/usb/controller/dwc_otg_hisi.c optional dwcotg fdt soc_hisi_hi6220
 dev/usb/controller/ehci_mv.c   optionalehci_mv fdt

Added: head/sys/dev/uart/uart_dev_mu.c
==
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sys/dev/uart/uart_dev_mu.c Tue Jun 12 13:26:31 2018
(r334997)
@@ -0,0 +1,521 @@
+/*-
+ * Copyright (c) 2018 Diane Bruce 
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *notice, this list of conditions and the following disclaimer in the
+ *documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Based on uart_dev_pl011.c
+ * Copyright (c) 2012 Semihalf.
+ * All rights reserved.
+ */
+/*
+ * The mini Uart has the following features: 
+ * - 7 or 8 bit operation. 
+ * - 1 start and 1 stop bit. 
+ * - No parities. 
+ * - Break generation. 
+ * - 8 symbols deep FIFOs for receive and transmit. 
+ * - SW controlled RTS, SW readable CTS. 
+ * - Auto flow control with programmable FIFO level. 
+ * - 16550 like registers. 
+ * - Baudrate derived from system clock. 
+ * This is a mini UART and it does NOT have the following capabilities: 
+ * - Break detection 
+ * - Framing errors detection. 
+ * - Parity bit 
+ * - Receive Time-out interrupt 
+ * - DCD, DSR, DTR or RI signals. 
+ * The implemented UART is not a 16650 compatible UART However as far
+ * as possible the first 8 control and status registers are laid out 
+ * like a 16550 UART. All 16550 register bits which are not supported can
+ * be written but will be ignored and read back as 0. All control bits
+ * for simple UART receive/transmit operations are available.
+ */
+
+#include "opt_acpi.h"
+#include "opt_platform.h"
+
+#include 
+__FBSDID("$FreeBSD$");
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#ifdef FDT
+#include 
+#include 
+#endif
+#include 
+#include "uart_if.h"
+
+/* BCM2835 Micro UART r

Re: svn commit: r340088 - head/sbin/devd

2018-11-02 Thread Diane Bruce
On Fri, Nov 02, 2018 at 05:28:29PM -0500, Matthew D. Fuller wrote:
> > +# devices are assocaited with the USB Bus and provide an ifnet device to
>  
> Tpyo.

heh I just emailed him privately about that one too ;)

> 
> 
> -- 
> Matthew Fuller (MF4839)   |  fulle...@over-yonder.net
> Systems/Network Administrator |  http://www.over-yonder.net/~fullermd/
>On the Internet, nobody can hear you scream.
> ___
> svn-src-...@freebsd.org mailing list
> https://lists.freebsd.org/mailman/listinfo/svn-src-all
> To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

-- 
- d...@freebsd.org d...@db.net http://artemis.db.net/~db
___
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"


svn commit: r255715 - head/usr.bin/calendar

2013-09-19 Thread Diane Bruce
Author: db (ports committer)
Date: Thu Sep 19 20:17:50 2013
New Revision: 255715
URL: http://svnweb.freebsd.org/changeset/base/255715

Log:
  - calendar uses cpp internally, this diff removes this usage and
substitutes a limited subset cpp processor internally.
  
  PR:   src/178463
  Approved by:  re (gjb)

Added:
  head/usr.bin/calendar/calcpp.c   (contents, props changed)
Modified:
  head/usr.bin/calendar/Makefile   (contents, props changed)
  head/usr.bin/calendar/calendar.1   (contents, props changed)
  head/usr.bin/calendar/calendar.h   (contents, props changed)
  head/usr.bin/calendar/io.c   (contents, props changed)
  head/usr.bin/calendar/pathnames.h   (contents, props changed)

Modified: head/usr.bin/calendar/Makefile
==
--- head/usr.bin/calendar/Makefile  Thu Sep 19 20:15:24 2013
(r255714)
+++ head/usr.bin/calendar/Makefile  Thu Sep 19 20:17:50 2013
(r255715)
@@ -3,7 +3,7 @@
 
 PROG=  calendar
 SRCS=  calendar.c locale.c events.c dates.c parsedata.c io.c day.c \
-   ostern.c paskha.c pom.c sunpos.c
+   ostern.c paskha.c pom.c sunpos.c calcpp.c
 DPADD= ${LIBM}
 LDADD= -lm
 INTER=  de_AT.ISO_8859-15 de_DE.ISO8859-1 fr_FR.ISO8859-1 \

Added: head/usr.bin/calendar/calcpp.c
==
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/usr.bin/calendar/calcpp.c  Thu Sep 19 20:17:50 2013
(r255715)
@@ -0,0 +1,229 @@
+/*-
+ * Copyright (c) 2013 Diane Bruce
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *notice, this list of conditions and the following disclaimer in the
+ *documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/* calendar fake cpp does a very limited cpp version */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "pathnames.h"
+#include "calendar.h"
+
+#define MAXFPSTACK 50
+static FILE *fpstack[MAXFPSTACK];
+static int curfpi;
+static void pushfp(FILE *fp);
+static FILE *popfp(void);
+static int tokenscpp(char *buf, char *string);
+
+#define T_INVALID  -1
+#define T_INCLUDE  0
+#define T_DEFINE   1
+#define T_IFNDEF   2
+#define T_ENDIF3
+
+#define MAXSYMS100
+static char *symtable[MAXSYMS];
+static void addsym(const char *name);
+static int findsym(const char *name);
+
+FILE *
+fincludegets(char *buf, int size, FILE *fp)
+{
+   char name[MAXPATHLEN];
+   FILE *nfp=NULL;
+   char *p;
+   int ch;
+
+   if (fp == NULL)
+   return(NULL);
+
+   if (fgets(buf, size, fp) == NULL) {
+   *buf = '\0';
+   fclose(fp);
+   fp = popfp();
+   return (fp);
+   }
+   if ((p = strchr(buf, '\n')) != NULL)
+   *p = '\0';
+   else {
+   /* Flush this line */
+   while ((ch = fgetc(fp)) != '\n' && ch != EOF);
+   if (ch == EOF) {
+   *buf = '\0';
+   fclose(fp);
+   fp = popfp();
+   return(fp);
+   }
+   }
+   switch (tokenscpp(buf, name)) {
+   case T_INCLUDE:
+   *buf = '\0';
+   if ((nfp = fopen(name, "r")) != NULL) {
+   pushfp(fp);
+   fp = nfp;
+   }
+   break;
+   case T_DEFINE:
+   addsym(name);
+   break;
+   case T_IFNDEF:
+   if (findsym(name)) {

svn commit: r247919 - head/lib/libutil

2013-03-07 Thread Diane Bruce
Author: db (ports committer)
Date: Thu Mar  7 19:00:00 2013
New Revision: 247919
URL: http://svnweb.freebsd.org/changeset/base/247919

Log:
  Cleanup gr_add() so it does not leak mem
  This is part of ongoing work on sbin/pw
  
  Mlibutil.h
  Mgr_util.c
  
  Approved by:  theraven

Modified:
  head/lib/libutil/gr_util.c
  head/lib/libutil/libutil.h

Modified: head/lib/libutil/gr_util.c
==
--- head/lib/libutil/gr_util.c  Thu Mar  7 18:55:37 2013(r247918)
+++ head/lib/libutil/gr_util.c  Thu Mar  7 19:00:00 2013(r247919)
@@ -49,6 +49,8 @@ static char group_dir[PATH_MAX];
 static char group_file[PATH_MAX];
 static char tempname[PATH_MAX];
 static int initialized;
+static size_t grmemlen(const struct group *, const char *, int *);
+static struct group *grcopy(const struct group *gr, struct group *newgr, const 
char *, int ndx);
 
 /*
  * Initialize statics
@@ -429,90 +431,121 @@ gr_make(const struct group *gr)
 struct group *
 gr_dup(const struct group *gr)
 {
+   return (gr_add(gr, NULL));
+}
+/*
+ * Add a new member name to a struct group.
+ */
+struct group *
+gr_add(const struct group *gr, const char *newmember)
+{
struct group *newgr;
-   char *dst;
size_t len;
-   int ndx;
int num_mem;
 
-   /* Calculate size of the group. */
-   len = sizeof(*newgr);
-   if (gr->gr_name != NULL)
-   len += strlen(gr->gr_name) + 1;
-   if (gr->gr_passwd != NULL)
-   len += strlen(gr->gr_passwd) + 1;
-   if (gr->gr_mem != NULL) {
-   for (num_mem = 0; gr->gr_mem[num_mem] != NULL; num_mem++)
-   len += strlen(gr->gr_mem[num_mem]) + 1;
-   len += (num_mem + 1) * sizeof(*gr->gr_mem);
-   } else
-   num_mem = -1;
+   num_mem = 0;
+   len = grmemlen(gr, newmember, &num_mem);
/* Create new group and copy old group into it. */
if ((newgr = malloc(len)) == NULL)
return (NULL);
-   /* point new gr_mem to end of struct + 1 */
-   if (gr->gr_mem != NULL)
+   return (grcopy(gr, newgr, newmember, num_mem));
+}
+
+/* It is safer to walk the pointers given at gr_mem since there is no
+ * guarantee the gr_mem + strings are continguous in the given struct group
+ * but compact the new group into the following form.
+ *
+ * The new struct is laid out like this in memory. The example given is
+ * for a group with two members only.
+ *
+ * {
+ * (char *name)
+ * (char *passwd)
+ * (int gid)
+ * (gr_mem * newgrp + sizeof(struct group) + sizeof(**)) points to gr_mem area
+ * gr_mem area
+ * (member1 *) 
+ * (member2 *)
+ * (NULL)
+ * (name string)
+ * (passwd string)
+ * (member1 string)
+ * (member2 string)
+ * }
+ */
+/*
+ * Copy the guts of a group plus given name to a preallocated group struct
+ */
+static struct group *
+grcopy(const struct group *gr, struct group *newgr, const char *name, int ndx)
+{
+   char *dst;
+   int i;
+
+   if (name != NULL)
+   ndx++;
+   /* point new gr_mem to end of struct + 1 if there are names */
+   if (ndx != 0)
newgr->gr_mem = (char **)(newgr + 1);
else
newgr->gr_mem = NULL;
/* point dst after the end of all the gr_mem pointers in newgr */
-   dst = (char *)&newgr->gr_mem[num_mem + 1];
+   dst = (char *)&newgr->gr_mem[ndx + 1];
if (gr->gr_name != NULL) {
newgr->gr_name = dst;
dst = stpcpy(dst, gr->gr_name) + 1;
-   } else {
+   } else
newgr->gr_name = NULL;
-   }
if (gr->gr_passwd != NULL) {
newgr->gr_passwd = dst;
dst = stpcpy(dst, gr->gr_passwd) + 1;
-   } else {
+   } else
newgr->gr_passwd = NULL;
-   }
newgr->gr_gid = gr->gr_gid;
-   if (gr->gr_mem != NULL) {
-   for (ndx = 0; ndx < num_mem; ndx++) {
-   newgr->gr_mem[ndx] = dst;
-   dst = stpcpy(dst, gr->gr_mem[ndx]) + 1;
+   if (ndx != 0) {
+   for (i = 0; gr->gr_mem[i] != NULL; i++) {
+   newgr->gr_mem[i] = dst;
+   dst = stpcpy(dst, gr->gr_mem[i]) + 1;
+   }
+   if (name != NULL) {
+   newgr->gr_mem[i++] = dst;
+   dst = stpcpy(dst, name) + 1;
}
-   newgr->gr_mem[ndx] = NULL;
+   newgr->gr_mem[i] = NULL;
}
return (newgr);
 }
 
 /*
- * Add a new member name to a struct group.
+ *  Calculate length of a struct group + given name
  */
-struct group *
-gr_add(struct group *gr, char *newmember)
+static size_t
+grmemlen(const struct group *gr, const char *name, int *num_mem)
 {
-   size_t mlen;
-   int num_mem=0;
-   char **members;
-   struct group *newgr;
-
-   if (newmember == NULL)
-  

svn commit: r248102 - head/lib/libutil

2013-03-09 Thread Diane Bruce
Author: db (ports committer)
Date: Sat Mar  9 13:30:06 2013
New Revision: 248102
URL: http://svnweb.freebsd.org/changeset/base/248102

Log:
  commit correct tested fix for gr_util.c
  
  Approved by:  theraven

Modified:
  head/lib/libutil/gr_util.c

Modified: head/lib/libutil/gr_util.c
==
--- head/lib/libutil/gr_util.c  Sat Mar  9 13:25:45 2013(r248101)
+++ head/lib/libutil/gr_util.c  Sat Mar  9 13:30:06 2013(r248102)
@@ -50,7 +50,7 @@ static char group_file[PATH_MAX];
 static char tempname[PATH_MAX];
 static int initialized;
 static size_t grmemlen(const struct group *, const char *, int *);
-static struct group *grcopy(const struct group *gr, struct group *newgr, const 
char *, int ndx);
+static struct group *grcopy(const struct group *gr, char *mem, const char *, 
int ndx);
 
 /*
  * Initialize statics
@@ -361,26 +361,30 @@ gr_equal(const struct group *gr1, const 
if (gr1->gr_gid != gr2->gr_gid)
return (false);
 
-   /* Check all members in both groups. */
-   if (gr1->gr_mem == NULL || gr2->gr_mem == NULL) {
-   if (gr1->gr_mem != gr2->gr_mem)
-   return (false);
-   } else {
-   for (gr1_ndx = 0; gr1->gr_mem[gr1_ndx] != NULL; gr1_ndx++) {
-   for (gr2_ndx = 0;; gr2_ndx++) {
-   if (gr2->gr_mem[gr2_ndx] == NULL)
-   return (false);
-   if (strcmp(gr1->gr_mem[gr1_ndx],
-   gr2->gr_mem[gr2_ndx]) == 0) {
-   break;
-   }
-   }
-   }
-
-   /* Check that group2 does not have more members than group1. */
-   if (gr2->gr_mem[gr1_ndx] != NULL)
-   return (false);
-   }
+   /* Check all members in both groups.
+* getgrnam can return gr_mem with a pointer to NULL.
+* gr_dup and gr_add strip out this superfluous NULL, setting
+* gr_mem to NULL for no members.
+   */
+   if (gr1->gr_mem != NULL && gr2->gr_mem != NULL) {
+   int i;
+
+   for (i = 0; gr1->gr_mem[i] != NULL; i++) {
+   if (strcmp(gr1->gr_mem[i], gr2->gr_mem[i]) != 0)
+   return (false);
+   }
+   }
+   /* Count number of members in both structs */
+   gr2_ndx = 0;
+   if (gr2->gr_mem != NULL)
+   for(; gr2->gr_mem[gr2_ndx] != NULL; gr2_ndx++)
+   /* empty */;
+   gr1_ndx = 0;
+   if (gr1->gr_mem != NULL)
+   for(; gr1->gr_mem[gr1_ndx] != NULL; gr1_ndx++)
+   /* empty */;
+   if (gr1_ndx != gr2_ndx)
+   return (false);
 
return (true);
 }
@@ -439,21 +443,21 @@ gr_dup(const struct group *gr)
 struct group *
 gr_add(const struct group *gr, const char *newmember)
 {
-   struct group *newgr;
+   char *mem;
size_t len;
int num_mem;
 
num_mem = 0;
len = grmemlen(gr, newmember, &num_mem);
/* Create new group and copy old group into it. */
-   if ((newgr = malloc(len)) == NULL)
+   if ((mem = malloc(len)) == NULL)
return (NULL);
-   return (grcopy(gr, newgr, newmember, num_mem));
+   return (grcopy(gr, mem, newmember, num_mem));
 }
 
 /* It is safer to walk the pointers given at gr_mem since there is no
- * guarantee the gr_mem + strings are continguous in the given struct group
- * but compact the new group into the following form.
+ * guarantee the gr_mem + strings are contiguous in the given struct group
+ * but compactify the new group into the following form.
  *
  * The new struct is laid out like this in memory. The example given is
  * for a group with two members only.
@@ -474,23 +478,21 @@ gr_add(const struct group *gr, const cha
  * }
  */
 /*
- * Copy the guts of a group plus given name to a preallocated group struct
+ * Copy the contents of a group plus given name to a preallocated group struct
  */
 static struct group *
-grcopy(const struct group *gr, struct group *newgr, const char *name, int ndx)
+grcopy(const struct group *gr, char *dst, const char *name, int ndx)
 {
-   char *dst;
int i;
+   struct group *newgr;
 
-   if (name != NULL)
-   ndx++;
-   /* point new gr_mem to end of struct + 1 if there are names */
-   if (ndx != 0)
-   newgr->gr_mem = (char **)(newgr + 1);
-   else
+   newgr = (struct group *)(void *)dst;/* avoid alignment warning */
+   dst += sizeof(*newgr);
+   if (ndx != 0) {
+   newgr->gr_mem = (char **)(void *)(dst); /* avoid alignment 
warning */
+   dst += (ndx + 1) * sizeof(*newgr->gr_mem);
+   } else
newgr->gr_mem = NULL;
-   /* point dst a