smdb2.c
上传用户:xu_441
上传日期:2007-01-04
资源大小:1640k
文件大小:13k
源码类别:

Email客户端

开发平台:

Unix_Linux

  1. /*
  2. ** Copyright (c) 1999 Sendmail, Inc. and its suppliers.
  3. ** All rights reserved.
  4. **
  5. ** By using this file, you agree to the terms and conditions set
  6. ** forth in the LICENSE file which can be found at the top level of
  7. ** the sendmail distribution.
  8. */
  9. #ifndef lint
  10. static char id[] = "@(#)$Id: smdb2.c,v 8.48 1999/11/23 08:42:54 gshapiro Exp $";
  11. #endif /* ! lint */
  12. #include <fcntl.h>
  13. #include <stdlib.h>
  14. #include <unistd.h>
  15. #include <sendmail/sendmail.h>
  16. #include <libsmdb/smdb.h>
  17. #if (DB_VERSION_MAJOR >= 2)
  18. # define SMDB2_FILE_EXTENSION "db"
  19. struct smdb_db2_database
  20. {
  21. DB *smdb2_db;
  22. int smdb2_lock_fd;
  23. };
  24. typedef struct smdb_db2_database SMDB_DB2_DATABASE;
  25. /*
  26. **  SMDB_TYPE_TO_DB2_TYPE -- Translates smdb database type to db2 type.
  27. **
  28. ** Parameters:
  29. ** type -- The type to translate.
  30. **
  31. ** Returns:
  32. ** The DB2 type that corresponsds to the passed in SMDB type.
  33. ** Returns -1 if there is no equivalent type.
  34. **
  35. */
  36. DBTYPE
  37. smdb_type_to_db2_type(type)
  38. SMDB_DBTYPE type;
  39. {
  40. if (type == SMDB_TYPE_DEFAULT)
  41. return DB_HASH;
  42. if (strncmp(type, SMDB_TYPE_HASH, SMDB_TYPE_HASH_LEN) == 0)
  43. return DB_HASH;
  44. if (strncmp(type, SMDB_TYPE_BTREE, SMDB_TYPE_BTREE_LEN) == 0)
  45. return DB_BTREE;
  46. return DB_UNKNOWN;
  47. }
  48. /*
  49. **  DB2_ERROR_TO_SMDB -- Translates db2 errors to smdbe errors
  50. **
  51. ** Parameters:
  52. ** error -- The error to translate.
  53. **
  54. ** Returns:
  55. ** The SMDBE error corresponding to the db2 error.
  56. ** If we don't have a corresponding error, it returs errno.
  57. **
  58. */
  59. int
  60. db2_error_to_smdb(error)
  61. int error;
  62. {
  63. int result;
  64. switch (error)
  65. {
  66. # ifdef DB_INCOMPLETE
  67. case DB_INCOMPLETE:
  68. result = SMDBE_INCOMPLETE;
  69. break;
  70. # endif /* DB_INCOMPLETE */
  71. # ifdef DB_NOTFOUND
  72. case DB_NOTFOUND:
  73. result = SMDBE_NOT_FOUND;
  74. break;
  75. # endif /* DB_NOTFOUND */
  76. # ifdef DB_KEYEMPTY
  77. case DB_KEYEMPTY:
  78. result = SMDBE_KEY_EMPTY;
  79. break;
  80. # endif /* DB_KEYEMPTY */
  81. # ifdef DB_KEYEXIST
  82. case DB_KEYEXIST:
  83. result = SMDBE_KEY_EXIST;
  84. break;
  85. # endif /* DB_KEYEXIST */
  86. # ifdef DB_LOCK_DEADLOCK
  87. case DB_LOCK_DEADLOCK:
  88. result = SMDBE_LOCK_DEADLOCK;
  89. break;
  90. # endif /* DB_LOCK_DEADLOCK */
  91. # ifdef DB_LOCK_NOTGRANTED
  92. case DB_LOCK_NOTGRANTED:
  93. result = SMDBE_LOCK_NOT_GRANTED;
  94. break;
  95. # endif /* DB_LOCK_NOTGRANTED */
  96. # ifdef DB_LOCK_NOTHELD
  97. case DB_LOCK_NOTHELD:
  98. result = SMDBE_LOCK_NOT_HELD;
  99. break;
  100. # endif /* DB_LOCK_NOTHELD */
  101. # ifdef DB_RUNRECOVERY
  102. case DB_RUNRECOVERY:
  103. result = SMDBE_RUN_RECOVERY;
  104. break;
  105. # endif /* DB_RUNRECOVERY */
  106. # ifdef DB_OLD_VERSION
  107. case DB_OLD_VERSION:
  108. result = SMDBE_OLD_VERSION;
  109. break;
  110. # endif /* DB_OLD_VERSION */
  111. case 0:
  112. result = SMDBE_OK;
  113. break;
  114. default:
  115. result = errno;
  116. }
  117. return result;
  118. }
  119. /*
  120. **  SMDB_PUT_FLAGS_TO_DB2_FLAGS -- Translates smdb put flags to db2 put flags.
  121. **
  122. ** Parameters:
  123. ** flags -- The flags to translate.
  124. **
  125. ** Returns:
  126. ** The db2 flags that are equivalent to the smdb flags.
  127. **
  128. ** Notes:
  129. ** Any invalid flags are ignored.
  130. **
  131. */
  132. u_int
  133. smdb_put_flags_to_db2_flags(flags)
  134. SMDB_FLAG flags;
  135. {
  136. int return_flags;
  137. return_flags = 0;
  138. if (bitset(SMDBF_NO_OVERWRITE, flags))
  139. return_flags |= DB_NOOVERWRITE;
  140. return return_flags;
  141. }
  142. /*
  143. **  SMDB_CURSOR_GET_FLAGS_TO_DB2 -- Translates smdb cursor get flags to db2
  144. ** getflags.
  145. **
  146. ** Parameters:
  147. ** flags -- The flags to translate.
  148. **
  149. ** Returns:
  150. ** The db2 flags that are equivalent to the smdb flags.
  151. **
  152. ** Notes:
  153. ** -1 is returned if flag is unknown.
  154. **
  155. */
  156. int
  157. smdb_cursor_get_flags_to_db2(flags)
  158. SMDB_FLAG flags;
  159. {
  160. switch (flags)
  161. {
  162. case SMDB_CURSOR_GET_FIRST:
  163. return DB_FIRST;
  164. case SMDB_CURSOR_GET_LAST:
  165. return DB_LAST;
  166. case SMDB_CURSOR_GET_NEXT:
  167. return DB_NEXT;
  168. default:
  169. return -1;
  170. }
  171. }
  172. SMDB_DB2_DATABASE *
  173. smdb2_malloc_database()
  174. {
  175. SMDB_DB2_DATABASE *db2;
  176. db2 = (SMDB_DB2_DATABASE *) malloc(sizeof(SMDB_DB2_DATABASE));
  177. if (db2 != NULL)
  178. db2->smdb2_lock_fd = -1;
  179. return db2;
  180. }
  181. /*
  182. ** Except for smdb_db_open, the rest of these function correspond to the
  183. ** interface laid out in smdb.h.
  184. */
  185. int
  186. smdb2_close(database)
  187. SMDB_DATABASE *database;
  188. {
  189. SMDB_DB2_DATABASE *db2 = (SMDB_DB2_DATABASE *) database->smdb_impl;
  190. DB *db = ((SMDB_DB2_DATABASE *) database->smdb_impl)->smdb2_db;
  191. if (db2->smdb2_lock_fd != -1)
  192. close(db2->smdb2_lock_fd);
  193. free(db2);
  194. database->smdb_impl = NULL;
  195. return db2_error_to_smdb(db->close(db, 0));
  196. }
  197. int
  198. smdb2_del(database, key, flags)
  199. SMDB_DATABASE *database;
  200. SMDB_DBENT *key;
  201. u_int flags;
  202. {
  203. DB *db = ((SMDB_DB2_DATABASE *) database->smdb_impl)->smdb2_db;
  204. return db2_error_to_smdb(db->del(db, NULL, &key->db, flags));
  205. }
  206. int
  207. smdb2_fd(database, fd)
  208. SMDB_DATABASE *database;
  209. int *fd;
  210. {
  211. DB *db = ((SMDB_DB2_DATABASE *) database->smdb_impl)->smdb2_db;
  212. return db2_error_to_smdb(db->fd(db, fd));
  213. }
  214. int
  215. smdb2_get(database, key, data, flags)
  216. SMDB_DATABASE *database;
  217. SMDB_DBENT *key;
  218. SMDB_DBENT *data;
  219. u_int flags;
  220. {
  221. DB *db = ((SMDB_DB2_DATABASE *) database->smdb_impl)->smdb2_db;
  222. return db2_error_to_smdb(db->get(db, NULL, &key->db, &data->db, flags));
  223. }
  224. int
  225. smdb2_put(database, key, data, flags)
  226. SMDB_DATABASE *database;
  227. SMDB_DBENT *key;
  228. SMDB_DBENT *data;
  229. u_int flags;
  230. {
  231. DB *db = ((SMDB_DB2_DATABASE *) database->smdb_impl)->smdb2_db;
  232. return db2_error_to_smdb(db->put(db, NULL, &key->db, &data->db,
  233.  smdb_put_flags_to_db2_flags(flags)));
  234. }
  235. int
  236. smdb2_set_owner(database, uid, gid)
  237. SMDB_DATABASE *database;
  238. uid_t uid;
  239. gid_t gid;
  240. {
  241. # if HASFCHOWN
  242. int fd;
  243. int result;
  244. DB *db = ((SMDB_DB2_DATABASE *) database->smdb_impl)->smdb2_db;
  245. result = db->fd(db, &fd);
  246. if (result != 0)
  247. return result;
  248. result = fchown(fd, uid, gid);
  249. if (result < 0)
  250. return errno;
  251. # endif /* HASFCHOWN */
  252. return SMDBE_OK;
  253. }
  254. int
  255. smdb2_sync(database, flags)
  256. SMDB_DATABASE *database;
  257. u_int flags;
  258. {
  259. DB *db = ((SMDB_DB2_DATABASE *) database->smdb_impl)->smdb2_db;
  260. return db2_error_to_smdb(db->sync(db, flags));
  261. }
  262. int
  263. smdb2_cursor_close(cursor)
  264. SMDB_CURSOR *cursor;
  265. {
  266. DBC *dbc = (DBC *) cursor->smdbc_impl;
  267. return db2_error_to_smdb(dbc->c_close(dbc));
  268. }
  269. int
  270. smdb2_cursor_del(cursor, flags)
  271. SMDB_CURSOR *cursor;
  272. SMDB_FLAG flags;
  273. {
  274. DBC *dbc = (DBC *) cursor->smdbc_impl;
  275. return db2_error_to_smdb(dbc->c_del(dbc, 0));
  276. }
  277. int
  278. smdb2_cursor_get(cursor, key, value, flags)
  279. SMDB_CURSOR *cursor;
  280. SMDB_DBENT *key;
  281. SMDB_DBENT *value;
  282. SMDB_FLAG flags;
  283. {
  284. int db2_flags;
  285. int result;
  286. DBC *dbc = (DBC *) cursor->smdbc_impl;
  287. db2_flags = smdb_cursor_get_flags_to_db2(flags);
  288. result = dbc->c_get(dbc, &key->db, &value->db, db2_flags);
  289. if (result == DB_NOTFOUND)
  290. return SMDBE_LAST_ENTRY;
  291. return db2_error_to_smdb(result);
  292. }
  293. int
  294. smdb2_cursor_put(cursor, key, value, flags)
  295. SMDB_CURSOR *cursor;
  296. SMDB_DBENT *key;
  297. SMDB_DBENT *value;
  298. SMDB_FLAG flags;
  299. {
  300. DBC *dbc = (DBC *) cursor->smdbc_impl;
  301. return db2_error_to_smdb(dbc->c_put(dbc, &key->db, &value->db, 0));
  302. }
  303. int
  304. smdb2_cursor(database, cursor, flags)
  305. SMDB_DATABASE *database;
  306. SMDB_CURSOR **cursor;
  307. SMDB_FLAG flags;
  308. {
  309. int result;
  310. DB *db = ((SMDB_DB2_DATABASE *) database->smdb_impl)->smdb2_db;
  311. DBC *db2_cursor;
  312. # if DB_VERSION_MAJOR > 2 || DB_VERSION_MINOR >= 6
  313. result = db->cursor(db, NULL, &db2_cursor, 0);
  314. # else /* DB_VERSION_MAJOR > 2 || DB_VERSION_MINOR >= 6 */
  315. result = db->cursor(db, NULL, &db2_cursor);
  316. # endif /* DB_VERSION_MAJOR > 2 || DB_VERSION_MINOR >= 6 */
  317. if (result != 0)
  318. return db2_error_to_smdb(result);
  319. *cursor = (SMDB_CURSOR *) malloc(sizeof(SMDB_CURSOR));
  320. if (*cursor == NULL)
  321. return SMDBE_MALLOC;
  322. (*cursor)->smdbc_close = smdb2_cursor_close;
  323. (*cursor)->smdbc_del = smdb2_cursor_del;
  324. (*cursor)->smdbc_get = smdb2_cursor_get;
  325. (*cursor)->smdbc_put = smdb2_cursor_put;
  326. (*cursor)->smdbc_impl = db2_cursor;
  327. return SMDBE_OK;
  328. }
  329. # if DB_VERSION_MAJOR == 2
  330. static int
  331. smdb_db_open_internal(db_name, db_type, db_flags, db_params, db)
  332. char *db_name;
  333. DBTYPE db_type;
  334. int db_flags;
  335. SMDB_DBPARAMS *db_params;
  336. DB **db;
  337. {
  338. void *params;
  339. DB_INFO db_info;
  340. params = NULL;
  341. memset(&db_info, '', sizeof db_info);
  342. if (db_params != NULL)
  343. {
  344. db_info.db_cachesize = db_params->smdbp_cache_size;
  345. if (db_type == DB_HASH)
  346. db_info.h_nelem = db_params->smdbp_num_elements;
  347. if (db_params->smdbp_allow_dup)
  348. db_info.flags |= DB_DUP;
  349. params = &db_info;
  350. }
  351. return db_open(db_name, db_type, db_flags, 0644, NULL, params, db);
  352. }
  353. # endif /* DB_VERSION_MAJOR == 2 */
  354. # if DB_VERSION_MAJOR > 2
  355. static int
  356. smdb_db_open_internal(db_name, db_type, db_flags, db_params, db)
  357. char *db_name;
  358. DBTYPE db_type;
  359. int db_flags;
  360. SMDB_DBPARAMS *db_params;
  361. DB **db;
  362. {
  363. int result;
  364. result = db_create(db, NULL, 0);
  365. if (result != 0 || *db == NULL)
  366. return result;
  367. if (db_params != NULL)
  368. {
  369. result = (*db)->set_cachesize(*db, 0,
  370.       db_params->smdbp_cache_size, 0);
  371. if (result != 0)
  372. {
  373. (void) (*db)->close((*db), 0);
  374. *db = NULL;
  375. return db2_error_to_smdb(result);
  376. }
  377. if (db_type == DB_HASH)
  378. {
  379. result = (*db)->set_h_nelem(*db, db_params->smdbp_num_elements);
  380. if (result != 0)
  381. {
  382. (void) (*db)->close(*db, 0);
  383. *db = NULL;
  384. return db2_error_to_smdb(result);
  385. }
  386. }
  387. if (db_params->smdbp_allow_dup)
  388. {
  389. result = (*db)->set_flags(*db, DB_DUP);
  390. if (result != 0)
  391. {
  392. (void) (*db)->close(*db, 0);
  393. *db = NULL;
  394. return db2_error_to_smdb(result);
  395. }
  396. }
  397. }
  398. result = (*db)->open(*db, db_name, NULL, db_type, db_flags, 0644);
  399. if (result != 0)
  400. {
  401. (void) (*db)->close(*db, 0);
  402. *db = NULL;
  403. }
  404. return db2_error_to_smdb(result);
  405. }
  406. # endif /* DB_VERSION_MAJOR > 2 */
  407. /*
  408. **  SMDB_DB_OPEN -- Opens a db database.
  409. **
  410. ** Parameters:
  411. ** database -- An unallocated database pointer to a pointer.
  412. ** db_name -- The name of the database without extension.
  413. ** mode -- File permisions for a created database.
  414. ** mode_mask -- Mode bits that must match on an opened database.
  415. ** sff -- Flags for safefile.
  416. ** type -- The type of database to open
  417. ** See smdb_type_to_db2_type for valid types.
  418. ** user_info -- User information for file permissions.
  419. ** db_params --
  420. ** An SMDB_DBPARAMS struct including params. These
  421. ** are processed according to the type of the
  422. ** database. Currently supported params (only for
  423. ** HASH type) are:
  424. **    num_elements
  425. **    cache_size
  426. **
  427. ** Returns:
  428. ** SMDBE_OK -- Success, other errno:
  429. ** SMDBE_MALLOC -- Cannot allocate memory.
  430. ** SMDBE_BAD_OPEN -- db_open didn't return an error, but
  431. **  somehow the DB pointer is NULL.
  432. ** Anything else: translated error from db2
  433. */
  434. int
  435. smdb_db_open(database, db_name, mode, mode_mask, sff, type, user_info, db_params)
  436. SMDB_DATABASE **database;
  437. char *db_name;
  438. int mode;
  439. int mode_mask;
  440. int sff;
  441. SMDB_DBTYPE type;
  442. SMDB_USER_INFO *user_info;
  443. SMDB_DBPARAMS *db_params;
  444. {
  445. int result;
  446. int db_flags;
  447. int lock_fd;
  448. int db_fd;
  449. SMDB_DATABASE *smdb_db;
  450. SMDB_DB2_DATABASE *db2;
  451. DB *db;
  452. DBTYPE db_type;
  453. struct stat stat_info;
  454. char db_file_name[SMDB_MAX_NAME_LEN];
  455. *database = NULL;
  456. result = smdb_add_extension(db_file_name, SMDB_MAX_NAME_LEN,
  457.     db_name, SMDB2_FILE_EXTENSION);
  458. if (result != SMDBE_OK)
  459. return result;
  460. result = smdb_setup_file(db_name, SMDB2_FILE_EXTENSION,
  461.  mode_mask, sff, user_info, &stat_info);
  462. if (result != SMDBE_OK)
  463. return result;
  464. lock_fd = -1;
  465. result = smdb_lock_file(&lock_fd, db_name, mode, sff,
  466. SMDB2_FILE_EXTENSION);
  467. if (result != SMDBE_OK)
  468. return result;
  469. smdb_db = smdb_malloc_database();
  470. if (smdb_db == NULL)
  471. return SMDBE_MALLOC;
  472. db2 = smdb2_malloc_database();
  473. if (db2 == NULL)
  474. return SMDBE_MALLOC;
  475. db2->smdb2_lock_fd = lock_fd;
  476. db_type = smdb_type_to_db2_type(type);
  477. db = NULL;
  478. db_flags = 0;
  479. if (O_CREAT & mode)
  480. db_flags |= DB_CREATE;
  481. if (O_TRUNC & mode)
  482. db_flags |= DB_TRUNCATE;
  483. if (O_RDONLY == mode)
  484. db_flags |= DB_RDONLY;
  485. # if !HASFLOCK && defined(DB_FCNTL_LOCKING)
  486. db_flags |= DB_FCNTL_LOCKING;
  487. # endif /* !HASFLOCK && defined(DB_FCNTL_LOCKING) */
  488. result = smdb_db_open_internal(db_file_name, db_type,
  489.        db_flags, db_params, &db);
  490. if (result == 0 && db != NULL)
  491. {
  492. result = db->fd(db, &db_fd);
  493. if (result == 0)
  494. result = SMDBE_OK;
  495. }
  496. else
  497. {
  498. /* Try and narrow down on the problem */
  499. if (result != 0)
  500. result = db2_error_to_smdb(result);
  501. else
  502. result = SMDBE_BAD_OPEN;
  503. }
  504. if (result == SMDBE_OK)
  505. result = smdb_filechanged(db_name, SMDB2_FILE_EXTENSION, db_fd,
  506.   &stat_info);
  507. if (result == SMDBE_OK)
  508. {
  509. /* Everything is ok. Setup driver */
  510. db2->smdb2_db = db;
  511. smdb_db->smdb_close = smdb2_close;
  512. smdb_db->smdb_del = smdb2_del;
  513. smdb_db->smdb_fd = smdb2_fd;
  514. smdb_db->smdb_get = smdb2_get;
  515. smdb_db->smdb_put = smdb2_put;
  516. smdb_db->smdb_set_owner = smdb2_set_owner;
  517. smdb_db->smdb_sync = smdb2_sync;
  518. smdb_db->smdb_cursor = smdb2_cursor;
  519. smdb_db->smdb_impl = db2;
  520. *database = smdb_db;
  521. return SMDBE_OK;
  522. }
  523. if (db != NULL)
  524. db->close(db, 0);
  525. smdb_unlock_file(db2->smdb2_lock_fd);
  526. free(db2);
  527. smdb_free_database(smdb_db);
  528. return result;
  529. }
  530. #endif /* (DB_VERSION_MAJOR >= 2) */