/usr/src/cmd/sendmail/db/db/db_iface.c

https://github.com/buffygb/illumos-gate · C · 490 lines · 303 code · 53 blank · 134 comment · 93 complexity · da9acc99bc87deda4155bbc52252fb7b MD5 · raw file

  1. /*-
  2. * See the file LICENSE for redistribution information.
  3. *
  4. * Copyright (c) 1996, 1997, 1998
  5. * Sleepycat Software. All rights reserved.
  6. */
  7. #pragma ident "%Z%%M% %I% %E% SMI"
  8. #include "config.h"
  9. #ifndef lint
  10. static const char sccsid[] = "@(#)db_iface.c 10.40 (Sleepycat) 12/19/98";
  11. #endif /* not lint */
  12. #ifndef NO_SYSTEM_INCLUDES
  13. #include <sys/types.h>
  14. #include <errno.h>
  15. #endif
  16. #include "db_int.h"
  17. #include "db_page.h"
  18. #include "db_auto.h"
  19. #include "db_ext.h"
  20. #include "common_ext.h"
  21. static int __db_keyempty __P((const DB_ENV *));
  22. static int __db_rdonly __P((const DB_ENV *, const char *));
  23. static int __dbt_ferr __P((const DB *, const char *, const DBT *, int));
  24. /*
  25. * __db_cdelchk --
  26. * Common cursor delete argument checking routine.
  27. *
  28. * PUBLIC: int __db_cdelchk __P((const DB *, u_int32_t, int, int));
  29. */
  30. int
  31. __db_cdelchk(dbp, flags, isrdonly, isvalid)
  32. const DB *dbp;
  33. u_int32_t flags;
  34. int isrdonly, isvalid;
  35. {
  36. /* Check for changes to a read-only tree. */
  37. if (isrdonly)
  38. return (__db_rdonly(dbp->dbenv, "c_del"));
  39. /* Check for invalid function flags. */
  40. switch (flags) {
  41. case 0:
  42. break;
  43. default:
  44. return (__db_ferr(dbp->dbenv, "DBcursor->c_del", 0));
  45. }
  46. /*
  47. * The cursor must be initialized, return -1 for an invalid cursor,
  48. * otherwise 0.
  49. */
  50. return (isvalid ? 0 : EINVAL);
  51. }
  52. /*
  53. * __db_cgetchk --
  54. * Common cursor get argument checking routine.
  55. *
  56. * PUBLIC: int __db_cgetchk __P((const DB *, DBT *, DBT *, u_int32_t, int));
  57. */
  58. int
  59. __db_cgetchk(dbp, key, data, flags, isvalid)
  60. const DB *dbp;
  61. DBT *key, *data;
  62. u_int32_t flags;
  63. int isvalid;
  64. {
  65. int key_einval, key_flags, ret;
  66. key_einval = key_flags = 0;
  67. /* Check for invalid function flags. */
  68. LF_CLR(DB_RMW);
  69. switch (flags) {
  70. case DB_NEXT_DUP:
  71. if (dbp->type == DB_RECNO)
  72. goto err;
  73. /* FALLTHROUGH */
  74. case DB_CURRENT:
  75. case DB_FIRST:
  76. case DB_LAST:
  77. case DB_NEXT:
  78. case DB_PREV:
  79. key_flags = 1;
  80. break;
  81. case DB_GET_BOTH:
  82. case DB_SET_RANGE:
  83. key_einval = key_flags = 1;
  84. break;
  85. case DB_SET:
  86. key_einval = 1;
  87. break;
  88. case DB_GET_RECNO:
  89. if (!F_ISSET(dbp, DB_BT_RECNUM))
  90. goto err;
  91. break;
  92. case DB_SET_RECNO:
  93. if (!F_ISSET(dbp, DB_BT_RECNUM))
  94. goto err;
  95. key_einval = key_flags = 1;
  96. break;
  97. default:
  98. err: return (__db_ferr(dbp->dbenv, "DBcursor->c_get", 0));
  99. }
  100. /* Check for invalid key/data flags. */
  101. if ((ret = __dbt_ferr(dbp, "key", key, 0)) != 0)
  102. return (ret);
  103. if ((ret = __dbt_ferr(dbp, "data", data, 0)) != 0)
  104. return (ret);
  105. /* Check for missing keys. */
  106. if (key_einval && (key->data == NULL || key->size == 0))
  107. return (__db_keyempty(dbp->dbenv));
  108. /*
  109. * The cursor must be initialized for DB_CURRENT, return -1 for an
  110. * invalid cursor, otherwise 0.
  111. */
  112. return (isvalid || flags != DB_CURRENT ? 0 : EINVAL);
  113. }
  114. /*
  115. * __db_cputchk --
  116. * Common cursor put argument checking routine.
  117. *
  118. * PUBLIC: int __db_cputchk __P((const DB *,
  119. * PUBLIC: const DBT *, DBT *, u_int32_t, int, int));
  120. */
  121. int
  122. __db_cputchk(dbp, key, data, flags, isrdonly, isvalid)
  123. const DB *dbp;
  124. const DBT *key;
  125. DBT *data;
  126. u_int32_t flags;
  127. int isrdonly, isvalid;
  128. {
  129. int key_einval, key_flags, ret;
  130. key_einval = key_flags = 0;
  131. /* Check for changes to a read-only tree. */
  132. if (isrdonly)
  133. return (__db_rdonly(dbp->dbenv, "c_put"));
  134. /* Check for invalid function flags. */
  135. switch (flags) {
  136. case DB_AFTER:
  137. case DB_BEFORE:
  138. if (dbp->dup_compare != NULL)
  139. goto err;
  140. if (dbp->type == DB_RECNO && !F_ISSET(dbp, DB_RE_RENUMBER))
  141. goto err;
  142. if (dbp->type != DB_RECNO && !F_ISSET(dbp, DB_AM_DUP))
  143. goto err;
  144. break;
  145. case DB_CURRENT:
  146. /*
  147. * If there is a comparison function, doing a DB_CURRENT
  148. * must not change the part of the data item that is used
  149. * for the comparison.
  150. */
  151. break;
  152. case DB_KEYFIRST:
  153. case DB_KEYLAST:
  154. if (dbp->type == DB_RECNO)
  155. goto err;
  156. key_einval = key_flags = 1;
  157. break;
  158. default:
  159. err: return (__db_ferr(dbp->dbenv, "DBcursor->c_put", 0));
  160. }
  161. /* Check for invalid key/data flags. */
  162. if (key_flags && (ret = __dbt_ferr(dbp, "key", key, 0)) != 0)
  163. return (ret);
  164. if ((ret = __dbt_ferr(dbp, "data", data, 0)) != 0)
  165. return (ret);
  166. /* Check for missing keys. */
  167. if (key_einval && (key->data == NULL || key->size == 0))
  168. return (__db_keyempty(dbp->dbenv));
  169. /*
  170. * The cursor must be initialized for anything other than DB_KEYFIRST
  171. * and DB_KEYLAST, return -1 for an invalid cursor, otherwise 0.
  172. */
  173. return (isvalid ||
  174. flags == DB_KEYFIRST || flags == DB_KEYLAST ? 0 : EINVAL);
  175. }
  176. /*
  177. * __db_closechk --
  178. * DB->close flag check.
  179. *
  180. * PUBLIC: int __db_closechk __P((const DB *, u_int32_t));
  181. */
  182. int
  183. __db_closechk(dbp, flags)
  184. const DB *dbp;
  185. u_int32_t flags;
  186. {
  187. /* Check for invalid function flags. */
  188. if (flags != 0 && flags != DB_NOSYNC)
  189. return (__db_ferr(dbp->dbenv, "DB->close", 0));
  190. return (0);
  191. }
  192. /*
  193. * __db_delchk --
  194. * Common delete argument checking routine.
  195. *
  196. * PUBLIC: int __db_delchk __P((const DB *, DBT *, u_int32_t, int));
  197. */
  198. int
  199. __db_delchk(dbp, key, flags, isrdonly)
  200. const DB *dbp;
  201. DBT *key;
  202. u_int32_t flags;
  203. int isrdonly;
  204. {
  205. /* Check for changes to a read-only tree. */
  206. if (isrdonly)
  207. return (__db_rdonly(dbp->dbenv, "delete"));
  208. /* Check for invalid function flags. */
  209. switch (flags) {
  210. case 0:
  211. break;
  212. default:
  213. return (__db_ferr(dbp->dbenv, "DB->del", 0));
  214. }
  215. /* Check for missing keys. */
  216. if (key->data == NULL || key->size == 0)
  217. return (__db_keyempty(dbp->dbenv));
  218. return (0);
  219. }
  220. /*
  221. * __db_getchk --
  222. * Common get argument checking routine.
  223. *
  224. * PUBLIC: int __db_getchk __P((const DB *, const DBT *, DBT *, u_int32_t));
  225. */
  226. int
  227. __db_getchk(dbp, key, data, flags)
  228. const DB *dbp;
  229. const DBT *key;
  230. DBT *data;
  231. u_int32_t flags;
  232. {
  233. int ret;
  234. /* Check for invalid function flags. */
  235. LF_CLR(DB_RMW);
  236. switch (flags) {
  237. case 0:
  238. case DB_GET_BOTH:
  239. break;
  240. case DB_SET_RECNO:
  241. if (!F_ISSET(dbp, DB_BT_RECNUM))
  242. goto err;
  243. break;
  244. default:
  245. err: return (__db_ferr(dbp->dbenv, "DB->get", 0));
  246. }
  247. /* Check for invalid key/data flags. */
  248. if ((ret = __dbt_ferr(dbp, "key", key, flags == DB_SET_RECNO)) != 0)
  249. return (ret);
  250. if ((ret = __dbt_ferr(dbp, "data", data, 1)) != 0)
  251. return (ret);
  252. /* Check for missing keys. */
  253. if (key->data == NULL || key->size == 0)
  254. return (__db_keyempty(dbp->dbenv));
  255. return (0);
  256. }
  257. /*
  258. * __db_joinchk --
  259. * Common join argument checking routine.
  260. *
  261. * PUBLIC: int __db_joinchk __P((const DB *, u_int32_t));
  262. */
  263. int
  264. __db_joinchk(dbp, flags)
  265. const DB *dbp;
  266. u_int32_t flags;
  267. {
  268. if (flags != 0)
  269. return (__db_ferr(dbp->dbenv, "DB->join", 0));
  270. return (0);
  271. }
  272. /*
  273. * __db_putchk --
  274. * Common put argument checking routine.
  275. *
  276. * PUBLIC: int __db_putchk
  277. * PUBLIC: __P((const DB *, DBT *, const DBT *, u_int32_t, int, int));
  278. */
  279. int
  280. __db_putchk(dbp, key, data, flags, isrdonly, isdup)
  281. const DB *dbp;
  282. DBT *key;
  283. const DBT *data;
  284. u_int32_t flags;
  285. int isrdonly, isdup;
  286. {
  287. int ret;
  288. /* Check for changes to a read-only tree. */
  289. if (isrdonly)
  290. return (__db_rdonly(dbp->dbenv, "put"));
  291. /* Check for invalid function flags. */
  292. switch (flags) {
  293. case 0:
  294. case DB_NOOVERWRITE:
  295. break;
  296. case DB_APPEND:
  297. if (dbp->type != DB_RECNO)
  298. goto err;
  299. break;
  300. default:
  301. err: return (__db_ferr(dbp->dbenv, "DB->put", 0));
  302. }
  303. /* Check for invalid key/data flags. */
  304. if ((ret = __dbt_ferr(dbp, "key", key, 0)) != 0)
  305. return (ret);
  306. if ((ret = __dbt_ferr(dbp, "data", data, 0)) != 0)
  307. return (ret);
  308. /* Check for missing keys. */
  309. if (key->data == NULL || key->size == 0)
  310. return (__db_keyempty(dbp->dbenv));
  311. /* Check for partial puts in the presence of duplicates. */
  312. if (isdup && F_ISSET(data, DB_DBT_PARTIAL)) {
  313. __db_err(dbp->dbenv,
  314. "a partial put in the presence of duplicates requires a cursor operation");
  315. return (EINVAL);
  316. }
  317. return (0);
  318. }
  319. /*
  320. * __db_statchk --
  321. * Common stat argument checking routine.
  322. *
  323. * PUBLIC: int __db_statchk __P((const DB *, u_int32_t));
  324. */
  325. int
  326. __db_statchk(dbp, flags)
  327. const DB *dbp;
  328. u_int32_t flags;
  329. {
  330. /* Check for invalid function flags. */
  331. switch (flags) {
  332. case 0:
  333. break;
  334. case DB_RECORDCOUNT:
  335. if (dbp->type == DB_RECNO)
  336. break;
  337. if (dbp->type == DB_BTREE && F_ISSET(dbp, DB_BT_RECNUM))
  338. break;
  339. goto err;
  340. default:
  341. err: return (__db_ferr(dbp->dbenv, "DB->stat", 0));
  342. }
  343. return (0);
  344. }
  345. /*
  346. * __db_syncchk --
  347. * Common sync argument checking routine.
  348. *
  349. * PUBLIC: int __db_syncchk __P((const DB *, u_int32_t));
  350. */
  351. int
  352. __db_syncchk(dbp, flags)
  353. const DB *dbp;
  354. u_int32_t flags;
  355. {
  356. /* Check for invalid function flags. */
  357. switch (flags) {
  358. case 0:
  359. break;
  360. default:
  361. return (__db_ferr(dbp->dbenv, "DB->sync", 0));
  362. }
  363. return (0);
  364. }
  365. /*
  366. * __dbt_ferr --
  367. * Check a DBT for flag errors.
  368. */
  369. static int
  370. __dbt_ferr(dbp, name, dbt, check_thread)
  371. const DB *dbp;
  372. const char *name;
  373. const DBT *dbt;
  374. int check_thread;
  375. {
  376. int ret;
  377. /*
  378. * Check for invalid DBT flags. We allow any of the flags to be
  379. * specified to any DB or DBcursor call so that applications can
  380. * set DB_DBT_MALLOC when retrieving a data item from a secondary
  381. * database and then specify that same DBT as a key to a primary
  382. * database, without having to clear flags.
  383. */
  384. if ((ret = __db_fchk(dbp->dbenv, name, dbt->flags,
  385. DB_DBT_MALLOC | DB_DBT_USERMEM | DB_DBT_PARTIAL)) != 0)
  386. return (ret);
  387. if ((ret = __db_fcchk(dbp->dbenv, name,
  388. dbt->flags, DB_DBT_MALLOC, DB_DBT_USERMEM)) != 0)
  389. return (ret);
  390. if (check_thread && F_ISSET(dbp, DB_AM_THREAD) &&
  391. !F_ISSET(dbt, DB_DBT_MALLOC | DB_DBT_USERMEM)) {
  392. __db_err(dbp->dbenv,
  393. "missing flag thread flag for %s DBT", name);
  394. return (EINVAL);
  395. }
  396. return (0);
  397. }
  398. /*
  399. * __db_eopnotsup --
  400. * Common operation not supported message.
  401. *
  402. * PUBLIC: int __db_eopnotsup __P((const DB_ENV *));
  403. */
  404. int
  405. __db_eopnotsup(dbenv)
  406. const DB_ENV *dbenv;
  407. {
  408. __db_err(dbenv, "operation not supported");
  409. #ifdef EOPNOTSUPP
  410. return (EOPNOTSUPP);
  411. #else
  412. return (EINVAL);
  413. #endif
  414. }
  415. /*
  416. * __db_keyempty --
  417. * Common missing or empty key value message.
  418. */
  419. static int
  420. __db_keyempty(dbenv)
  421. const DB_ENV *dbenv;
  422. {
  423. __db_err(dbenv, "missing or empty key value specified");
  424. return (EINVAL);
  425. }
  426. /*
  427. * __db_rdonly --
  428. * Common readonly message.
  429. */
  430. static int
  431. __db_rdonly(dbenv, name)
  432. const DB_ENV *dbenv;
  433. const char *name;
  434. {
  435. __db_err(dbenv, "%s: attempt to modify a read-only tree", name);
  436. return (EACCES);
  437. }