Peter's given me SVN commit access.  However there are a few things I want
to clear up before I start doing anything:

Is there a policy on code review?  Apart from fixing simple bugs, I probably
don't want to start committing chunks of code without at least giving
someone else the chance to say I'm being stupid.  Shall I continue to post
patches to the list for feedback?

What's the autobuilder settings to build for the packaging website?  I had a
go with a standard SVN HEAD checkout of both GCC4 and autobuilder, and it
built everything as ELF very nicely.  But it also packaged them as ELF,
which wasn't so good.  Do I need to have a 3.4 AIF compiler handy as well?
(and if so, can they coexist?) Or do you just run elf2aif on everything? 
I tried that, but it said:

: ELF file 'ls,e1f' contains non-static program data which makes it
: unconvertable to AIF

Is that the default autobuilder setup building for a shared library system? 
Should programs for the end-user be built static?

If I want to run ELF programs, what do I need?  I couldn't find anything on
the wiki about this.

Anyway, attached is a patch to provide getgrouplist() for review.  This
enables coreutils to build.  I haven't been able to test it on RISC OS, but
there's a test program and file included, which covers it fairly thoroughly. 
As testing requires a known /etc/group (where does that end up on RISC OS?)
the test program needed a modified copy of the function to work on Unix.  So
it's only a regression test if run on RISC OS and you can introduce the
supplied 'test.group' file as /etc/group for the duration of the test.

Theo
Index: gcc4/recipe/files/libunixlib/grp/getgroups.c
===================================================================
--- gcc4/recipe/files/libunixlib/grp/getgroups.c	(revision 3564)
+++ gcc4/recipe/files/libunixlib/grp/getgroups.c	(working copy)
@@ -25,6 +25,102 @@
 static int g_ngroups = 0;
 
 
+/* getgrouplist():
+
+Standard:
+http://refspecs.freestandards.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/baselib-getgrouplist-3.html
+
+Description
+
+The getgrouplist() function shall fill in the array groups with the
+supplementary groups for the user specified by user. On entry, ngroups shall
+refer to an integer containing the maximum number of gid_t members in the
+groups array. The group group shall also be included. On success, the value
+referred to by ngroups shall be updated to contain the number of gid_t
+objects copied.
+
+Return Value
+
+On success, if there was sufficient room to copy all the supplementatry
+group identifiers to the array identified by groups, getgrouplist() shall
+return the number of gid_t objects copied, and the value referenced by
+ngroups shall be updated. If there was not sufficient room to copy all the
+supplementary group identifiers, grouplist() shall return -1, and update the
+value referenced by ngroups to the number actually copied.
+
+If user does not refer to a valid user on the system, getgrouplist() shall
+return 0, and set the value referenced by ngroups to 0
+
+*/
+
+int
+getgrouplist (const char *user, gid_t group, gid_t *groups, int *ngroups)
+{
+  struct group *grp;
+  int grps_copied=0;
+  int moretocome=0;
+
+  PTHREAD_UNSAFE_CANCELLATION
+  
+  /* Need a group name to lookup */
+  if (user == NULL)
+    return __set_errno (EINVAL);
+
+  /* And somewhere to store the results */
+  if (groups == NULL)
+    return __set_errno (EINVAL);
+
+  if (ngroups == NULL)
+    return __set_errno (EINVAL);
+
+  /* Need space to copy in at least one group ID */
+  if (*ngroups <= 0)
+    return __set_errno (EINVAL);
+
+  /* Iterate through the group structure, copying gids of groups
+   * we find that match.  Leave at least one space at the end.
+   */
+  while ((grp = getgrent ()) !=NULL)
+    {
+      char **mem;
+
+      for (mem = grp->gr_mem;
+	   *mem && grps_copied < *ngroups;
+           ++mem)
+        {
+          if ((strcmp (*mem, user) == 0) && (grp->gr_gid!=group))
+          {  
+            if ((grps_copied+1) < (*ngroups))
+              groups[grps_copied++] = grp->gr_gid;
+            else
+              moretocome++;
+          }
+        }
+    }
+  endgrent ();
+  
+  /* if we failed to find this group anywhere, then indicate that */
+  if (grps_copied==0)
+  {
+    *ngroups=0;
+    return 0;
+  }
+  
+  /* tag on to the end the group we were told to add */
+  groups[grps_copied++] = group;
+
+  /* Return the number we copied */
+  *ngroups = grps_copied;
+
+  /* Return -1 if there are still more to copy */
+  if (moretocome)
+    return -1;
+
+  /* We succeeded, so return the number of groups we did find */
+  return grps_copied;
+}
+
+
 /* Get a list of all supplementary groups this user is in.  */
 int
 getgroups (int gidsetlen, gid_t *gidset)
Index: gcc4/recipe/files/libunixlib/test/grp/getgrouplist.c
===================================================================
--- gcc4/recipe/files/libunixlib/test/grp/getgrouplist.c	(revision 0)
+++ gcc4/recipe/files/libunixlib/test/grp/getgrouplist.c	(revision 0)
@@ -0,0 +1,214 @@
+/*
+ * Test function for getgrouplist()
+ *
+ * If built for RISC OS, will use the group file in /etc/group:
+ * need to copy the file test.groups there before running the test
+ * (and probably replace it afterwards with what was there before)
+ *
+ * If built for other platforms it'll use the host C library functions to
+ * read the file 'test.group' in the current directory.  It'll only test
+ * the copy of getgrouplist() found in this file, not the one in
+ * the main UnixLib tree.
+ *
+ * Copyright (c) 2002-2008 UnixLib Developers
+ */
+
+
+#include <errno.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <grp.h>
+#include <pthread.h>
+
+#ifndef __riscos
+
+
+/* getgrouplist():
+
+Standard:
+http://refspecs.freestandards.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/baselib-getgrouplist-3.html
+
+Description
+
+The getgrouplist() function shall fill in the array groups with the
+supplementary groups for the user specified by user. On entry, ngroups shall
+refer to an integer containing the maximum number of gid_t members in the
+groups array. The group group shall also be included. On success, the value
+referred to by ngroups shall be updated to contain the number of gid_t
+objects copied.
+
+Return Value
+
+On success, if there was sufficient room to copy all the supplementatry
+group identifiers to the array identified by groups, getgrouplist() shall
+return the number of gid_t objects copied, and the value referenced by
+ngroups shall be updated. If there was not sufficient room to copy all the
+supplementary group identifiers, grouplist() shall return -1, and update the
+value referenced by ngroups to the number actually copied.
+
+If user does not refer to a valid user on the system, getgrouplist() shall
+return 0, and set the value referenced by ngroups to 0
+
+*/
+
+int
+getgrouplist (const char *user, gid_t group, gid_t *groups, int *ngroups)
+{
+  struct group *grp;
+  int grps_copied=0;
+  FILE *f;
+  int moretocome=0;
+
+  /* Need a group name to lookup */
+  if (user == NULL)
+    return (EINVAL);
+
+  /* And somewhere to store the results */
+  if (groups == NULL)
+    return (EINVAL);
+
+  if (ngroups == NULL)
+    return (EINVAL);
+
+  /* Need space to copy in at least one group ID */
+  if (*ngroups <= 0)
+    return (EINVAL);
+
+  f=fopen("test.group","r");
+
+  if (!f) { fprintf(stderr,"Can't file group file test.group\n");abort();}
+
+  /* Iterate through the group structure, copying gids of groups
+   * we find that match.  Leave at least one space at the end.
+   */
+   
+  while (( (grp = fgetgrent(f))!=NULL) )
+    {
+      char **mem;
+
+      for (mem = grp->gr_mem;
+	   *mem && grps_copied < *ngroups;
+           ++mem)
+        {
+          if ((strcmp (*mem, user) == 0) && (grp->gr_gid!=group))
+          {
+            if ((grps_copied+1) < (*ngroups))
+              groups[grps_copied++] = grp->gr_gid;
+            else
+              moretocome++;
+          }
+        }
+    }
+  endgrent ();
+  
+  /* if we failed to find this group anywhere, then indicate that */
+  if (grps_copied==0)
+  {
+    *ngroups=0;
+    return 0;
+  }
+  
+  /* tag on to the end the group we were told to add */
+  groups[grps_copied++] = group;
+
+  /* Return the number we copied */
+  *ngroups = grps_copied;
+
+  /* Return -1 if there are still more to copy */
+  if (moretocome)
+    return -1;
+
+  /* We succeeded, so return the number of groups we did find */
+  return grps_copied;
+}
+
+#endif
+
+#define IN(a,b,c,d) printf("Calling getgrouplist(\"%s\",%d,%x,%x) ",a,b,c,d);\
+if (d) printf(" ngroups=%d ",*d);
+#define OUT(r) printf(" result=%d ",r);
+#define GETGROUPLIST(a,b,c,d,e) IN(a,b,c,d);e=getgrouplist(a,b,c,d);OUT(e)
+#define TEST(a,b) {if(a==b) printf(" PASS! Expected %s=%s\n",#a,#b); else printf(" FAIL! Expected %s=%s!\n",#a,#b);}
+#define SHOWGROUPS(grps,ngrps) { int i=0; for (i=0; i<ngrps; i++) {printf("GID %d = %d\n",i,grps[i]);}}
+
+int main(void)
+{
+  char *user=NULL;
+  gid_t group=0;
+  gid_t groups[100];
+  int ngroups;
+  int result=0;
+  int *n=NULL;
+
+/* these tests won't work unless you have the right group file in place - see above */
+#ifdef __riscos
+  fprintf(stderr,"libunixlib/test/grp/getgrouplist.c will only work if you have\n"\
+  "copied in libunixlib/test/grp/test.group into /etc/group on RISC OS.\n" \
+  "Make sure you restore /etc/group afterwards.\n");
+#endif
+  
+  GETGROUPLIST(user,group,n,n,result);
+  TEST(result,EINVAL)
+  
+  GETGROUPLIST(user,group,groups,n,result);
+  TEST(result,EINVAL);
+    
+  user="zzzz";
+  GETGROUPLIST(user,group,groups,n,result);
+  TEST(result,EINVAL);
+
+  ngroups=0;
+  GETGROUPLIST(user,group,groups,&ngroups,result);
+  TEST(result,EINVAL);
+
+  ngroups=3;
+  user="missing";
+  GETGROUPLIST(user,group,groups,&ngroups,result);
+  TEST(result,0);
+  TEST(ngroups,0);
+
+  ngroups=3;
+  user="bill";
+  group=(gid_t) 123;
+  GETGROUPLIST(user,group,groups,&ngroups,result);
+  TEST(result,-1);
+  TEST(ngroups,3);
+  SHOWGROUPS(groups,ngroups);  
+
+  ngroups=3;
+  user="fred";
+  group=(gid_t) 123;
+  GETGROUPLIST(user,group,groups,&ngroups,result);
+  TEST(result,3);
+  TEST(ngroups,3);
+  SHOWGROUPS(groups,ngroups);  
+
+  ngroups=20;
+  user="bill";
+  group=(gid_t) 123;
+  GETGROUPLIST(user,group,groups,&ngroups,result);
+  TEST(result,6);
+  TEST(ngroups,6);
+  SHOWGROUPS(groups,ngroups);  
+
+  ngroups=20;
+  user="bill";
+  group=(gid_t) 44;
+  GETGROUPLIST(user,group,groups,&ngroups,result);
+  TEST(result,5);
+  TEST(ngroups,5);
+  SHOWGROUPS(groups,ngroups);  
+
+  ngroups=5;
+  user="bill";
+  group=(gid_t) 44;
+  GETGROUPLIST(user,group,groups,&ngroups,result);
+  TEST(result,5);
+  TEST(ngroups,5);
+  SHOWGROUPS(groups,ngroups);  
+
+}
+
Index: gcc4/recipe/files/libunixlib/test/grp/test.group
===================================================================
--- gcc4/recipe/files/libunixlib/test/grp/test.group	(revision 0)
+++ gcc4/recipe/files/libunixlib/test/grp/test.group	(revision 0)
@@ -0,0 +1,54 @@
+root:x:0:
+daemon:x:1:
+bin:x:2:
+sys:x:3:
+adm:x:4:
+tty:x:5:
+disk:x:6:
+lp:x:7:lp
+mail:x:8:
+news:x:9:
+uucp:x:10:
+proxy:x:13:
+kmem:x:15:
+dialout:x:20:
+fax:x:21:
+voice:x:22:
+cdrom:x:24:dave
+floppy:x:25:
+tape:x:26:smith,tony,dave,bill,mike
+sudo:x:27:
+audio:x:29:dave
+dip:x:30:tony
+postgres:x:32:jones
+www-data:x:33:
+backup:x:34:
+operator:x:37:
+list:x:38:
+irc:x:39:
+src:x:40:dave
+gnats:x:41:
+shadow:x:42:
+utmp:x:43:bill
+video:x:44:bill
+staff:x:50:bill
+games:x:60:
+scanner:x:70:dave
+users:x:100:
+nogroup:x:65534:
+dave:x:1000:
+lpadmin:x:101:
+man:*:12:
+sasl:*:45:
+crontab:x:102:
+ssh:x:103:
+camera:x:105:dave
+plugdev:*:46:
+Debian-exim:x:107:
+webadmin:x:1001:dave,www-data,fred
+mysql:x:108:bill
+archive:x:1003:archive,dave
+messagebus:x:109:
+fuse:x:110:dave
+ssl-cert:x:113:postgres
+ARMBOOT:x:1006:fred
Index: gcc4/recipe/files/libunixlib/include/grp.h
===================================================================
--- gcc4/recipe/files/libunixlib/include/grp.h	(revision 3564)
+++ gcc4/recipe/files/libunixlib/include/grp.h	(working copy)
@@ -109,6 +109,12 @@
    This function is a cancellation point.  */
 extern int initgroups (const char *__name, gid_t __basegid)
      __nonnull ((1));
+
+/* Return a list of groups the user is in */
+extern int getgrouplist (const char *__user, gid_t __group,
+    gid_t *__groups, int *__ngroups);
+     __nonnull ((1,3,4));
+
 #endif
 
 __END_DECLS
_______________________________________________
GCCSDK mailing list [email protected]
Bugzilla: http://www.riscos.info/bugzilla/index.cgi
List Info: http://www.riscos.info/mailman/listinfo/gcc
Main Page: http://www.riscos.info/index.php/GCCSDK

Reply via email to