123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281 |
- #include <dirent.h>
- #include <errno.h>
- #include <fcntl.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/stat.h>
- #include <sys/types.h>
- #include <unistd.h>
- #include "fingerdb.h"
- /**************************************************
- * *
- * This file contents functions, which provide *
- * content storage abstraction. *
- * *
- **************************************************/
- #define FINGERDB_PATH_MAXLEN 512
- #define FINGERDB_DB_DIR "/var/db/upekux"
- #define FINGERDB_DIR_MASK 0700
- #define FINGERDB_FILE_MASK 0600
- /******************************
- fun fingerdbCreateFinger
- create new record in db
- return
- negative on error
- id of new record on succes
- *******************************/
- int fingerdbCreateFinger( void ){
-
- int res;
- int i;
- char path[FINGERDB_PATH_MAXLEN];
- struct stat dirstat;
-
- for( i = 1; ;i++ ){
- sprintf( path, "%s/%i", FINGERDB_DB_DIR, i );
- if( stat(path, &dirstat) ){
- if( errno == ENOENT ) break;
- perror( "fingerdbCreateFinger stat" );
- return -1;
- }
- }
-
- res = mkdir( path, FINGERDB_DIR_MASK );
- if( res ) perror( "fingerdbCreateFinger mkdir" );
-
- return res < 0 ? res : i;
- }
- /***********************************
- func fingerdbCheckIdExist
- check exist id record in db
- input
- id which need check
- return
- 1 if exist
- 0 if not exist
- ***********************************/
- int fingerdbCheckIdExist( int id ){
-
- struct stat dirstat;
- char path[FINGERDB_PATH_MAXLEN];
-
- sprintf( path, "%s/%i", FINGERDB_DB_DIR, id );
-
- if( !stat(path, &dirstat) )return 1;
- return 0;
- }
- /*************************************
- fun fingerdbSetField
- set new field value in db
- input
- id - id of record in db
- field - field id the record
- data - new content of field
- datalen - length in bytes of data
- return
- 0 on success
- negative on error
- **************************************/
- int fingerdbSetField( unsigned int id, const char* field, const void* data, int datalen ){
-
- int wres;
- int writelen = 0;
- int fd;
- char path[FINGERDB_PATH_MAXLEN];
-
- //Prevent use slashes in field name
- for( int i = 0; field[i]; i++ ) if( field[i] == '/' || field[i] == '\\' ){
- printf( "WARNING: attempt to use '%c' in field name!\n", field[i] );
- return -EINVAL;
- }
-
- sprintf( path, "%s/%u/%s", FINGERDB_DB_DIR, id, field );
- fd = open( path, O_CREAT | O_WRONLY | O_TRUNC, FINGERDB_FILE_MASK );
- if( fd < 0 ){
- perror( "fingerdbSetField open" );
- return -1;
- }
-
- do{
- wres = write( fd, data + writelen, datalen - writelen );
- if( wres < 0 ){
- perror( "fingerdbSetField write" );
- goto l_close;
- }
- writelen += wres;
- }while( writelen < datalen );
-
- l_close:
- close( fd );
- return wres < 0 ? wres : 0;
- }
- /**************************************************************
- func fingerdbGetField
- read content of field
- input
- id - if of record in db
- field - name of field in record
- buf - pointer to buffer, in which the data will be placed
- buflen - size of buf
- return
- negative on error
- 0 if field not exist or empty
- positive - amount of data read
- ***************************************************************/
- int fingerdbGetField( unsigned int id, const char* field, void* buf, int buflen ){
-
- int filesize;
- int readlen;
- int datalen;
- int needRead;
- char path[FINGERDB_PATH_MAXLEN];
- int fd;
-
- datalen = 0;
-
- if( buflen < 1 ){
- printf( "%s: output buffer too small\n", __FUNCTION__ );
- return -ENOMEM;
- }
-
- //Prevent use slashes in field name
- for( int i = 0; field[i]; i++ ) if( field[i] == '/' || field[i] == '\\' ){
- printf( "WARNING: attempt to use '%c' in field name!\n", field[i] );
- return -EINVAL;
- }
-
- sprintf( path, "%s/%u/%s", FINGERDB_DB_DIR, id, field );
- fd = open( path, O_RDONLY );
- if( fd < 0 ){
- if( errno == ENOENT ) return 0;//not error
- perror( "fingerdbGetField open" );
- return fd;
- }
-
- filesize = lseek( fd, 0, SEEK_END );
- if( filesize < 0 ){
- perror( "fingerdbGetField lseek" );
- goto l_close;
- }
- if( !filesize ) goto l_close;
- lseek( fd, 0, SEEK_SET );
-
- needRead = filesize >= buflen ? buflen : filesize;
-
- do{
- readlen = read( fd, buf + datalen, needRead - datalen );
- if( readlen < 0 ){
- perror( "fingerdbGetField read" );
- goto l_close;
- }
- datalen += readlen;
- }while( datalen < needRead );
-
- if( datalen < buflen ) memcpy( buf + datalen, "\0", 1 );
-
- l_close:
- close( fd );
- return datalen;
- }
- /**********************************************
- func fingerdbRemoveFinger
- trash all data in record and delete record
- input
- id - id of record, wich be removed
- return
- 0 on success
- not 0 on error
- ***********************************************/
- int fingerdbRemoveFinger( unsigned int id ){
-
- int res = 0;
- char path[FINGERDB_PATH_MAXLEN];
- DIR* fingerdir;
- struct dirent* diritem;
-
- sprintf( path, "%s/%u", FINGERDB_DB_DIR, id );
- fingerdir = opendir( path );
- if( !fingerdir ){
- perror( "fingerdbRemoveFinger opendir" );
- return -ENOENT;
- }
-
- l_read_next_diritem:
- diritem = readdir( fingerdir );
- if( diritem ){
-
- if( !strcmp(".", diritem->d_name) || !strcmp("..", diritem->d_name) ) goto l_read_next_diritem;
-
- sprintf( path, "%s/%u/%s", FINGERDB_DB_DIR, id, diritem->d_name );
- res = remove( path );
- if( res ) perror( "fingerdbRemoveFinger remove file" );
- else goto l_read_next_diritem;
- }
-
- closedir( fingerdir );
-
- if( !res ){
-
- sprintf( path, "%s/%u", FINGERDB_DB_DIR, id );
- res = remove( path );
- if( res ) perror( "fingerdbRemoveFinger remove dir" );
- }
-
- return res;
- }
- /**********************************
- func fingerdbOpen
- open db for operate
- return
- pointer to db
- NULL on error
- **********************************/
- void* fingerdbOpen( void ){
- return opendir( FINGERDB_DB_DIR );
- }
- /**********************************
- func fingerdbSerachNextId
- search next record id in the db
- input
- pointer to the db
- return
- 0 - error or not found
- not 0 - id
- **********************************/
- int fingerdbSearchNextId( void* dbp ){
-
- int id;
- struct dirent* de;
-
- l_read:
- de = readdir( dbp );
- if( !de ) return 0;
-
- if( sscanf(de->d_name, "%i", &id) == 1 ) return id;
-
- goto l_read;
- }
- /**********************************
- func fingerdbClose
- close db
- input
- pointer to the db to be closed
- **********************************/
- void fingerdbClose( void* dbp ){
- closedir( dbp );
- }
|