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
