fingerdb.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. #include <dirent.h>
  2. #include <errno.h>
  3. #include <fcntl.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <sys/stat.h>
  8. #include <sys/types.h>
  9. #include <unistd.h>
  10. #include "fingerdb.h"
  11. /**************************************************
  12. * *
  13. * This file contents functions, which provide *
  14. * content storage abstraction. *
  15. * *
  16. **************************************************/
  17. #define FINGERDB_PATH_MAXLEN 512
  18. #define FINGERDB_DB_DIR "/var/db/upekux"
  19. #define FINGERDB_DIR_MASK 0700
  20. #define FINGERDB_FILE_MASK 0600
  21. /******************************
  22. fun fingerdbCreateFinger
  23. create new record in db
  24. return
  25. negative on error
  26. id of new record on succes
  27. *******************************/
  28. int fingerdbCreateFinger( void ){
  29. int res;
  30. int i;
  31. char path[FINGERDB_PATH_MAXLEN];
  32. struct stat dirstat;
  33. for( i = 1; ;i++ ){
  34. sprintf( path, "%s/%i", FINGERDB_DB_DIR, i );
  35. if( stat(path, &dirstat) ){
  36. if( errno == ENOENT ) break;
  37. perror( "fingerdbCreateFinger stat" );
  38. return -1;
  39. }
  40. }
  41. res = mkdir( path, FINGERDB_DIR_MASK );
  42. if( res ) perror( "fingerdbCreateFinger mkdir" );
  43. return res < 0 ? res : i;
  44. }
  45. /***********************************
  46. func fingerdbCheckIdExist
  47. check exist id record in db
  48. input
  49. id which need check
  50. return
  51. 1 if exist
  52. 0 if not exist
  53. ***********************************/
  54. int fingerdbCheckIdExist( int id ){
  55. struct stat dirstat;
  56. char path[FINGERDB_PATH_MAXLEN];
  57. sprintf( path, "%s/%i", FINGERDB_DB_DIR, id );
  58. if( !stat(path, &dirstat) )return 1;
  59. return 0;
  60. }
  61. /*************************************
  62. fun fingerdbSetField
  63. set new field value in db
  64. input
  65. id - id of record in db
  66. field - field id the record
  67. data - new content of field
  68. datalen - length in bytes of data
  69. return
  70. 0 on success
  71. negative on error
  72. **************************************/
  73. int fingerdbSetField( unsigned int id, const char* field, const void* data, int datalen ){
  74. int wres;
  75. int writelen = 0;
  76. int fd;
  77. char path[FINGERDB_PATH_MAXLEN];
  78. //Prevent use slashes in field name
  79. for( int i = 0; field[i]; i++ ) if( field[i] == '/' || field[i] == '\\' ){
  80. printf( "WARNING: attempt to use '%c' in field name!\n", field[i] );
  81. return -EINVAL;
  82. }
  83. sprintf( path, "%s/%u/%s", FINGERDB_DB_DIR, id, field );
  84. fd = open( path, O_CREAT | O_WRONLY | O_TRUNC, FINGERDB_FILE_MASK );
  85. if( fd < 0 ){
  86. perror( "fingerdbSetField open" );
  87. return -1;
  88. }
  89. do{
  90. wres = write( fd, data + writelen, datalen - writelen );
  91. if( wres < 0 ){
  92. perror( "fingerdbSetField write" );
  93. goto l_close;
  94. }
  95. writelen += wres;
  96. }while( writelen < datalen );
  97. l_close:
  98. close( fd );
  99. return wres < 0 ? wres : 0;
  100. }
  101. /**************************************************************
  102. func fingerdbGetField
  103. read content of field
  104. input
  105. id - if of record in db
  106. field - name of field in record
  107. buf - pointer to buffer, in which the data will be placed
  108. buflen - size of buf
  109. return
  110. negative on error
  111. 0 if field not exist or empty
  112. positive - amount of data read
  113. ***************************************************************/
  114. int fingerdbGetField( unsigned int id, const char* field, void* buf, int buflen ){
  115. int filesize;
  116. int readlen;
  117. int datalen;
  118. int needRead;
  119. char path[FINGERDB_PATH_MAXLEN];
  120. int fd;
  121. datalen = 0;
  122. if( buflen < 1 ){
  123. printf( "%s: output buffer too small\n", __FUNCTION__ );
  124. return -ENOMEM;
  125. }
  126. //Prevent use slashes in field name
  127. for( int i = 0; field[i]; i++ ) if( field[i] == '/' || field[i] == '\\' ){
  128. printf( "WARNING: attempt to use '%c' in field name!\n", field[i] );
  129. return -EINVAL;
  130. }
  131. sprintf( path, "%s/%u/%s", FINGERDB_DB_DIR, id, field );
  132. fd = open( path, O_RDONLY );
  133. if( fd < 0 ){
  134. if( errno == ENOENT ) return 0;//not error
  135. perror( "fingerdbGetField open" );
  136. return fd;
  137. }
  138. filesize = lseek( fd, 0, SEEK_END );
  139. if( filesize < 0 ){
  140. perror( "fingerdbGetField lseek" );
  141. goto l_close;
  142. }
  143. if( !filesize ) goto l_close;
  144. lseek( fd, 0, SEEK_SET );
  145. needRead = filesize >= buflen ? buflen : filesize;
  146. do{
  147. readlen = read( fd, buf + datalen, needRead - datalen );
  148. if( readlen < 0 ){
  149. perror( "fingerdbGetField read" );
  150. goto l_close;
  151. }
  152. datalen += readlen;
  153. }while( datalen < needRead );
  154. if( datalen < buflen ) memcpy( buf + datalen, "\0", 1 );
  155. l_close:
  156. close( fd );
  157. return datalen;
  158. }
  159. /**********************************************
  160. func fingerdbRemoveFinger
  161. trash all data in record and delete record
  162. input
  163. id - id of record, wich be removed
  164. return
  165. 0 on success
  166. not 0 on error
  167. ***********************************************/
  168. int fingerdbRemoveFinger( unsigned int id ){
  169. int res = 0;
  170. char path[FINGERDB_PATH_MAXLEN];
  171. DIR* fingerdir;
  172. struct dirent* diritem;
  173. sprintf( path, "%s/%u", FINGERDB_DB_DIR, id );
  174. fingerdir = opendir( path );
  175. if( !fingerdir ){
  176. perror( "fingerdbRemoveFinger opendir" );
  177. return -ENOENT;
  178. }
  179. l_read_next_diritem:
  180. diritem = readdir( fingerdir );
  181. if( diritem ){
  182. if( !strcmp(".", diritem->d_name) || !strcmp("..", diritem->d_name) ) goto l_read_next_diritem;
  183. sprintf( path, "%s/%u/%s", FINGERDB_DB_DIR, id, diritem->d_name );
  184. res = remove( path );
  185. if( res ) perror( "fingerdbRemoveFinger remove file" );
  186. else goto l_read_next_diritem;
  187. }
  188. closedir( fingerdir );
  189. if( !res ){
  190. sprintf( path, "%s/%u", FINGERDB_DB_DIR, id );
  191. res = remove( path );
  192. if( res ) perror( "fingerdbRemoveFinger remove dir" );
  193. }
  194. return res;
  195. }
  196. /**********************************
  197. func fingerdbOpen
  198. open db for operate
  199. return
  200. pointer to db
  201. NULL on error
  202. **********************************/
  203. void* fingerdbOpen( void ){
  204. return opendir( FINGERDB_DB_DIR );
  205. }
  206. /**********************************
  207. func fingerdbSerachNextId
  208. search next record id in the db
  209. input
  210. pointer to the db
  211. return
  212. 0 - error or not found
  213. not 0 - id
  214. **********************************/
  215. int fingerdbSearchNextId( void* dbp ){
  216. int id;
  217. struct dirent* de;
  218. l_read:
  219. de = readdir( dbp );
  220. if( !de ) return 0;
  221. if( sscanf(de->d_name, "%i", &id) == 1 ) return id;
  222. goto l_read;
  223. }
  224. /**********************************
  225. func fingerdbClose
  226. close db
  227. input
  228. pointer to the db to be closed
  229. **********************************/
  230. void fingerdbClose( void* dbp ){
  231. closedir( dbp );
  232. }