diff options
author | Michael Stone <michael@laptop.org> | 2007-12-23 02:41:31 (GMT) |
---|---|---|
committer | Michael Stone <michael@laptop.org> | 2007-12-23 02:41:31 (GMT) |
commit | bb291807b27d5dcbbb9302bd8c7aff5e7d12484b (patch) | |
tree | fc1030b3ae967652468163806364e3bab962c320 | |
parent | 0a15ac730fb533eb5daeaa27134f9ecbd82b5a37 (diff) |
Commit logic is ready; start filling in the passwd struct.
-rw-r--r-- | nss-rainbow.c | 92 |
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; } |