nsdb.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836
  1. /** BEGIN COPYRIGHT BLOCK
  2. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  3. * Copyright (C) 2005 Red Hat, Inc.
  4. * All rights reserved.
  5. * END COPYRIGHT BLOCK **/
  6. /*
  7. * Description (nsdb.c)
  8. *
  9. * This provides access to a Netscape server database.
  10. * A server database is composed of two (libdbm) DB files. One
  11. * of these (<dbname>.db) contains records indexed by a string
  12. * key. These records contain the primary information in the
  13. * database. A second DB file (<dbname>.id) is used to map an
  14. * integer id value to a string key, which can then be used to
  15. * locate a record in the first file.
  16. *
  17. * Normally the records in the primary DB file will contain the
  18. * id values which are used to key the id-to-name DB. When this
  19. * is the case, it is possible to construct the id-to-name DB from
  20. * the primary DB file, and an interface is provided to facilitate
  21. * this.
  22. */
  23. #include <stdio.h>
  24. #include <base/systems.h>
  25. #include <netsite.h>
  26. #include <base/file.h>
  27. #define __PRIVATE_NSDB
  28. #include <libaccess/nsdb.h>
  29. #include <errno.h>
  30. #define NDBMODE 0644 /* mode for creating files */
  31. char * NSDB_Program = "NSDB"; /* NSDB facility name */
  32. NSPR_BEGIN_EXTERN_C
  33. /*
  34. * Description (ndbClose)
  35. *
  36. * This function closes the specified database. This involves
  37. * closing the primary and id-to-name DB files, and freeing the
  38. * NSDB_t object.
  39. *
  40. * Arguments:
  41. *
  42. * ndb - database handle from ndbOpen()
  43. * flags - (currently unused - should be zero)
  44. *
  45. */
  46. void ndbClose(void * ndb, int flags)
  47. {
  48. NSDB_t * ndbp = (NSDB_t *)ndb; /* database object pointer */
  49. if (ndbp->ndb_flags & (NDBF_WRNAME|NDBF_RDNAME)) {
  50. (*ndbp->ndb_pdb->close)(ndbp->ndb_pdb);
  51. }
  52. if (ndbp->ndb_flags & (NDBF_WRID|NDBF_RDID)) {
  53. (*ndbp->ndb_idb->close)(ndbp->ndb_idb);
  54. }
  55. if (ndbp->ndb_pname) {
  56. FREE(ndbp->ndb_pname);
  57. }
  58. if (ndbp->ndb_iname) {
  59. FREE(ndbp->ndb_iname);
  60. }
  61. FREE(ndbp);
  62. }
  63. /*
  64. * Description (ndbEnumerate)
  65. *
  66. * This function is called to enumerate the records of the primary
  67. * DB file to a caller-specified function. The function specified
  68. * by the caller is called with the name (key), length and address
  69. * of each record in the primary DB file. The 'flags' argument can
  70. * be used to select normal data records, metadata records, or both.
  71. * If the 'flags' value is zero, only normal data records are
  72. * enumerated. The function specified by the caller returns -1 to
  73. * terminate the enumeration, 0 to continue it, or +1 to restart
  74. * the enumeration from the beginning.
  75. *
  76. * Arguments:
  77. *
  78. * errp - error frame list pointer (may be null)
  79. * ndb - database handle from ndbOpen()
  80. * flags - bit flags:
  81. * NDBF_ENUMNORM - normal data records
  82. * NDBF_ENUMMETA - metadata records
  83. * func - pointer to caller's enumeration function
  84. *
  85. * Returns:
  86. *
  87. * If successful, the return value is zero. Otherwise a non-zero
  88. * error code is returned, and an error frame is generated if an
  89. * error frame list was provided by the caller.
  90. */
  91. int ndbEnumerate(NSErr_t * errp, void * ndb, int flags, void * argp,
  92. #ifdef UnixWare
  93. ArgFn_ndbEnum func) /* for ANSI C++ standard, see nsdb.h */
  94. #else
  95. int (*func)(NSErr_t * ferrp, void * parg,
  96. int namelen, char * name,
  97. int reclen, char * recptr))
  98. #endif
  99. {
  100. NSDB_t * ndbp = (NSDB_t *)ndb; /* database object pointer */
  101. DBT key;
  102. DBT rec;
  103. int rv;
  104. int dbflag;
  105. /* Is the user DB open for reading names? */
  106. if (!(ndbp->ndb_flags & NDBF_RDNAME)) {
  107. /* No, (re)open it */
  108. rv = ndbReOpen(errp, ndb, NDBF_RDNAME);
  109. if (rv) goto punt;
  110. }
  111. if (flags == 0) flags = NDBF_ENUMNORM;
  112. for (dbflag = R_FIRST; ; dbflag = (rv > 0) ? R_FIRST : R_NEXT) {
  113. /* Retrieve the next (first) record from the primary DB */
  114. rv = (*ndbp->ndb_pdb->seq)(ndbp->ndb_pdb, &key, &rec, dbflag);
  115. if (rv) break;
  116. /* Is this a metadata record? */
  117. if (*(char *)key.data == NDB_MDPREFIX) {
  118. /* Yes, skip it if metadata was not requested */
  119. if (!(flags & NDBF_ENUMMETA)) continue;
  120. }
  121. else {
  122. /* Skip normal data if not requested */
  123. if (!(flags & NDBF_ENUMNORM)) continue;
  124. }
  125. /* Pass this record to the caller's function */
  126. rv = (*func)(errp, argp,
  127. key.size, (char *)key.data, rec.size, (char *)rec.data);
  128. if (rv < 0) break;
  129. }
  130. /* Indicate success */
  131. rv = 0;
  132. punt:
  133. return rv;
  134. }
  135. /*
  136. * Description (ndbFindName)
  137. *
  138. * This function retrieves from the database a record with the
  139. * specified key.
  140. *
  141. * Arguments:
  142. *
  143. * errp - error frame list pointer (may be null)
  144. * ndb - database handle from ndbOpen()
  145. * namelen - length of the key, including null
  146. * terminator if any
  147. * name - pointer to the key of the desired record
  148. * reclen - pointer to returned record length
  149. * recptr - pointer to returned record pointer
  150. *
  151. * Returns:
  152. *
  153. * If successful, the return value is zero, and the length and
  154. * address of the returned record are returned through reclen and
  155. * recptr. Otherwise the return value is non-zero, and an error
  156. * frame is generated if an error frame list was provided by the
  157. * caller.
  158. *
  159. * Notes:
  160. *
  161. * The record buffer is dynamically allocated and is freed
  162. * automatically when the database is closed.
  163. */
  164. int ndbFindName(NSErr_t * errp, void * ndb, int namelen, char * name,
  165. int * reclen, char **recptr)
  166. {
  167. NSDB_t * ndbp = (NSDB_t *)ndb; /* database object pointer */
  168. DBT key;
  169. DBT rec;
  170. int eid; /* error id code */
  171. int rv; /* result value */
  172. /* Is the user DB open for reading names? */
  173. if (!(ndbp->ndb_flags & NDBF_RDNAME)) {
  174. /* No, (re)open it */
  175. rv = ndbReOpen(errp, ndb, NDBF_RDNAME);
  176. if (rv) goto punt;
  177. }
  178. /* Set up record key. Include the terminating null byte. */
  179. key.data = (void *)name;
  180. key.size = (namelen > 0) ? namelen : (strlen(name) + 1);
  181. /* Initialize record buffer descriptor */
  182. rec.data = 0;
  183. rec.size = 0;
  184. /* Retrieve the record by its key */
  185. rv = (*ndbp->ndb_pdb->get)(ndbp->ndb_pdb, &key, &rec, 0);
  186. if (rv) goto err_pget;
  187. /* Return record length and address */
  188. if (reclen) *reclen = rec.size;
  189. if (recptr) *recptr = (char *)rec.data;
  190. /* Indicate success */
  191. rv = 0;
  192. punt:
  193. return rv;
  194. err_pget:
  195. eid = NSDBERR1000;
  196. rv = NDBERRGET;
  197. nserrGenerate(errp, rv, eid, NSDB_Program, 2, ndbp->ndb_pname, name);
  198. goto punt;
  199. }
  200. /*
  201. * Description (ndbIdToName)
  202. *
  203. * This function looks up a specified id in the id-to-name DB
  204. * file, and returns the associated name string. This name
  205. * can be used to retrieve a record using ndbFindName().
  206. *
  207. * Arguments:
  208. *
  209. * errp - error frame list pointer (may be null)
  210. * ndb - database handle from ndbOpen()
  211. * id - id to look up
  212. * plen - pointer to returned length of name
  213. * (may be null, length includes null terminator
  214. * in a string)
  215. * pname - pointer to returned name string pointer
  216. *
  217. * Returns:
  218. *
  219. * The return value is zero if the operation is successful. An
  220. * error is indicated by a negative return value (see nsdberr.h),
  221. * and an error frame is generated if an error frame list was
  222. * provided by the caller.
  223. */
  224. int ndbIdToName(NSErr_t * errp,
  225. void * ndb, unsigned int id, int * plen, char **pname)
  226. {
  227. NSDB_t * ndbp = (NSDB_t *)ndb; /* database object pointer */
  228. DBT key;
  229. DBT rec;
  230. char * name = 0;
  231. int namelen = 0;
  232. uint32 myid = id - 1;
  233. int eid; /* error id code */
  234. int rv; /* result value */
  235. /* Is the id-to-name DB open for reading ids? */
  236. if (!(ndbp->ndb_flags & NDBF_RDID)) {
  237. /* No, (re)open it */
  238. rv = ndbReOpen(errp, ndb, NDBF_RDID);
  239. if (rv) goto punt;
  240. }
  241. /* Set up record key */
  242. #if BYTE_ORDER == LITTLE_ENDIAN
  243. M_32_SWAP(myid);
  244. #endif
  245. key.data = (void *)&myid;
  246. key.size = sizeof(myid);
  247. /* Initialize record buffer descriptor */
  248. rec.data = 0;
  249. rec.size = 0;
  250. /* Retrieve the record by its key */
  251. rv = (*ndbp->ndb_idb->get)(ndbp->ndb_idb, &key, &rec, 0);
  252. if (rv) goto err_iget;
  253. /* Get the name pointer (terminating null is part of the name) */
  254. namelen = rec.size;
  255. name = (char *) rec.data;
  256. punt:
  257. /* Return name length and size if requested */
  258. if (plen) *plen = namelen;
  259. if (pname) *pname = name;
  260. return rv;
  261. err_iget:
  262. eid = NSDBERR1100;
  263. rv = NDBERRGET;
  264. nserrGenerate(errp, rv, eid, NSDB_Program,
  265. 2, ndbp->ndb_iname, system_errmsg());
  266. goto punt;
  267. }
  268. /*
  269. * Description (ndbInitPrimary)
  270. *
  271. * This function creates and initializes the primary DB file.
  272. * Initialization involves writing any required metadata records.
  273. * Currently there is a ?dbtype record, which specifies the nsdb
  274. * version number, and a database type and version number that
  275. * were passed as arguments to ndbOpen(). There is also a
  276. * ?idmap record, which contains an allocation bitmap for id values
  277. * used as keys in the associated id-to-name DB file.
  278. *
  279. * Arguments:
  280. *
  281. * errp - error frame list pointer (may be null)
  282. * ndb - database handle from ndbOpen()
  283. *
  284. * Returns:
  285. *
  286. * If successful, the return value is zero. Otherwise a non-zero
  287. * error code is returned, and an error frame is generated if an
  288. * error frame list was provided by the caller.
  289. */
  290. int ndbInitPrimary(NSErr_t * errp, void * ndb)
  291. {
  292. NSDB_t * ndbp = (NSDB_t *)ndb; /* database object pointer */
  293. DBT key;
  294. DBT rec;
  295. #if BYTE_ORDER == LITTLE_ENDIAN
  296. uint32 m;
  297. int i;
  298. #endif
  299. int eid; /* error id code */
  300. int rv; /* result value */
  301. uint32 dbtype[4];
  302. /* Error if the primary DB is marked as existing already */
  303. if (!(ndbp->ndb_flags & NDBF_NONAME)) goto err_exists;
  304. /* First create the primary DB file */
  305. ndbp->ndb_pdb = dbopen(ndbp->ndb_pname, O_RDWR | O_CREAT | O_TRUNC,
  306. NDBMODE, DB_HASH, 0);
  307. if (!ndbp->ndb_pdb) goto err_open;
  308. /* Generate data for the ?dbtype record */
  309. dbtype[0] = NDB_VERSION;
  310. dbtype[1] = ndbp->ndb_dbtype;
  311. dbtype[2] = ndbp->ndb_version;
  312. dbtype[3] = 0;
  313. #if BYTE_ORDER == LITTLE_ENDIAN
  314. for (i = 0; i < 4; ++i) {
  315. m = dbtype[i];
  316. M_32_SWAP(m);
  317. dbtype[i] = m;
  318. }
  319. #endif
  320. /* Set up descriptors for the ?dbtype record key and data */
  321. key.data = (void *)NDB_DBTYPE;
  322. key.size = strlen(NDB_DBTYPE) + 1;
  323. rec.data = (void *)dbtype;
  324. rec.size = sizeof(dbtype);
  325. /* Write the ?dbtype record out */
  326. rv = (*ndbp->ndb_pdb->put)(ndbp->ndb_pdb, &key, &rec, 0);
  327. if (rv) goto err_mput1;
  328. /* Write out an empty ?idmap record */
  329. key.data = (void *)NDB_IDMAP;
  330. key.size = strlen(NDB_IDMAP) + 1;
  331. rec.data = 0;
  332. rec.size = 0;
  333. /* Write the ?idmap record */
  334. rv = (*ndbp->ndb_pdb->put)(ndbp->ndb_pdb, &key, &rec, 0);
  335. if (rv) goto err_mput2;
  336. /* Close the DB file */
  337. (*ndbp->ndb_pdb->close)(ndbp->ndb_pdb);
  338. /* Clear the flag that says the primary DB file does not exist */
  339. ndbp->ndb_flags &= ~(NDBF_NONAME|NDBF_RDNAME|NDBF_WRNAME);
  340. /* Indicate success */
  341. return 0;
  342. err_exists:
  343. /* Primary database already exists */
  344. eid = NSDBERR1200;
  345. rv = NDBERREXIST;
  346. nserrGenerate(errp, rv, eid, NSDB_Program, 1, ndbp->ndb_pname);
  347. return rv;
  348. err_open:
  349. /* Error opening primary database for write */
  350. eid = NSDBERR1220;
  351. rv = NDBERROPEN;
  352. goto err_dbio;
  353. err_mput1:
  354. /* Error writing "?dbtype" record */
  355. eid = NSDBERR1240;
  356. rv = NDBERRMDPUT;
  357. goto err_dbio;
  358. err_mput2:
  359. /* Error writing "?idmap" record */
  360. eid = NSDBERR1260;
  361. rv = NDBERRMDPUT;
  362. goto err_dbio;
  363. err_dbio:
  364. nserrGenerate(errp, rv, eid, NSDB_Program,
  365. 2, ndbp->ndb_pname, system_errmsg());
  366. /* Close the primary DB file if it exists */
  367. if (ndbp->ndb_pdb) {
  368. (*ndbp->ndb_pdb->close)(ndbp->ndb_pdb);
  369. ndbp->ndb_flags &= ~(NDBF_RDNAME|NDBF_WRNAME);
  370. }
  371. /* Delete the file */
  372. system_unlink(ndbp->ndb_pname);
  373. return rv;
  374. }
  375. /*
  376. * Description (ndbOpen)
  377. *
  378. * This function opens a server database by name. The specified
  379. * name may be the name of the primary DB file, or the name
  380. * without the ".db" suffix. This function will attempt to open
  381. * both the primary and the id-to-name DB files for read access.
  382. * If either of the DB files do not exist, they are not created
  383. * here, but a handle for the database will still be returned.
  384. * The DB files will be created when a subsequent access writes
  385. * to the database. The caller also specifies an application
  386. * database type, which is checked against a value stored in
  387. * in the database metadata, if the primary DB file exists, or
  388. * which is stored in the file metadata when the file is created.
  389. * A type-specific version number is passed and returned. The
  390. * value passed will be stored in the file metadata if it is
  391. * subsequently created. If the file exists, the value in the
  392. * file metadata is returned, and it is the caller's responsibility
  393. * to interpret it.
  394. *
  395. * Arguments:
  396. *
  397. * errp - error frame list pointer (may be null)
  398. * dbname - primary DB filename
  399. * flags - (currently unused - should be zero)
  400. * dbtype - application DB type (NDB_TYPE_xxxxx)
  401. * version - (in/out) type-specific version number
  402. *
  403. * Returns:
  404. *
  405. * A handle that can be used for subsequent accesses to the database
  406. * is returned, or 0, if an error occurs, and an error frame is
  407. * generated if an error frame list was provided by the caller.
  408. */
  409. void * ndbOpen(NSErr_t * errp,
  410. char * dbname, int flags, int dbtype, int * version)
  411. {
  412. NSDB_t * ndbp = 0; /* database object pointer */
  413. char * pname = 0; /* primary DB file name */
  414. char * iname = 0; /* id-to-name DB file name */
  415. int namelen;
  416. uint32 dbtrec[4];
  417. uint32 m;
  418. DBT key;
  419. DBT rec;
  420. int eid; /* error id code */
  421. int rv; /* result value */
  422. /* Get the database name */
  423. namelen = strlen(dbname);
  424. if (!strcmp(&dbname[namelen-3], ".db")) {
  425. namelen -= 3;
  426. }
  427. /* Get the primary DB file name */
  428. pname = (char *)MALLOC(namelen + 4);
  429. if (pname == 0) goto err_nomem1;
  430. strncpy(pname, dbname, namelen);
  431. strcpy(&pname[namelen], ".db");
  432. /* Get the id-to-name DB file name */
  433. iname = (char *)MALLOC(namelen + 4);
  434. if (iname == 0) goto err_nomem2;
  435. strncpy(iname, dbname, namelen);
  436. strcpy(&iname[namelen], ".id");
  437. /* Allocate the database object */
  438. ndbp = (NSDB_t *)MALLOC(sizeof(NSDB_t));
  439. if (ndbp == 0) goto err_nomem3;
  440. /* Initialize the database object */
  441. ndbp->ndb_pname = pname;
  442. ndbp->ndb_pdb = 0;
  443. ndbp->ndb_iname = iname;
  444. ndbp->ndb_idb = 0;
  445. ndbp->ndb_flags = 0;
  446. ndbp->ndb_dbtype = dbtype;
  447. ndbp->ndb_version = (version) ? *version : 0;
  448. /* Open the primary DB file */
  449. ndbp->ndb_pdb = dbopen(pname, O_RDONLY, NDBMODE, DB_HASH, 0);
  450. /* Was it there? */
  451. if (ndbp->ndb_pdb) {
  452. /* Retrieve the ?dbtype record */
  453. key.data = (void *)NDB_DBTYPE;
  454. key.size = strlen(NDB_DBTYPE) + 1;
  455. rec.data = 0;
  456. rec.size = 0;
  457. /* Read the ?dbtype record */
  458. rv = (*ndbp->ndb_pdb->get)(ndbp->ndb_pdb, &key, &rec, 0);
  459. if (rv) goto err_mdget;
  460. /* Check it out */
  461. if (rec.size < 16) goto err_fmt;
  462. /* Copy data to an aligned area */
  463. memcpy((void *)dbtrec, rec.data, sizeof(dbtrec));
  464. /* Get the NSDB version number */
  465. m = dbtrec[0];
  466. #if BYTE_ORDER == LITTLE_ENDIAN
  467. M_32_SWAP(m);
  468. #endif
  469. /* Assume forward compatibility with versions up to current + 0.5 */
  470. if (m > (NDB_VERSION + 5)) goto err_vers;
  471. /* XXX Assume infinite backward compatibility */
  472. /* Get the application database type */
  473. m = dbtrec[1];
  474. #if BYTE_ORDER == LITTLE_ENDIAN
  475. M_32_SWAP(m);
  476. #endif
  477. /* It's got to match */
  478. if (m != dbtype) goto err_type;
  479. /* Get the type-specific version number */
  480. m = dbtrec[3];
  481. #if BYTE_ORDER == LITTLE_ENDIAN
  482. M_32_SWAP(m);
  483. #endif
  484. /* Don't check it. Just return it. */
  485. if (version) *version = m;
  486. /* The value in dbtrec[3] is currently ignored */
  487. /* Mark the primary DB file open for read access */
  488. ndbp->ndb_flags |= NDBF_RDNAME;
  489. }
  490. else {
  491. /* Indicate that the primary DB file does not exist */
  492. ndbp->ndb_flags |= NDBF_NONAME;
  493. }
  494. return (void *)ndbp;
  495. err_nomem1:
  496. eid = NSDBERR1400;
  497. rv = NDBERRNOMEM;
  498. goto err_nomem;
  499. err_nomem2:
  500. eid = NSDBERR1420;
  501. rv = NDBERRNOMEM;
  502. goto err_nomem;
  503. err_nomem3:
  504. eid = NSDBERR1440;
  505. rv = NDBERRNOMEM;
  506. err_nomem:
  507. nserrGenerate(errp, rv, eid, NSDB_Program, 0);
  508. goto punt;
  509. err_mdget:
  510. eid = NSDBERR1460;
  511. rv = NDBERRMDGET;
  512. nserrGenerate(errp, rv, eid, NSDB_Program, 2, ndbp->ndb_pname,
  513. system_errmsg());
  514. goto err_ret;
  515. err_fmt:
  516. eid = NSDBERR1480;
  517. rv = NDBERRMDFMT;
  518. goto err_ret;
  519. err_vers:
  520. {
  521. char vnbuf[16];
  522. eid = NSDBERR1500;
  523. rv = NDBERRVERS;
  524. sprintf(vnbuf, "%d", (int)m);
  525. nserrGenerate(errp, rv, eid, NSDB_Program, 2, ndbp->ndb_pname, vnbuf);
  526. }
  527. goto punt;
  528. err_type:
  529. eid = NSDBERR1520;
  530. rv = NDBERRDBTYPE;
  531. goto err_ret;
  532. err_ret:
  533. nserrGenerate(errp, rv, eid, NSDB_Program, 1, ndbp->ndb_pname);
  534. goto punt;
  535. punt:
  536. /* Error clean-up */
  537. if (pname) FREE(pname);
  538. if (iname) FREE(iname);
  539. if (ndbp) {
  540. /* Close the DB files if we got as far as opening them */
  541. if (ndbp->ndb_pdb) {
  542. (*ndbp->ndb_pdb->close)(ndbp->ndb_pdb);
  543. }
  544. if (ndbp->ndb_idb) {
  545. (*ndbp->ndb_idb->close)(ndbp->ndb_idb);
  546. }
  547. FREE(ndbp);
  548. }
  549. return 0;
  550. }
  551. /*
  552. * Description (ndbReOpen)
  553. *
  554. * This function is called to ensure that the primary DB file
  555. * and/or the id-to-name DB file are open with specified access
  556. * rights. For example, a file may be open for read, and it needs
  557. * to be open for write. Both the primary and id-to-name DB files
  558. * can be manipulated with a single call.
  559. *
  560. * Arguments:
  561. *
  562. * errp - error frame list pointer (may be null)
  563. * ndb - database handle from ndbOpen()
  564. * flags - (currently unused - should be zero)
  565. *
  566. * Returns:
  567. *
  568. * If successful, the return value is zero. Otherwise a non-zero
  569. * error code is returned (NDBERRxxxx - see nsdb.h). If an error
  570. * list is provided, an error frame will be generated when the
  571. * return value is non-zero.
  572. */
  573. int ndbReOpen(NSErr_t * errp, void * ndb, int flags)
  574. {
  575. NSDB_t * ndbp = (NSDB_t *)ndb; /* database object pointer */
  576. char * dbname; /* database name pointer */
  577. int eid;
  578. int rv;
  579. /* Want to read or write the primary DB file? */
  580. if (flags & (NDBF_RDNAME|NDBF_WRNAME)) {
  581. /* Need to open for write? */
  582. if ((flags & NDBF_WRNAME) && !(ndbp->ndb_flags & NDBF_WRNAME)) {
  583. /* If it's already open for read, close it first */
  584. if (ndbp->ndb_flags & NDBF_RDNAME) {
  585. (*ndbp->ndb_pdb->close)(ndbp->ndb_pdb);
  586. ndbp->ndb_flags &= ~NDBF_RDNAME;
  587. }
  588. /* Create it if it doesn't exist */
  589. if (ndbp->ndb_flags & NDBF_NONAME) {
  590. rv = ndbInitPrimary(errp, ndb);
  591. if (rv) goto err_init;
  592. }
  593. /* Open primary DB file for write access */
  594. dbname = ndbp->ndb_pname;
  595. ndbp->ndb_pdb = dbopen(dbname, O_RDWR, NDBMODE, DB_HASH, 0);
  596. if (!ndbp->ndb_pdb) goto err_open1;
  597. /* Update flags to indicate successful open */
  598. ndbp->ndb_flags |= (NDBF_RDNAME|NDBF_WRNAME);
  599. }
  600. /* Need to open for read? */
  601. if ((flags & NDBF_RDNAME) && !(ndbp->ndb_flags & NDBF_RDNAME)) {
  602. /* If it's already open for write, close it first */
  603. if (ndbp->ndb_flags & NDBF_WRNAME) {
  604. (*ndbp->ndb_pdb->close)(ndbp->ndb_pdb);
  605. ndbp->ndb_flags &= ~(NDBF_RDNAME|NDBF_WRNAME);
  606. }
  607. /* Open primary DB file for read access */
  608. dbname = ndbp->ndb_pname;
  609. ndbp->ndb_pdb = dbopen(dbname, O_RDONLY, NDBMODE, DB_HASH, 0);
  610. if (!ndbp->ndb_pdb) goto err_open2;
  611. /* Update flags to indicate successful open */
  612. ndbp->ndb_flags |= NDBF_RDNAME;
  613. }
  614. }
  615. /* Want to read or write the id-to-name DB file? */
  616. if (flags & (NDBF_RDID|NDBF_WRID)) {
  617. /* Need to open for write? */
  618. if ((flags & NDBF_WRID) && !(ndbp->ndb_flags & NDBF_WRID)) {
  619. /*
  620. * If it's not open for read yet, try to open it for read
  621. * in order to find out if it exists.
  622. */
  623. if (!(ndbp->ndb_flags & NDBF_RDID)) {
  624. /* Open id-to-name DB file for read access */
  625. dbname = ndbp->ndb_iname;
  626. ndbp->ndb_idb = dbopen(dbname, O_RDONLY, NDBMODE, DB_HASH,0);
  627. /* Does it exist? */
  628. if (ndbp->ndb_idb == 0) {
  629. /* No, create it */
  630. dbname = ndbp->ndb_iname;
  631. ndbp->ndb_idb = dbopen(dbname,O_RDWR | O_CREAT | O_TRUNC,
  632. NDBMODE, DB_HASH, 0);
  633. if (!ndbp->ndb_idb) goto err_open3;
  634. (*ndbp->ndb_idb->close)(ndbp->ndb_idb);
  635. }
  636. else {
  637. /* Mark it open for read */
  638. ndbp->ndb_flags |= NDBF_RDID;
  639. }
  640. }
  641. /* If it's already open for read, close it first */
  642. if (ndbp->ndb_flags & NDBF_RDID) {
  643. (*ndbp->ndb_idb->close)(ndbp->ndb_idb);
  644. ndbp->ndb_flags &= ~NDBF_RDID;
  645. }
  646. /* Open id-to-name DB file for write access */
  647. dbname = ndbp->ndb_iname;
  648. ndbp->ndb_idb = dbopen(dbname, O_RDWR, NDBMODE, DB_HASH, 0);
  649. if (!ndbp->ndb_idb) goto err_open4;
  650. /* Update flags to indicate successful open */
  651. ndbp->ndb_flags |= (NDBF_RDID|NDBF_WRID);
  652. }
  653. /* Need to open for read? */
  654. if ((flags & NDBF_RDID) && !(ndbp->ndb_flags & NDBF_RDID)) {
  655. /* If it's already open for write, close it first */
  656. if (ndbp->ndb_flags & NDBF_WRID) {
  657. (*ndbp->ndb_idb->close)(ndbp->ndb_idb);
  658. ndbp->ndb_flags &= ~(NDBF_RDID|NDBF_WRID);
  659. }
  660. /* Open id-to-name DB file for read access */
  661. dbname = ndbp->ndb_iname;
  662. ndbp->ndb_idb = dbopen(dbname, O_RDONLY, NDBMODE, DB_HASH, 0);
  663. if (!ndbp->ndb_idb) goto err_open5;
  664. /* Update flags to indicate successful open */
  665. ndbp->ndb_flags |= NDBF_RDID;
  666. }
  667. }
  668. /* Successful completion */
  669. return 0;
  670. /* Begin error handlers */
  671. err_init: /* failed to create primary DB file */
  672. (void)nserrGenerate(errp, NDBERRPINIT, NSDBERR1600, NSDB_Program,
  673. 1,
  674. ndbp->ndb_pname /* primary DB filename */
  675. );
  676. rv = NDBERRPINIT;
  677. goto punt;
  678. err_open1:
  679. eid = NSDBERR1620;
  680. goto err_open;
  681. err_open2:
  682. eid = NSDBERR1640;
  683. goto err_open;
  684. err_open3:
  685. eid = NSDBERR1660;
  686. goto err_open;
  687. err_open4:
  688. eid = NSDBERR1680;
  689. goto err_open;
  690. err_open5:
  691. eid = NSDBERR1700;
  692. goto err_open;
  693. err_open: /* database open error */
  694. rv = NDBERROPEN;
  695. (void)nserrGenerate(errp, NDBERROPEN, eid, NSDB_Program,
  696. 2, dbname, system_errmsg());
  697. punt:
  698. return rv;
  699. }
  700. NSPR_END_EXTERN_C