| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018 |
- /*
- * Copyright (c) 2019 Clementine Computing LLC.
- *
- * This file is part of PopuFare.
- *
- * PopuFare is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * PopuFare is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with PopuFare. If not, see <https://www.gnu.org/licenses/>.
- *
- */
- #include <sys/user.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/mman.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <string.h>
- #include <errno.h>
- #include "../common/common_defs.h"
- #include "passdb.h"
- static void free_rider_node_list(rider_node *head)
- {
- rider_node *p = head;
- rider_node *q;
- while(p)
- {
- q = p;
- p = p->next;
- free(q);
- }
- }
- #define FIND_IDX_IN_BUCKET(b, idx, p, q)\
- { \
- p = b; \
- q = NULL; \
- \
- while(p) \
- { \
- if(p->idx == idx) \
- { \
- break; \
- } \
- \
- q = p; \
- p = p->next; \
- } \
- } \
- //---------------------------
- #define ADD_TO_BUCKET(b, idx, p, q) \
- { \
- p = (rider_node *) malloc( sizeof(rider_node) );\
- \
- if(p == NULL) return FAIL_MEM; \
- \
- p->next = NULL; \
- p->idx = idx; \
- \
- if(q) \
- { \
- q->next = p; \
- } \
- else \
- { \
- b = p; \
- } \
- } \
- //---------------------------
- #define DEL_FROM_BUCKET(b, p, q) \
- { \
- if(q) \
- { \
- q->next = p->next; \
- } \
- else \
- { \
- b = p->next; \
- } \
- \
- free(p); \
- } \
- //---------------------------
- int find_id_in_hash(passdb_context *ctx, logical_card_id_t id)
- {
- rider_node *p;
- if(id <= 0)
- return FAIL_PARAM;
- p = ctx->logical_card_id_hash[id % STORED_PASS_HASH];
- while(p)
- {
- if(ctx->riders[p->idx].id == id)
- return p->idx;
- p = p->next;
- }
- return WARN_NOTFOUND;
- }
- int add_to_id_hash(passdb_context *ctx, int idx)
- {
- rider_node *p, *q;
- unsigned int bucket;
- if(idx < 0) return FAIL_PARAM;
- if(ctx->riders[idx].id == ID_INVALID) return FAIL_PARAM;
- bucket = ctx->riders[idx].id % STORED_PASS_HASH;
- FIND_IDX_IN_BUCKET( ctx->logical_card_id_hash[bucket], idx, p, q )
- if(p)
- {
- return FAIL_DUPKEY; //already exists!
- }
- else
- {
- ADD_TO_BUCKET( ctx->logical_card_id_hash[bucket], idx, p, q );
- return 0;
- }
- }
- int delete_from_id_hash(passdb_context *ctx, int idx)
- {
- rider_node *p, *q;
- unsigned int bucket;
- if(idx < 0) return FAIL_PARAM;
- bucket = ctx->riders[idx].id % STORED_PASS_HASH;
- FIND_IDX_IN_BUCKET( ctx->logical_card_id_hash[bucket], idx, p, q)
- if(p)
- {
- DEL_FROM_BUCKET( ctx->logical_card_id_hash[bucket], p, q )
- return 0;
- }
- else
- {
- return WARN_NOTFOUND;
- }
- }
- //##
- int find_mag_in_hash(passdb_context *ctx, char *mag)
- {
- rider_node *p;
- if(mag[0] == '\0') return FAIL_PARAM;
- p = ctx->rider_mag_hash[stringhash(mag) % STORED_PASS_HASH];
- while(p)
- {
- if(!strncmp(ctx->riders[p->idx].magstripe_value, mag, CREDENTIAL_LEN))
- return p->idx;
- p = p->next;
- }
- return WARN_NOTFOUND;
- }
- int add_to_mag_hash(passdb_context *ctx, int idx)
- {
- rider_node *p, *q;
- unsigned int bucket;
- if(idx < 0) return 0; //if we have a non index or a non-value, return silently
- if(ctx->riders[idx].magstripe_value[0] == '\0') return 0;
- bucket = stringhash(ctx->riders[idx].magstripe_value) % STORED_PASS_HASH;
- FIND_IDX_IN_BUCKET( ctx->rider_mag_hash[bucket], idx, p, q )
- #ifndef ALLOW_CREDENTIAL_COLLISIONS
- //On allowing hash collisions among credentials see comment tagged **STUPID** later in this file.
- if(p)
- {
- return FAIL_DUPKEY; //already exists!
- }
- else
- #endif
- {
- ADD_TO_BUCKET( ctx->rider_mag_hash[bucket], idx, p, q );
- return 0;
- }
- }
- int delete_from_mag_hash(passdb_context *ctx, int idx)
- {
- rider_node *p, *q;
- unsigned int bucket;
- if(idx < 0) return FAIL_PARAM;
- bucket = stringhash(ctx->riders[idx].magstripe_value) % STORED_PASS_HASH;
- FIND_IDX_IN_BUCKET( ctx->rider_mag_hash[bucket], idx, p, q)
- if(p)
- {
- DEL_FROM_BUCKET( ctx->rider_mag_hash[bucket], p, q )
- return 0;
- }
- else
- {
- return WARN_NOTFOUND;
- }
- }
- //##
- int find_rf_in_hash(passdb_context *ctx, char *rfid)
- {
- rider_node *p;
- if(rfid[0] == '\0') return WARN_NOTFOUND;
- p = ctx->rider_rf_hash[stringhash(rfid)% STORED_PASS_HASH];
- while(p)
- {
- if(!strncmp(ctx->riders[p->idx].rfid_value, rfid, CREDENTIAL_LEN))
- return p->idx;
- p = p->next;
- }
- return WARN_NOTFOUND;
- }
- int add_to_rf_hash(passdb_context *ctx, int idx)
- {
- rider_node *p, *q;
- unsigned int bucket;
- if(idx < 0) return 0; //if we have a non index or a non-value, return silently
- if(ctx->riders[idx].rfid_value[0] == '\0') return 0;
- bucket = stringhash(ctx->riders[idx].rfid_value) % STORED_PASS_HASH;
- FIND_IDX_IN_BUCKET( ctx->rider_rf_hash[bucket], idx, p, q )
- #ifndef ALLOW_CREDENTIAL_COLLISIONS
- //On allowing hash collisions among credentials see comment tagged **STUPID** later in this file.
- if(p)
- {
- return FAIL_DUPKEY; //already exists!
- }
- else
- #endif
- {
- ADD_TO_BUCKET( ctx->rider_rf_hash[bucket], idx, p, q );
- return 0;
- }
- }
- int delete_from_rf_hash(passdb_context *ctx, int idx)
- {
- rider_node *p, *q;
- unsigned int bucket;
- if(idx < 0) return FAIL_PARAM;
- bucket = stringhash(ctx->riders[idx].rfid_value) % STORED_PASS_HASH;
- FIND_IDX_IN_BUCKET( ctx->rider_rf_hash[bucket], idx, p, q)
- if(p)
- {
- DEL_FROM_BUCKET( ctx->rider_rf_hash[bucket], p, q )
- return 0;
- }
- else
- {
- return WARN_NOTFOUND;
- }
- }
- //##
- int build_hashes(passdb_context *ctx)
- {
- rider_node *p = ctx->activelist;
- int retval;
- while(p)
- {
- retval = add_to_id_hash(ctx, p->idx);
- if( !DB_OKAY(retval) )
- {
- fprintf(stderr, "Error (%d) indexing rider ID %llu at index %d!\n", retval, ctx->riders[p->idx].id, p->idx);
- return retval;
- }
- retval = add_to_mag_hash(ctx, p->idx);
- if( !DB_OKAY(retval) )
- {
- fprintf(stderr, "Error (%d) indexing magstripe %s at index %d!\n", retval, ctx->riders[p->idx].magstripe_value, p->idx);
- return -1;
- }
- retval = add_to_rf_hash(ctx, p->idx);
- if( !DB_OKAY(retval) )
- {
- fprintf(stderr, "Error (%d) indexing RFID %s at index %d!\n", retval, ctx->riders[p->idx].rfid_value, p->idx);
- return -1;
- }
- p = p->next;
- }
- return 0;
- }
- int format_new_passdb()
- {
- char blank[MEMORY_PAGE_SIZE] = {0};
- int i,n;
- int fd;
- fd = creat(PASSES_FILE, S_IRUSR | S_IWUSR);
- if( fd < 0 )
- {
- fprintf(stderr, "Cannot create pass file!\n");
- return FAIL_DATABASE;
- }
- n = PASS_MAP_SIZE / MEMORY_PAGE_SIZE;
- for(i = 0; i < n; i++)
- {
- if( write(fd, &blank, sizeof(blank)) != sizeof(blank) )
- {
- fprintf(stderr, "Cannot write blank data to passes file!\n");
- close(fd);
- return FAIL_DATABASE;
- }
- }
- close(fd);
- return 0;
- }
- int detach_from_passdb(passdb_context *ctx)
- {
- int i;
- if(!ctx)
- return FAIL_PARAM;
- free_rider_node_list(ctx->freelist);
- free_rider_node_list(ctx->activelist);
- for(i=0; i < STORED_PASS_HASH; i++)
- {
- free_rider_node_list(ctx->logical_card_id_hash[i]);
- free_rider_node_list(ctx->rider_mag_hash[i]);
- free_rider_node_list(ctx->rider_rf_hash[i]);
- }
- if(ctx->riders != NULL)
- {
- munmap(ctx->riders, PASS_MAP_SIZE);
- }
- if(ctx->mmap_broken)
- {
- close(ctx->passes_fd);
- }
- memset(ctx, 0, sizeof(passdb_context));
- return 0;
- }
- int attach_to_passdb(passdb_context *ctx)
- {
- int n;
- int retval;
- struct stat st;
- int fd;
- rider_record *foo;
- int mmap_broken;
- seq_t maxseq = 0;
- rider_node *freehead, *acthead, *q;
- int numfree, numact;
- int i;
- //--------
- if(!ctx) //fail if we get passed a null pointer
- return FAIL_PARAM;
- //We also want to fail if we get passed a pointer to an active/in-use context...
- if(ctx->riders || ctx->activelist || ctx->freelist)
- {
- return FAIL_PARAM;
- }
- mmap_broken = 0;
- //Go and stat the pass database file
- retval = stat(PASSES_FILE, &st);
- if(retval)
- {
- fprintf(stderr, "Cannot find passes file!\n");
- return FAIL_DATABASE;
- }
- //Make sure it is the right size...
- n = (st.st_size / sizeof(rider_record));
- if(n != NUM_STORED_PASSES)
- {
- fprintf(stderr, "Passes file contains %d records, expecting %d!\n", n, NUM_STORED_PASSES);
- return FAIL_DATABASE;
- }
- //open the file
- fd = open(PASSES_FILE, O_RDWR | O_SYNC);
- if(fd < 0)
- {
- fprintf(stderr, "Cannot open passes file!\n");
- return FAIL_DATABASE;
- }
- //mmap() the file into a pointer in our address space
- foo = (rider_record *) mmap(NULL, PASS_MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
- if( (foo == NULL) || (foo == MAP_FAILED) ) //if the MAP_SHARED option fails...
- {
- //try again with MAP_PRIVATE and see if it works...
- foo = (rider_record *) mmap(NULL, PASS_MAP_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
- if( (foo == NULL) || (foo == MAP_FAILED) )
- {
- close(fd);
- fprintf(stderr, "Cannot mmap passes file! Try checking sysctl settings kernel.shmall and kernel.shmmax (return == %p errno == %d)\n",foo,errno);
- return FAIL_MEM;
- }
- else
- {
- //set our mmap broken flag
- printf("mmap seems to be broken... operating in braindead file IO mode...\n");
- mmap_broken = 1;
- }
- }
- else
- {
- //close the file (we no longer need it open once it is mmap()'d)
- close(fd);
- }
- //------
- freehead = acthead = q = NULL;
- numfree = numact = 0;
- maxseq = 0;
- //For all records in our flat file
- for(i=0; i < n; i++)
- {
- //check the sequence number and update our "latest" tally if it is newer.
- if(foo[i].seq > maxseq)
- {
- maxseq = foo[i].seq;
- }
- //if the record is not in use
- if(foo[i].id == ID_INVALID)
- {
- //add it to the freelist
- q = (rider_node *) malloc( sizeof(rider_node) );
- if(!q)
- {
- free_rider_node_list(freehead);
- free_rider_node_list(acthead);
- fprintf(stderr, "Malloc returned NULL loading riders!\n");
- munmap(foo, n * sizeof(rider_record));
- return FAIL_MEM;
- }
- else
- {
- numfree++;
- q->next = freehead;
- q->idx = i;
- freehead = q;
- }
- }
- else
- {
- //add it to the active list
- q = (rider_node *) malloc( sizeof(rider_node) );
- if(!q)
- {
- free_rider_node_list(freehead);
- free_rider_node_list(acthead);
- fprintf(stderr, "Malloc returned NULL loading riders!\n");
- munmap(foo, n * sizeof(rider_record));
- return FAIL_MEM;
- }
- else
- {
- numact++;
- q->next = acthead;
- q->idx = i;
- acthead = q;
- }
- }
- }
- ctx->riders = foo;
- ctx->freelist = freehead;
- ctx->activelist = acthead;
- ctx->seq = maxseq;
- retval = build_hashes(ctx);
- if( DB_FAIL(retval) )
- {
- fprintf(stderr, "Building hashes failed.\n");
- detach_from_passdb(ctx);
- return retval;
- }
- if(mmap_broken)
- {
- ctx->mmap_broken = 1;
- ctx->passes_fd = fd;
- }
- else
- {
- ctx->mmap_broken = 0;
- ctx->passes_fd = 0;
- }
- printf("Loaded and indexed %d records (%d used, %d free); Newest seq = %llu\n", n, numact, numfree, maxseq);
- return n;
- }
- static int copy_rider(rider_record *dst, rider_record *src)
- {
- if(! (src && dst) )
- return FAIL_PARAM;
- memcpy(dst, src, sizeof(rider_record));
- dst->rfid_value[CREDENTIAL_LEN - 1] = '\0';
- dst->magstripe_value[CREDENTIAL_LEN - 1] = '\0';
- dst->rule_name[RULENAME_LEN - 1] = '\0';
- dst->rule_param[PARAM_LEN - 1] = '\0';
- return 0;
- }
- static int alloc_rider(passdb_context *ctx)
- {
- rider_node *p;
- p = ctx->freelist;
- if(p)
- {
- ctx->freelist = ctx->freelist->next;
- p->next = ctx->activelist;
- ctx->activelist = p;
- return p->idx;
- }
- else
- {
- return FAIL_FULL;
- }
- }
- static int free_rider(passdb_context *ctx, int idx)
- {
- rider_node *p, *q;
- q = NULL;
- p = ctx->activelist;
- while(p)
- {
- if( p->idx == idx )
- break;
- q = p;
- p = p->next;
- }
- if(p)
- {
- if(q)
- {
- q->next = p->next;
- }
- else
- {
- ctx->activelist = p->next;
- }
- p->next = ctx->freelist;
- ctx->freelist = p;
- memset(&ctx->riders[idx], 0, sizeof(rider_record));
- ctx->riders[idx].id = ID_INVALID;
- return 0;
- }
- else
- {
- return WARN_NOTFOUND;
- }
- }
- static void sync_rider_change(passdb_context *ctx, int idx)
- {
- int offset;
- int retval;
- if(idx < 0)
- return;
- if(idx >= NUM_STORED_PASSES)
- return;
- if(!ctx)
- return;
- if(ctx->mmap_broken)
- {
- offset = (idx * sizeof(rider_record)) / MEMORY_PAGE_SIZE; //calculate the beginning page number
- offset *= MEMORY_PAGE_SIZE; //multiply by page size
- retval = lseek(ctx->passes_fd, offset, SEEK_SET);
- if(retval != offset)
- {
- fprintf(stderr, "lseek() failed in sync_rider_change(). errno = %d\n", errno);
- return;
- }
- retval = write(ctx->passes_fd, ((void *)ctx->riders) + offset, MEMORY_PAGE_SIZE);
- if(retval != MEMORY_PAGE_SIZE)
- {
- fprintf(stderr, "write() failed in sync_rider_change(). errno = %d\n", errno);
- return;
- }
- }
- else
- {
- retval = msync(ctx->riders, PASS_MAP_SIZE, MS_SYNC | MS_INVALIDATE);
- if(retval < 0)
- {
- fprintf(stderr, "msync() failed in sync_rider_change(). errno = %d\n", errno);
- return;
- }
- }
- }
- void sync_all_riders(passdb_context *ctx)
- {
- int retval;
- if(!ctx)
- return;
- if(ctx->mmap_broken)
- {
- retval = lseek(ctx->passes_fd, 0, SEEK_SET);
- if(retval != 0)
- {
- fprintf(stderr, "lseek() failed in sync_all_riders(). errno = %d\n", errno);
- return;
- }
- retval = write(ctx->passes_fd, ctx->riders, PASS_MAP_SIZE);
- if(retval != PASS_MAP_SIZE)
- {
- fprintf(stderr, "write() failed in sync_all_riders(). errno = %d\n", errno);
- return;
- }
- }
- else
- {
- retval = msync(ctx->riders, PASS_MAP_SIZE, MS_SYNC | MS_INVALIDATE);
- if(retval < 0)
- {
- fprintf(stderr, "msync() failed in sync_all_riders(). errno = %d\n", errno);
- return;
- }
- }
- }
- int delete_rider(passdb_context *ctx, rider_record *rec, int sync)
- {
- int id_idx;
- if(!ctx)
- {
- return FAIL_PARAM;
- }
- if(!ctx->riders)
- {
- return FAIL_PARAM;
- }
- //If this record is older than out current database, ignore it as a duplicate.
- if( ctx->seq >= rec->seq )
- {
- return 0;
- }
- //find the record to be deleted in our ID hash
- id_idx = find_id_in_hash(ctx, rec->id);
- //If we didn't find it, it must have already been deleted...
- if(id_idx < 0)
- {
- return 0;
- }
- //delete it from all hashes
- delete_from_id_hash(ctx, id_idx);
- delete_from_mag_hash(ctx, id_idx);
- delete_from_rf_hash(ctx, id_idx);
- //free the record (this zeros out the entire block)
- free_rider(ctx, id_idx);
- //populate the seq number of this delete
- ctx->riders[id_idx].seq = rec->seq;
- //and sync our SHM
- if(sync)
- {
- sync_rider_change(ctx, id_idx);
- }
- return 1;
- }
- int update_rider(passdb_context *ctx, rider_record *rec, int sync)
- {
- int id_idx;
- int mag_idx;
- int rf_idx;
- int update_credentials = 0;
- int update_id_hash = 0;
- int retval;
- if(!ctx)
- {
- return FAIL_MEM;
- }
- if(!ctx->riders)
- {
- return FAIL_MEM;
- }
- //If this record is older than out current database, ignore it as a duplicate.
- if( ctx->seq >= rec->seq )
- {
- return 0;
- }
- id_idx = find_id_in_hash(ctx, rec->id);
- mag_idx = find_mag_in_hash(ctx, rec->magstripe_value);
- rf_idx = find_rf_in_hash(ctx, rec->rfid_value);
- // We want to allow a short period of magstrip or RFID collision as the lesser of two evils vs. **STUPID**
- // possibly losing a record due to a degenerately stupid administrator doing the following:
- //
- // 1) Create user 1 with magstripe '1:foo'
- // 2) Delete user 1
- // 3) Create user 2 with magstripe '1:foo'
- // 4) Create user 1 with magstripe '1:bar' <---- THIS IS NOT ALLOWED (Creating user 1 is dissalowed after a delete of user 1. This card should be created as user 3).
- //
- // The issue here is that if the bus asks what's happensed since sequence number 1, it will get rows
- // 3 and 4.
- //
- // In reality, we'd hope that each bus would complete a sync at least once on a shorter interval
- // than the frequency at which credentials are recycled, but you never know... And if somebody manually
- // fucks things up such that a user id (card id) is deleted, and then created again (this is a big no-no), we
- // can recover by allowing a hash collision to exist in the meantime.
- #ifndef ALLOW_CREDENTIAL_COLLISIONS
- if( (mag_idx >= 0) && (mag_idx != id_idx) )
- {
- fprintf(stderr, "Refusing to accept change that would introduce duplicate magstripe \"%s\" for records %llu and %llu.\n", rec->magstripe_value, ctx->riders[mag_idx].id, rec->id);
- return FAIL_DUPKEY;
- }
- if( (rf_idx >= 0) && (rf_idx != id_idx) )
- {
- fprintf(stderr, "Refusing to accept change that would introduce duplicate RFID \"%s\" for records %llu and %llu.\n", rec->rfid_value, ctx->riders[rf_idx].id, rec->id);
- return FAIL_DUPKEY;
- }
- #endif
- if(id_idx >= 0) //if rec->id already exists, we're updating an existing record...
- {
- //if EITHER the RFID or MAGSTRIPE values have changed...
- if( strncmp(ctx->riders[id_idx].magstripe_value, rec->magstripe_value, CREDENTIAL_LEN) || strncmp(ctx->riders[id_idx].rfid_value, rec->rfid_value, CREDENTIAL_LEN) )
- {
- update_credentials = 1;
- }
- }
- else //otherwise, we're creating a new record...
- {
- id_idx = alloc_rider(ctx);
- if(DB_FAIL(id_idx))
- {
- fprintf(stderr, "Error (%d) trying to allocate rider\n", id_idx);
- return id_idx;
- }
- update_credentials = update_id_hash = 1;
- }
- if(update_credentials)
- {
- delete_from_mag_hash(ctx, id_idx);
- delete_from_rf_hash(ctx, id_idx);
- }
- if(update_id_hash)
- {
- delete_from_id_hash(ctx, id_idx);
- }
- copy_rider( &ctx->riders[id_idx], rec );
- if(sync)
- {
- sync_rider_change(ctx, id_idx);
- }
- if(update_id_hash)
- {
- retval = add_to_id_hash(ctx, id_idx);
- if( !DB_OKAY(retval) )
- {
- fprintf(stderr, "Error (%d) updating id hash for record seq = %llu\n", retval, (unsigned long long)rec->seq);
- }
- }
- if(update_credentials)
- {
- retval = add_to_mag_hash(ctx, id_idx);
- if( !DB_OKAY(retval) )
- {
- fprintf(stderr, "Error (%d) updating magstripe hash for record seq = %llu\n", retval, (unsigned long long)rec->seq);
- }
- retval = add_to_rf_hash(ctx, id_idx);
- if( !DB_OKAY(retval) )
- {
- fprintf(stderr, "Error (%d) updating rf hash for record seq = %llu\n", retval, (unsigned long long)rec->seq);
- }
- }
- ctx->seq = rec->seq;
- return 1;
- }
- void dump_hashes(passdb_context *ctx)
- {
- int i;
- rider_node *p;
- if(!ctx)
- {
- printf("NULL Context!\n");
- return;
- }
- if(!ctx->riders)
- {
- printf("NULL Riders, no database mmap()'d!\n");
- return;
- }
- printf("ID HASH:\n");
- for(i=0; i < STORED_PASS_HASH; i++)
- {
- if(!ctx->logical_card_id_hash[i]) continue;
- printf("\t%d:", i);
- p = ctx->logical_card_id_hash[i];
- while(p)
- {
- printf("\t[%d] %llu", p->idx, ctx->riders[p->idx].id);
- p = p -> next;
- }
- printf("\n");
- }
- printf("RFID HASH:\n");
- for(i=0; i < STORED_PASS_HASH; i++)
- {
- if(!ctx->rider_rf_hash[i]) continue;
- printf("\t%d:", i);
- p = ctx->rider_rf_hash[i];
- while(p)
- {
- printf("\t[%d] \"%s\"", p->idx, ctx->riders[p->idx].rfid_value);
- p = p -> next;
- }
- printf("\n");
- }
- printf("MAGSTRIPE HASH:\n");
- for(i=0; i < STORED_PASS_HASH; i++)
- {
- if(!ctx->rider_mag_hash[i]) continue;
- printf("\t%d:", i);
- p = ctx->rider_mag_hash[i];
- while(p)
- {
- printf("\t[%d] \"%s\"", p->idx, ctx->riders[p->idx].magstripe_value);
- p = p -> next;
- }
- printf("\n");
- }
- };
- /*
- int main(int argc, char **argv)
- {
- passdb_context ctx = {0};
- int retval;
- rider_record foo = {12362, 6, "SILLYRF", "FOOBAR", "STUPIDRULE", "STUPIDPARAM"};
- rider_record bar = {12354, 7, "WAWAWA", "SILLYMAG", "STUPIDRULE", "STUPIDPARAM"};
- rider_record baz = {12361, 8, "", "BARFOLA_MAG", "STUPIDRULE2", "STUPIDPARAM2"};
- rider_record bat = {12363, 7, "", "", "", ""};
- retval = attach_to_passdb(&ctx);
- dump_hashes(&ctx);
- retval = update_rider(&ctx, &foo);
- retval = update_rider(&ctx, &bar);
- retval = update_rider(&ctx, &baz);
- retval = delete_rider(&ctx, &bat);
- dump_hashes(&ctx);
- return 0;
- }
- */
|