1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
|
#! /bin/sh /usr/share/dpatch/dpatch-run
## 04_use_array_for_getgrent.dpatch by Stephen Gran <sgran@debian.org>
##
## All lines beginning with `## DP:' are a description of the patch.
## DP: Use a single lookup for all groups, instead of one to seed the
## DP: list and one for each group found.
@DPATCH@
--- a/src/backend.c 2007-09-02 21:55:33.000000000 -0400
+++ b/src/backend.c 2007-09-02 22:14:39.000000000 -0400
@@ -23,6 +23,7 @@
#define GROUP_NAME 0
#define GROUP_PASSWD 1
#define GROUP_GID 2
+#define GROUP_MEM 3
/* define passwd column names */
#define PASSWD_NAME 0
#define PASSWD_PASSWD 1
@@ -218,6 +219,85 @@
return NSS_STATUS_SUCCESS;
}
+enum nss_status
+copy_attr_grouparray(char *sptr,
+ char **valptr, char **buffer, size_t *buflen, int *errnop)
+{
+ size_t slen;
+
+ slen = strlen(sptr);
+ if(*buflen < slen+1) {
+ *errnop = ERANGE;
+ return NSS_STATUS_TRYAGAIN;
+ }
+ strncpy(*buffer, sptr, slen);
+ (*buffer)[slen] = '\0';
+
+
+ *valptr = *buffer;
+
+ *buffer += slen + 1;
+ *buflen -= slen + 1;
+
+ return NSS_STATUS_SUCCESS;
+}
+
+
+enum nss_status getgroupmemarray(PGresult *res,
+ struct group *result,
+ char *buffer, size_t buflen, int row, int *errnop)
+{
+ char *sptr, *saveptr;
+ int end = 0;
+ int n;
+ int t;
+
+ enum nss_status status = NSS_STATUS_NOTFOUND;
+ size_t ptrsize;
+
+ // TODO - parse array member and get number of elements
+
+ sptr = PQgetvalue(res, row, GROUP_MEM);
+ end = strlen(sptr) - 1;
+
+ if (end < 2) {
+ end = 0;
+ }
+ char *token[end+1];
+ if ( (0 == strncmp(sptr, "{", 1)) && (0 == strncmp(sptr+end, "}", 1)) ) {
+ sptr[end] = '\0';
+ sptr++;
+ }
+ for (n = 0 ; ; sptr = NULL, n++) {
+ if ( (token[n] = strtok_r(sptr, ",", &saveptr) ) == NULL )
+ break;
+ }
+
+ // Make sure there's enough room for the array of pointers to group member names
+ ptrsize = (n+1) * sizeof(const char *);
+ if(buflen < ptrsize) {
+ status = NSS_STATUS_TRYAGAIN;
+ *errnop = ERANGE;
+ return status;
+ }
+
+ result->gr_mem = (char**)buffer;
+
+ buffer += (ptrsize+3)&(~0x3);
+ buflen -= (ptrsize+3)&(~0x3);
+
+ status = NSS_STATUS_SUCCESS;
+
+ for(t = 0; t < n; t++) {
+ status = copy_attr_grouparray(token[t], &(result->gr_mem[t]), &buffer, &buflen, errnop);
+ if(status != NSS_STATUS_SUCCESS)
+ return status;
+ }
+ result->gr_mem[t] = NULL;
+
+ return status;
+}
+
/*
* return array of strings containing usernames that are member of group with gid 'gid'
@@ -319,7 +399,8 @@
result->gr_gid = (gid_t)strtoul(PQgetvalue(res, 0, GROUP_GID), (char**)NULL, 10);
- status = getgroupmem(result->gr_gid, result, buffer, buflen, errnop);
+ status = getgroupmemarray(res, result, buffer, buflen, 0, errnop);
+ if(status != NSS_STATUS_SUCCESS) goto BAIL_OUT;
#ifdef DEBUG
if (status == NSS_STATUS_SUCCESS) {
@@ -477,7 +558,7 @@
}
localerrno = *errnop;
PQclear(res);
- if (status == NSS_STATUS_TRYAGAIN && *errnop == ERANGE) {
+ if (status == NSS_STATUS_TRYAGAIN && localerrno == ERANGE) {
res = putback("allgroups");
PQclear(res);
}
Index: conf/nss-pgsql.conf
===================================================================
--- a/conf/nss-pgsql.conf (revision 74)
+++ b/conf/nss-pgsql.conf (working copy)
@@ -11,9 +11,9 @@
# All users
allusers = SELECT username, passwd, gecos, homedir, shell, uid, gid FROM passwd_table
# Must return group_name, group_passwd, group_gid
-getgrnam = SELECT groupname, passwd, gid FROM group_table WHERE groupname = $1
+getgrnam = SELECT groupname, passwd, gid, ARRAY(SELECT username FROM usergroups WHERE usergroups.gid = group_table.gid) AS members FROM group_table WHERE groupname = $1
# Must return group_name, group_passwd, group_gid
-getgrgid = SELECT groupname, passwd, gid FROM group_table WHERE gid = $1
+getgrgid = SELECT groupname, passwd, gid, ARRAY(SELECT username FROM usergroups WHERE usergroups.gid = group_table.gid) AS members FROM group_table WHERE gid = $1
# Must return gid. %s MUST appear first for username match in where clause
groups_dyn = SELECT ug.gid FROM passwd_table JOIN usergroups USING (uid) where username = $1 and ug.gid <> $2
-allgroups = SELECT groupname, passwd, gid FROM group_table
+allgroups = SELECT groupname, passwd, gid, ARRAY(SELECT username FROM usergroups WHERE usergroups.gid = group_table.gid) AS members FROM group_table
|