/*- * Copyright (c) 2006 Fredrik Lindberg. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $Id: plain.c 42 2006-02-20 14:39:13Z fli $ */ /* * Backwards compatible module. Not recommended for real-life usage. * Each record is stored in a separate file. * Does not support multiple records. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void * plain_open(const char *, int, char *[]); static void plain_close(void *); static struct birdb_rec ** plain_get(void *, struct birdb_rec *); static void plain_freegetres(void *, struct birdb_rec **); static int plain_ins(void *, struct birdb_rec *); static int plain_del(void *, struct birdb_rec *); static struct birdb_rec * plain_seq_getfirst(void *); static struct birdb_rec * plain_seq_getnext(void *, struct birdb_rec *); static void plain_seq_free(void *handle, struct birdb_rec *); /* Backend module glue */ BIRDB_BACKEND_PARAMS = { "plain", "Plain text file", plain_open, plain_close, plain_get, plain_freegetres, plain_ins, plain_del, plain_seq_getfirst, plain_seq_getnext, plain_seq_free, }; #define PLAIN_DEFPATH "/var/db/bioapi/bir" /* * Open and initialization routine * Arguments * bspid - BSP uuid * argc - Number of arguments * argv - Argument array * * Returns a full path on success, otherwise NULL. */ static void * plain_open(const char *bspid, int argc, char *argv[]) { struct stat sb; char *path, *rpath; if (bspid == NULL) { warnx("Missing BSP ID"); return (NULL); } path = (argc < 1) ? PLAIN_DEFPATH : argv[0]; if (stat(path, &sb) != 0) { if (errno == ENOENT) { if (mkdir(path, S_IRWXU) != 0) { warn("Unable to create %s", path); goto error; } } else { warn("Unable to access %s", path); goto error; } } asprintf(&rpath, "%s/%s", path, bspid); if (rpath == NULL) return (NULL); if (stat(rpath, &sb) != 0) { if (errno == ENOENT) { if (mkdir(rpath, S_IRWXU) != 0) { warn("Unable to create %s", rpath); goto error; } } else { warn("Unable to access %s", rpath); goto error; } } return (rpath); error: return (NULL); } /* * Close routine, just free memory */ static void plain_close(void *handle) { char *path = handle; free(path); } /* * Get a record * Arguments * handle - base path * br - BIRdb record (only br_key) * * Returns an array of birdb records that matches the given key. * This array must be freed with freegetres() */ static struct birdb_rec ** plain_get(void *handle, struct birdb_rec *br) { char *path = handle; char fullpath[FILENAME_MAX + 1]; struct birdb_rec **recarray = NULL; struct birdb_rec *rec; struct stat sb; int fd, nbytes; snprintf(fullpath, FILENAME_MAX, "%s/%s.bir", path, br->br_key); fd = open(fullpath, O_RDONLY | O_EXLOCK); if (fd < 0) return (NULL); recarray = malloc(sizeof(struct birdb_rec *) * 2); rec = recarray[0] = malloc(sizeof(struct birdb_rec)); rec->br_bir = malloc(sizeof(BioAPI_BIR)); if (rec->br_bir == NULL) goto fail; read(fd, &rec->br_bir->Header, sizeof(BioAPI_BIR_HEADER)); nbytes = (rec->br_bir->Header.Length) - sizeof(BioAPI_BIR_HEADER); rec->br_bir->BiometricData = malloc(nbytes); if (rec->br_bir->BiometricData == NULL) { free(rec->br_bir); goto fail; } read(fd, rec->br_bir->BiometricData, nbytes); if (read(fd, &nbytes, 4) > 0) { rec->br_bir->Signature = malloc(sizeof (BioAPI_DATA)); if (rec->br_bir->Signature == NULL) return (NULL); rec->br_bir->Signature->Length = nbytes; rec->br_bir->Signature->Data = malloc((nbytes)); if (rec->br_bir->Signature->Data == NULL) return (NULL); read(fd, rec->br_bir->Signature->Data, (nbytes)); } else { rec->br_bir->Signature = NULL; } close(fd); rec->br_key = strdup(br->br_key); if (stat(fullpath, &sb) != 0) rec->br_ctime = sb.st_birthtime; else rec->br_ctime = time(NULL); recarray[1] = NULL; return (recarray); fail: return (NULL); } /* * Free results returned by fdb_get() * Arguments * handle - base path * recarray - result array returned by plain_get */ static void plain_freegetres(void *handle, struct birdb_rec **recarray) { int idx = 0; if (recarray == NULL) return; while (recarray[idx] != NULL) { free(recarray[idx++]); } free(recarray); } /* * Creates a new bir file * Arguments * handle - base path * br - the birdb record to be inserted * * Returns 0 on success, non-zero on failure. */ static int plain_ins(void *handle, struct birdb_rec *br) { char *path = handle; char fullpath[FILENAME_MAX + 1]; BioAPI_BIR *bir = br->br_bir; int fd; snprintf(fullpath, FILENAME_MAX, "%s/%s.bir", path, br->br_key); fd = open(fullpath, O_WRONLY | O_CREAT | O_TRUNC | O_EXLOCK, S_IRWXU); if (fd < 0) return (-1); /* Write header */ write(fd, &bir->Header, sizeof(BioAPI_BIR_HEADER)); /* Write biometric data */ write(fd, bir->BiometricData, (bir->Header.Length) - sizeof(BioAPI_BIR_HEADER)); /* Write signature if present */ if (bir->Signature) { write(fd, &bir->Signature->Length, 4); write(fd, bir->Signature->Data, (bir->Header.Length)); } close(fd); return (0); } /* * Remove a record * Arguments * handle - base path * br - the birdb record to be removed * * Returns 0 on success, non-zero on failure. */ static int plain_del(void *handle, struct birdb_rec *br) { char *path = handle; char fullpath[FILENAME_MAX + 1]; snprintf(fullpath, FILENAME_MAX, "%s/%s.bir", path, br->br_key); return (unlink(fullpath)); } /* * Get the first record * Arguments * handle - base path * br - the birdb record to be removed * * Returns the first record if any, NULL otherwise */ static struct birdb_rec * plain_seq_getfirst(void *handle) { char *path = handle; char fullpath[FILENAME_MAX + 1]; struct birdb_rec *rec; struct dirent *dp; struct stat sb; DIR *dir; int fd, nbytes; dir = opendir(path); while ((dp = readdir(dir)) != NULL) { if (strstr(dp->d_name, ".bir") != NULL) break; } if (dp == NULL) return (NULL); snprintf(fullpath, FILENAME_MAX, "%s/%s", path, dp->d_name); fd = open(fullpath, O_RDONLY | O_EXLOCK); if (fd < 0) return (NULL); rec = malloc(sizeof(struct birdb_rec *) * 2); if (rec == NULL) return (NULL); rec->br_bir = malloc(sizeof(BioAPI_BIR)); if (rec->br_bir == NULL) return (NULL); read(fd, &rec->br_bir->Header, sizeof(BioAPI_BIR_HEADER)); nbytes = (rec->br_bir->Header.Length) - sizeof(BioAPI_BIR_HEADER); rec->br_bir->BiometricData = malloc(nbytes); if (rec->br_bir->BiometricData == NULL) { free(rec->br_bir); return (NULL); } read(fd, rec->br_bir->BiometricData, nbytes); if (read(fd, &nbytes, 4) > 0) { rec->br_bir->Signature = malloc(sizeof (BioAPI_DATA)); if (rec->br_bir->Signature == NULL) return (NULL); rec->br_bir->Signature->Length = nbytes; rec->br_bir->Signature->Data = malloc((nbytes)); if (rec->br_bir->Signature->Data == NULL) return (NULL); read(fd, rec->br_bir->Signature->Data, (nbytes)); } else { rec->br_bir->Signature = NULL; } close(fd); rec->br_key = strdup(dp->d_name); *(rec->br_key + dp->d_namlen - 4) = '\0'; closedir(dir); if (stat(fullpath, &sb) != 0) rec->br_ctime = sb.st_birthtime; else rec->br_ctime = time(NULL); return (rec); } /* * Get the next logical record * Arguments * handle - base path * prev - previous record from getnext or getfirst * * Returns the next record if any, NULL otherwise * Resources allocated for the previous record will be freed. */ static struct birdb_rec * plain_seq_getnext(void *handle, struct birdb_rec *prev) { char *path = handle, *p; char fullpath[FILENAME_MAX + 1]; struct birdb_rec *rec; struct dirent *dp; struct stat sb; DIR *dir; int fd, nbytes; dir = opendir(path); while ((dp = readdir(dir)) != NULL) { if (strstr(dp->d_name, ".bir") != NULL) { p = strdup(dp->d_name); *(p + dp->d_namlen - 4) = '\0'; if (strcmp(p, prev->br_key) == 0) { dp = readdir(dir); free(p); break; } free(p); } } plain_seq_free(handle, prev); if (dp == NULL) return (NULL); snprintf(fullpath, FILENAME_MAX, "%s/%s", path, dp->d_name); fd = open(fullpath, O_RDONLY | O_EXLOCK); if (fd < 0) return (NULL); rec = malloc(sizeof(struct birdb_rec *) * 2); if (rec == NULL) return (NULL); rec->br_bir = malloc(sizeof(BioAPI_BIR)); if (rec->br_bir == NULL) return (NULL); read(fd, &rec->br_bir->Header, sizeof(BioAPI_BIR_HEADER)); nbytes = (rec->br_bir->Header.Length) - sizeof(BioAPI_BIR_HEADER); rec->br_bir->BiometricData = malloc(nbytes); if (rec->br_bir->BiometricData == NULL) { free(rec->br_bir); return (NULL); } read(fd, rec->br_bir->BiometricData, nbytes); if (read(fd, &nbytes, 4) > 0) { rec->br_bir->Signature = malloc(sizeof (BioAPI_DATA)); if (rec->br_bir->Signature == NULL) return (NULL); rec->br_bir->Signature->Length = nbytes; rec->br_bir->Signature->Data = malloc((nbytes)); if (rec->br_bir->Signature->Data == NULL) return (NULL); read(fd, rec->br_bir->Signature->Data, (nbytes)); } else { rec->br_bir->Signature = NULL; } close(fd); rec->br_key = strdup(dp->d_name); *(rec->br_key + dp->d_namlen - 4) = '\0'; closedir(dir); if (stat(fullpath, &sb) != 0) rec->br_ctime = sb.st_birthtime; else rec->br_ctime = time(NULL); return (rec); } /* * Free the remains of an sequential traversial * Arguments * handle - base path * last - previous record from getnext or getfirst * * This is not needed if getnext returns NULL */ static void plain_seq_free(void *handle, struct birdb_rec *last) { birdb_freerec(last); }