Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Stone <michael@laptop.org>2007-12-23 02:41:31 (GMT)
committer Michael Stone <michael@laptop.org>2007-12-23 02:41:31 (GMT)
commitbb291807b27d5dcbbb9302bd8c7aff5e7d12484b (patch)
treefc1030b3ae967652468163806364e3bab962c320
parent0a15ac730fb533eb5daeaa27134f9ecbd82b5a37 (diff)
Commit logic is ready; start filling in the passwd struct.
-rw-r--r--nss-rainbow.c92
1 files changed, 73 insertions, 19 deletions
diff --git a/nss-rainbow.c b/nss-rainbow.c
index 0175ca4..0825a4d 100644
--- a/nss-rainbow.c
+++ b/nss-rainbow.c
@@ -2,6 +2,7 @@
#include <stdio.h>
#include <pwd.h>
#include <stdint.h>
+#include <stdbool.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
@@ -25,8 +26,13 @@
/* state */
enum rainbow_nss_state {
- STATE_UNINITIALIZED, /* we have never opened our db. */
- STATE_ITERATING, /* the DB is open and we are ready to return entries */
+ DB_UNINITIALIZED, /* we have never opened our db. */
+ DB_ITERATING, /* the DB is open and we are ready to return entries */
+};
+
+enum rainbow_entry_state {
+ ENTRY_FIZZLE,
+ ENTRY_COMMITTED,
};
/* We want a maximally simple database. Therefore, we will use a fixed array of
@@ -54,14 +60,13 @@ static struct pw_state {
struct frozen_passwd_db* db_mem;
int cur_entry;
} PW_STATE = {
- .state = STATE_UNINITIALIZED,
+ .state = DB_UNINITIALIZED,
.db_fd = 0,
.db_mem = 0,
.cur_entry = 0,
};
/* implementation */
-
enum nss_status
_nss_rainbow_endpwent(void) {
CHECK(int, -1,
@@ -80,7 +85,7 @@ out_error_0:
enum nss_status
_nss_rainbow_setpwent(void) {
- if (PW_STATE.state == STATE_ITERATING) {
+ if (PW_STATE.state == DB_ITERATING) {
CHECK(int, NSS_STATUS_UNAVAIL,
_nss_rainbow_endpwent(),
out_error_0, "Unable to terminate previous rainbow-passwd-db iterator.");
@@ -97,7 +102,7 @@ _nss_rainbow_setpwent(void) {
PW_STATE.db_fd = fd;
PW_STATE.db_mem = (struct frozen_passwd_db*) memory;
PW_STATE.cur_entry = 0;
- PW_STATE.state = STATE_ITERATING;
+ PW_STATE.state = DB_ITERATING;
return NSS_STATUS_SUCCESS;
@@ -108,28 +113,77 @@ out_error_0:
return NSS_STATUS_UNAVAIL;
}
+/* XXX: Endianness issues need to be worked out. */
+/* returns false on error */
+bool check_frozen_passwd(struct frozen_passwd const * ent) {
+ return false;
+}
-enum nss_status
-_nss_rainbow_getpwent_r(struct passwd *result, char* buffer, size_t buflen, int *errnop) {
- result = result; buffer = buffer; buflen = buflen; errnop = errnop; /* unused variable warnings */
-
- /* See gcc.info: (Atomic Builtins) */
- int real_entry = __sync_fetch_and_add((int*)&PW_STATE.cur_entry, 1);
-
- /*
- if (PW_STATE.cur == PW_STATE.num)
- return NSS_STATUS_NOTFOUND;
- result->pw_name = "hi";
+/* returns false on error */
+bool fill_passwd(struct passwd* pw, struct frozen_passwd const * ent) {
+
+ /* Is there any way to avoid page faults in this function? */
+ /* strncpy(result->pw_name, ent-> .... */
result->pw_passwd = "";
result->pw_uid = 1000;
result->pw_gid = 2000;
result->pw_gecos = "hi@laptop.org";
result->pw_dir = "/activities/uid_to_home_dir/1000";
result->pw_shell = "/bin/nologin";
+
+ return true;
+
+out_error:
+ return false;
+}
+
- PW_STATE.cur++;
- */
+enum nss_status
+_nss_rainbow_getpwent_r(struct passwd *result, char* buffer, size_t buflen, int *errnop) {
+ result = result; buffer = buffer; buflen = buflen; errnop = errnop; /* unused variable warnings */
+
+ /* I'm going to interpret the reentrancy requirement on this function to mean
+ * that the sequence of all results returned by all calls to this function
+ * between calls to setpwent() should contain contain every entry exactly
+ * once. It is undefined whether writes to the underlying storage that
+ * interleave with calls to getpwent() will be visible to callers. */
+
+ int old_entry, new_entry;
+ bool commit_successful;
+ struct frozen_passwd* ent;
+
+initialize:
+ /* copy current entry to allow a later atomic update */
+ new_entry = old_entry = PW_STATE.cur_entry;
+
+search:
+ /* bounds-check our array index */
+ if(new_entry < 0 || new_entry > DB_LEN)
+ return NSS_STATUS_NOTFOUND;
+
+ /* search for an entry */
+ if (PW_STATE.db_mem->entry_states[new_entry] != ENTRY_COMMITTED) {
+ new_entry++;
+ goto search;
+ }
+
+ /* sanity-check result: [nb: array indexing is known safe] */
+ ent = &PW_STATE.db_mem->entries[new_entry];
+ if (!check_frozen_passwd(ent)) {
+ new_entry++;
+ goto search;
+ }
+
+ /* copy record into result buffer */
+ /* XXX: HOW DO WE KNOW THAT SUFFICIENT SPACE HAS BEEN ALLOCATED? */
+ fill_passwd(result, ent);
+
+ /* See gcc.info: (Atomic Builtins) */
+ commit_successful = __sync_bool_compare_and_swap(&PW_STATE.cur_entry, old_entry, new_entry);
+ if (!commit_successful)
+ goto initialize;
+
return NSS_STATUS_SUCCESS;
}