On Sat, Dec 06, 2008 at 04:20:45PM +0200, John Tytgat wrote:
> In message <[email protected]>
> Theo Markettos <[email protected]> wrote:
>
> > Anyway, attached is a patch to provide getgrouplist() for review.
>
> I would break out this getgrouplist() implementation into a new file in
> grp directory. When you would do that, add something like this:
I've made most of the changes you suggested - new patch attached.
> > + while ((grp = getgrent ()) !=NULL)
> > + {
> > + char **mem;
>
> const char ** would be slightly better.
That doesn't work, because we have to modify the value of mem.
> What about doing a #include "../../grp/getgrouplist.c" instead (assuming you
> have your getgrouplist implementation in a separate file) and have the
> differences between this version and the UnixLib implementation covered with
> a test on __riscos ? So that we're sure that any changes in
> libunixlib/grp/getgrouplist.c are under test when compiling and running
> libunixlib/test/grp/getgrouplist.c ?
That's a good idea - I've done this.
Theo
Index: gcc4/recipe/files/libunixlib/grp/getgrouplist.c
===================================================================
--- gcc4/recipe/files/libunixlib/grp/getgrouplist.c (revision 0)
+++ gcc4/recipe/files/libunixlib/grp/getgrouplist.c (revision 0)
@@ -0,0 +1,133 @@
+/* getgrouplist ()
+ * Copyright (c) 2008 UnixLib Developers
+ * Written by Theo Markettos.
+ */
+
+#include <errno.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <grp.h>
+#include <pthread.h>
+
+/* enable this to be built on a non-RISC OS system to test */
+#ifndef __riscos
+#define __set_errno(x) x
+#else
+#include <internal/unix.h>
+#endif
+
+
+/* getgrouplist():
+
+Standard:
+http://refspecs.freestandards.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/baselib-getgrouplist-3.html
+Quote:
+
+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, getgrouplist() 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;
+
+#ifdef __riscos
+ PTHREAD_UNSAFE_CANCELLATION
+#else
+ FILE *f;
+#endif
+ /* 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);
+
+#ifndef __riscos
+/* If building on a non-RISC OS system, use fgetgrent so we can read a test group file */
+ f=fopen("test.group","r");
+
+ if (!f) { fprintf(stderr,"Can't file group file test.group\n");abort();}
+#endif
+
+ /* Iterate through the group structure, copying gids of groups
+ * we find that match. Leave at least one space at the end.
+ */
+#ifdef __riscos
+ while ((grp = getgrent ()) !=NULL)
+#else
+ while (( (grp = fgetgrent(f))!=NULL) )
+#endif
+ {
+ 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;
+}
+
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,116 @@
+/*
+ * 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) 2008 UnixLib Developers
+ */
+
+/* if not on RISC OS include our own copy of the function */
+#ifndef __riscos
+#include "../../grp/getgrouplist.c"
+#else
+#include <errno.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <grp.h>
+#include <pthread.h>
+#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,f) {if(a==b) printf(" PASS! Expected %s=%s\n",#a,#b); else {printf(" FAIL! Expected %s=%s!\n",#a,#b);f=1;}}
+#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;
+ int fail=0;
+
+/* 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,fail)
+
+ GETGROUPLIST(user,group,groups,n,result);
+ TEST(result,EINVAL,fail);
+
+ user="zzzz";
+ GETGROUPLIST(user,group,groups,n,result);
+ TEST(result,EINVAL,fail);
+
+ ngroups=0;
+ GETGROUPLIST(user,group,groups,&ngroups,result);
+ TEST(result,EINVAL,fail);
+
+ ngroups=3;
+ user="missing";
+ GETGROUPLIST(user,group,groups,&ngroups,result);
+ TEST(result,0,fail);
+ TEST(ngroups,0,fail);
+
+ ngroups=3;
+ user="bill";
+ group=(gid_t) 123;
+ GETGROUPLIST(user,group,groups,&ngroups,result);
+ TEST(result,-1,fail);
+ TEST(ngroups,3,fail);
+ SHOWGROUPS(groups,ngroups);
+
+ ngroups=3;
+ user="fred";
+ group=(gid_t) 123;
+ GETGROUPLIST(user,group,groups,&ngroups,result);
+ TEST(result,3,fail);
+ TEST(ngroups,3,fail);
+ SHOWGROUPS(groups,ngroups);
+
+ ngroups=20;
+ user="bill";
+ group=(gid_t) 123;
+ GETGROUPLIST(user,group,groups,&ngroups,result);
+ TEST(result,6,fail);
+ TEST(ngroups,6,fail);
+ SHOWGROUPS(groups,ngroups);
+
+ ngroups=20;
+ user="bill";
+ group=(gid_t) 44;
+ GETGROUPLIST(user,group,groups,&ngroups,result);
+ TEST(result,5,fail);
+ TEST(ngroups,5,fail);
+ SHOWGROUPS(groups,ngroups);
+
+ ngroups=5;
+ user="bill";
+ group=(gid_t) 44;
+ GETGROUPLIST(user,group,groups,&ngroups,result);
+ TEST(result,5,fail);
+ TEST(ngroups,5,fail);
+ SHOWGROUPS(groups,ngroups);
+
+ return fail;
+}
+
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