00001
00005 #include "system.h"
00006
00007 static int _debug = 1;
00008
00009 #ifdef HAVE_DB1_DB_H
00010 #include <db1/db.h>
00011 #else
00012 #ifdef HAVE_DB_185_H
00013 #include <db_185.h>
00014 #else
00015 #include <db.h>
00016 #endif
00017 #endif
00018
00019 #define DB_VERSION_MAJOR 1
00020 #define DB_VERSION_MINOR 85
00021 #define DB_VERSION_PATCH 0
00022
00023 #define _mymemset(_a, _b, _c)
00024
00025 #include <rpmio_internal.h>
00026 #include <rpmlib.h>
00027 #include <rpmmacro.h>
00028 #include <rpmurl.h>
00029
00030 #include "falloc.h"
00031 #include "misc.h"
00032
00033 #define DBC void
00034 #include "rpmdb.h"
00035
00036 #include "debug.h"
00037
00038
00039
00040
00041
00042
00043 static inline DBTYPE db3_to_dbtype(int dbitype)
00044 {
00045 switch(dbitype) {
00046 case 1: return DB_BTREE;
00047 case 2: return DB_HASH;
00048 case 3: return DB_RECNO;
00049 case 4: return DB_HASH;
00050 case 5: return DB_HASH;
00051 }
00052 return DB_HASH;
00053 }
00054
00055 static const char * db_strerror(int error)
00056 {
00057 if (error == 0)
00058 return ("Successful return: 0");
00059 if (error > 0)
00060 return (strerror(error));
00061
00062 switch (error) {
00063 default:
00064 {
00065
00066
00067
00068
00069
00070
00071 static char ebuf[40];
00072
00073 (void)snprintf(ebuf, sizeof(ebuf), "Unknown error: %d", error);
00074 return(ebuf);
00075 }
00076 }
00077
00078 }
00079
00080 static int cvtdberr(dbiIndex dbi, const char * msg, int error, int printit) {
00081 int rc = 0;
00082
00083 if (error == 0)
00084 rc = 0;
00085 else if (error < 0)
00086 rc = errno;
00087 else if (error > 0)
00088 rc = -1;
00089
00090 if (printit && rc) {
00091 if (msg)
00092 rpmError(RPMERR_DBERR, _("db%d error(%d) from %s: %s\n"),
00093 dbi->dbi_api, rc, msg, db_strerror(error));
00094 else
00095 rpmError(RPMERR_DBERR, _("db%d error(%d): %s\n"),
00096 dbi->dbi_api, rc, db_strerror(error));
00097 }
00098
00099 return rc;
00100 }
00101
00102 static int db1sync(dbiIndex dbi, unsigned int flags) {
00103 int rc = 0;
00104
00105 if (dbi->dbi_db) {
00106 if (dbi->dbi_rpmtag == RPMDBI_PACKAGES) {
00107 FD_t pkgs = dbi->dbi_db;
00108 int fdno = Fileno(pkgs);
00109 if (fdno >= 0 && (rc = fsync(fdno)) != 0)
00110 rc = errno;
00111 } else {
00112 DB * db = dbi->dbi_db;
00113 rc = db->sync(db, flags);
00114 rc = cvtdberr(dbi, "db->sync", rc, _debug);
00115 }
00116 }
00117
00118 return rc;
00119 }
00120
00121 static int db1byteswapped(dbiIndex dbi)
00122 {
00123 return 0;
00124 }
00125
00126 static void * doGetRecord(FD_t pkgs, unsigned int offset)
00127 {
00128 void * uh = NULL;
00129 Header h = NULL;
00130 const char ** fileNames;
00131 int fileCount = 0;
00132 int i;
00133
00134 if (offset >= fadGetFileSize(pkgs))
00135 goto exit;
00136
00137 (void)Fseek(pkgs, offset, SEEK_SET);
00138
00139 h = headerRead(pkgs, HEADER_MAGIC_NO);
00140
00141 if (h == NULL)
00142 goto exit;
00143
00144
00145 providePackageNVR(h);
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157 if (!headerGetEntryMinMemory(h, RPMTAG_OLDFILENAMES, NULL,
00158 (const void **) &fileNames, &fileCount)) goto exit;
00159
00160 for (i = 0; i < fileCount; i++)
00161 if (*fileNames[i] != '/') break;
00162
00163 if (i == fileCount) {
00164 free(fileNames);
00165 } else {
00166 const char ** newFileNames = alloca(sizeof(*newFileNames) * fileCount);
00167 for (i = 0; i < fileCount; i++) {
00168 char * newFileName = alloca(strlen(fileNames[i]) + 2);
00169 if (*fileNames[i] != '/') {
00170 newFileName[0] = '/';
00171 newFileName[1] = '\0';
00172 } else
00173 newFileName[0] = '\0';
00174 strcat(newFileName, fileNames[i]);
00175 newFileNames[i] = newFileName;
00176 }
00177
00178 free(fileNames);
00179
00180 headerModifyEntry(h, RPMTAG_OLDFILENAMES, RPM_STRING_ARRAY_TYPE,
00181 newFileNames, fileCount);
00182 }
00183
00184
00185
00186
00187
00188
00189
00190 compressFilelist(h);
00191
00192 exit:
00193 if (h) {
00194 uh = headerUnload(h);
00195 headerFree(h);
00196 }
00197 return uh;
00198 }
00199
00200 static int db1copen( dbiIndex dbi, DBC ** dbcp, unsigned int flags) {
00201
00202 if (flags)
00203 *dbcp = (DBC *)-1;
00204 return 0;
00205 }
00206
00207 static int db1cclose(dbiIndex dbi, DBC * dbcursor, unsigned int flags) {
00208 dbi->dbi_lastoffset = 0;
00209 return 0;
00210 }
00211
00212 static int db1cget(dbiIndex dbi, DBC * dbcursor, void ** keyp,
00213 size_t * keylen, void ** datap, size_t * datalen,
00214 unsigned int flags)
00215 {
00216 DBT key, data;
00217 int rc = 0;
00218
00219 if (dbi == NULL)
00220 return EFAULT;
00221
00222 memset(&key, 0, sizeof(key));
00223 memset(&data, 0, sizeof(data));
00224 if (keyp) key.data = *keyp;
00225 if (keylen) key.size = *keylen;
00226 if (datap) data.data = *datap;
00227 if (datalen) data.size = *datalen;
00228
00229 if (dbi->dbi_rpmtag == RPMDBI_PACKAGES) {
00230 FD_t pkgs = dbi->dbi_db;
00231 unsigned int offset;
00232 unsigned int newSize;
00233
00234 if (key.data == NULL) {
00235 if (dbi->dbi_lastoffset == 0) {
00236 dbi->dbi_lastoffset = fadFirstOffset(pkgs);
00237 } else {
00238 dbi->dbi_lastoffset = fadNextOffset(pkgs, dbi->dbi_lastoffset);
00239 }
00240 key.data = &dbi->dbi_lastoffset;
00241 key.size = sizeof(dbi->dbi_lastoffset);
00242 }
00243
00244 memcpy(&offset, key.data, sizeof(offset));
00245
00246 newSize = data.size;
00247
00248 if (offset == 0) {
00249 offset = fadAlloc(pkgs, newSize);
00250 if (offset == 0)
00251 return ENOMEM;
00252 offset--;
00253
00254 data.data = xmalloc(sizeof(offset));
00255 memcpy(data.data, &offset, sizeof(offset));
00256 data.size = sizeof(offset);
00257 } else {
00258 data.data = doGetRecord(pkgs, offset);
00259 data.size = 0;
00260 if (data.data == NULL)
00261 rc = EFAULT;
00262 }
00263 } else {
00264 DB * db;
00265 int _printit;
00266
00267 if ((db = dbi->dbi_db) == NULL)
00268 return EFAULT;
00269
00270 if (key.data == NULL) {
00271 rc = db->seq(db, &key, &data, (dbi->dbi_lastoffset++ ? R_NEXT : R_FIRST));
00272 _printit = (rc == 1 ? 0 : _debug);
00273 rc = cvtdberr(dbi, "db->seq", rc, _printit);
00274 } else {
00275 rc = db->get(db, &key, &data, 0);
00276 _printit = (rc == 1 ? 0 : _debug);
00277 rc = cvtdberr(dbi, "db1cget", rc, _printit);
00278 }
00279 }
00280
00281 if (rc == 0) {
00282 if (keyp) *keyp = key.data;
00283 if (keylen) *keylen = key.size;
00284 if (datap) *datap = data.data;
00285 if (datalen) *datalen = data.size;
00286 }
00287
00288 return rc;
00289 }
00290
00291 static int db1cdel(dbiIndex dbi, DBC * dbcursor, const void * keyp,
00292 size_t keylen, unsigned int flags)
00293 {
00294 int rc = 0;
00295
00296 if (dbi->dbi_rpmtag == RPMDBI_PACKAGES) {
00297 FD_t pkgs = dbi->dbi_db;
00298 unsigned int offset;
00299 memcpy(&offset, keyp, sizeof(offset));
00300 fadFree(pkgs, offset);
00301 } else {
00302 DBT key;
00303 DB * db = dbi->dbi_db;
00304
00305 _mymemset(&key, 0, sizeof(key));
00306
00307 key.data = (void *)keyp;
00308 key.size = keylen;
00309
00310 rc = db->del(db, &key, 0);
00311 rc = cvtdberr(dbi, "db->del", rc, _debug);
00312 }
00313
00314 return rc;
00315 }
00316
00317 static int db1cput(dbiIndex dbi, DBC * dbcursor,
00318 const void * keyp, size_t keylen,
00319 const void * datap, size_t datalen,
00320 unsigned int flags)
00321 {
00322 DBT key, data;
00323 int rc = 0;
00324
00325 memset(&key, 0, sizeof(key));
00326 memset(&data, 0, sizeof(data));
00327 key.data = (void *)keyp;
00328 key.size = keylen;
00329 data.data = (void *)datap;
00330 data.size = datalen;
00331
00332 if (dbi->dbi_rpmtag == RPMDBI_PACKAGES) {
00333 FD_t pkgs = dbi->dbi_db;
00334 unsigned int offset;
00335
00336 memcpy(&offset, key.data, sizeof(offset));
00337
00338 if (offset == 0) {
00339
00340 if (data.size == sizeof(offset)) {
00341 free(data.data);
00342 }
00343 } else {
00344 Header h = headerLoad(data.data);
00345 int newSize = headerSizeof(h, HEADER_MAGIC_NO);
00346
00347 (void)Fseek(pkgs, offset, SEEK_SET);
00348 fdSetContentLength(pkgs, newSize);
00349 rc = headerWrite(pkgs, h, HEADER_MAGIC_NO);
00350 fdSetContentLength(pkgs, -1);
00351 if (rc)
00352 rc = EIO;
00353 headerFree(h);
00354 }
00355 } else {
00356 DB * db = dbi->dbi_db;
00357
00358 rc = db->put(db, &key, &data, 0);
00359 rc = cvtdberr(dbi, "db->put", rc, _debug);
00360 }
00361
00362 return rc;
00363 }
00364
00365 static int db1close( dbiIndex dbi, unsigned int flags)
00366 {
00367 rpmdb rpmdb = dbi->dbi_rpmdb;
00368 const char * base = db1basename(dbi->dbi_rpmtag);
00369 const char * urlfn = rpmGenPath(rpmdb->db_root, rpmdb->db_home, base);
00370 const char * fn;
00371 int rc = 0;
00372
00373 (void) urlPath(urlfn, &fn);
00374
00375 if (dbi->dbi_db) {
00376 if (dbi->dbi_rpmtag == RPMDBI_PACKAGES) {
00377 FD_t pkgs = dbi->dbi_db;
00378 rc = Fclose(pkgs);
00379 } else {
00380 DB * db = dbi->dbi_db;
00381 rc = db->close(db);
00382 rc = cvtdberr(dbi, "db->close", rc, _debug);
00383 }
00384 dbi->dbi_db = NULL;
00385 }
00386
00387 rpmMessage(RPMMESS_DEBUG, _("closed db file %s\n"), urlfn);
00388
00389 if (dbi->dbi_temporary) {
00390 rpmMessage(RPMMESS_DEBUG, _("removed db file %s\n"), urlfn);
00391 (void) unlink(fn);
00392 }
00393
00394 db3Free(dbi);
00395 if (base)
00396 free((void *)base);
00397 if (urlfn)
00398 free((void *)urlfn);
00399 return rc;
00400 }
00401
00402 static int db1open(rpmdb rpmdb, int rpmtag, dbiIndex * dbip)
00403 {
00404 const char * base = NULL;
00405 const char * urlfn = NULL;
00406 const char * fn = NULL;
00407 dbiIndex dbi = NULL;
00408 extern struct _dbiVec db1vec;
00409 int rc = 0;
00410
00411 if (dbip)
00412 *dbip = NULL;
00413 if ((dbi = db3New(rpmdb, rpmtag)) == NULL)
00414 return EFAULT;
00415 dbi->dbi_api = DB_VERSION_MAJOR;
00416
00417 base = db1basename(rpmtag);
00418 urlfn = rpmGenPath(rpmdb->db_root, rpmdb->db_home, base);
00419 (void) urlPath(urlfn, &fn);
00420 if (!(fn && *fn != '\0')) {
00421 rpmError(RPMERR_DBOPEN, _("bad db file %s\n"), urlfn);
00422 rc = EFAULT;
00423 goto exit;
00424 }
00425
00426 rpmMessage(RPMMESS_DEBUG, _("opening db file %s mode 0x%x\n"),
00427 urlfn, dbi->dbi_mode);
00428
00429 if (dbi->dbi_rpmtag == RPMDBI_PACKAGES) {
00430 FD_t pkgs;
00431
00432 pkgs = fadOpen(fn, dbi->dbi_mode, dbi->dbi_perms);
00433 if (Ferror(pkgs)) {
00434 rc = errno;
00435 goto exit;
00436 }
00437
00438
00439 if (dbi->dbi_lockdbfd || (dbi->dbi_eflags & 0x30)) {
00440 struct flock l;
00441
00442 l.l_whence = 0;
00443 l.l_start = 0;
00444 l.l_len = 0;
00445 l.l_type = (dbi->dbi_mode & O_RDWR) ? F_WRLCK : F_RDLCK;
00446
00447 if (Fcntl(pkgs, F_SETLK, (void *) &l)) {
00448 rc = errno;
00449 rpmError(RPMERR_FLOCK, _("cannot get %s lock on database\n"),
00450 ((dbi->dbi_mode & O_RDWR) ? _("exclusive") : _("shared")));
00451 goto exit;
00452 }
00453 }
00454
00455 dbi->dbi_db = pkgs;
00456 } else {
00457 void * dbopeninfo = NULL;
00458 int dbimode = dbi->dbi_mode;
00459
00460 if (dbi->dbi_temporary)
00461 dbimode |= (O_CREAT | O_RDWR);
00462
00463 dbi->dbi_db = dbopen(fn, dbimode, dbi->dbi_perms,
00464 db3_to_dbtype(dbi->dbi_type), dbopeninfo);
00465 if (dbi->dbi_db == NULL) rc = errno;
00466 }
00467
00468 exit:
00469 if (rc == 0 && dbi->dbi_db != NULL && dbip) {
00470 dbi->dbi_vec = &db1vec;
00471 *dbip = dbi;
00472 } else
00473 db1close(dbi, 0);
00474
00475 if (base) {
00476 free((void *)base);
00477 base = NULL;
00478 }
00479 if (urlfn) {
00480 free((void *)urlfn);
00481 urlfn = NULL;
00482 }
00483
00484 return rc;
00485 }
00486
00489 struct _dbiVec db1vec = {
00490 DB_VERSION_MAJOR, DB_VERSION_MINOR, DB_VERSION_PATCH,
00491 db1open, db1close, db1sync, db1copen, db1cclose, db1cdel, db1cget, db1cput,
00492 db1byteswapped
00493 };