home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 February / CHIP_2_98.iso / misc / src / rpm / lib / rpmdb.c < prev    next >
C/C++ Source or Header  |  1997-09-17  |  18KB  |  678 lines

  1. #include "config.h"
  2.  
  3. #if HAVE_ALLOCA_H
  4. # include <alloca.h>
  5. #endif
  6.  
  7. #include <fcntl.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <sys/file.h>
  11. #include <signal.h>
  12. #include <sys/signal.h>
  13. #include <unistd.h>
  14.  
  15. #include "dbindex.h"
  16. #include "falloc.h"
  17. #include "header.h"
  18. #include "intl.h"
  19. #include "misc.h"
  20. #include "rpmdb.h"
  21. #include "rpmlib.h"
  22. #include "messages.h"
  23.  
  24. /* XXX the signal handling in here is not thread safe */
  25.  
  26. /* the requiredbyIndex isn't stricly necessary. In a perfect world, we could
  27.    have each header keep a list of packages that need it. However, we
  28.    can't reserve space in the header for extra information so all of the
  29.    required packages would move in the database every time a package was
  30.    added or removed. Instead, each package (or virtual package) name
  31.    keeps a list of package offsets of packages that might depend on this
  32.    one. Version numbers still need verification, but it gets us in the
  33.    right area w/o a linear search through the database. */
  34.  
  35. struct rpmdb_s {
  36.     faFile pkgs;
  37.     dbiIndex * nameIndex, * fileIndex, * groupIndex, * providesIndex;
  38.     dbiIndex * requiredbyIndex, * conflictsIndex;
  39. };
  40.  
  41. static void removeIndexEntry(dbiIndex * dbi, char * name, dbiIndexRecord rec,
  42.                      int tolerant, char * idxName);
  43. static int addIndexEntry(dbiIndex * idx, char * index, unsigned int offset,
  44.                  unsigned int fileNumber);
  45. static void blockSignals(void);
  46. static void unblockSignals(void);
  47.  
  48. static sigset_t signalMask;
  49.  
  50. int rpmdbOpen (char * prefix, rpmdb *rpmdbp, int mode, int perms) {
  51.     char * dbpath;
  52.  
  53.     dbpath = rpmGetVar(RPMVAR_DBPATH);
  54.     if (!dbpath) {
  55.     rpmMessage(RPMMESS_DEBUG, "no dbpath has been set");
  56.     return 1;
  57.     }
  58.  
  59.     return openDatabase(prefix, dbpath, rpmdbp, mode, perms, 0);
  60. }
  61.  
  62. int rpmdbInit (char * prefix, int perms) {
  63.     rpmdb db;
  64.     char * dbpath;
  65.  
  66.     dbpath = rpmGetVar(RPMVAR_DBPATH);
  67.     if (!dbpath) {
  68.     rpmMessage(RPMMESS_DEBUG, "no dbpath has been set");
  69.     return 1;
  70.     }
  71.  
  72.     return openDatabase(prefix, dbpath, &db, O_CREAT | O_RDWR, perms, 1);
  73. }
  74.  
  75. int openDatabase(char * prefix, char * dbpath, rpmdb *rpmdbp, int mode, 
  76.          int perms, int justcheck) {
  77.     char * filename;
  78.     struct rpmdb_s db;
  79.     int i;
  80.     struct flock lockinfo;
  81.  
  82.     i = strlen(dbpath);
  83.     if (dbpath[i - 1] != '/') {
  84.     filename = alloca(i + 2);
  85.     strcpy(filename, dbpath);
  86.     filename[i] = '/';
  87.     filename[i + 1] = '\0';
  88.     dbpath = filename;
  89.     }
  90.     
  91.     filename = alloca(strlen(prefix) + strlen(dbpath) + 40);
  92.  
  93.     if (mode & O_WRONLY) 
  94.     return 1;
  95.  
  96.     strcpy(filename, prefix); 
  97.     strcat(filename, dbpath);
  98.  
  99.     rpmMessage(RPMMESS_DEBUG, "opening database in %s\n", filename);
  100.  
  101.     strcat(filename, "packages.rpm");
  102.  
  103.     memset(&db, 0, sizeof(db));
  104.  
  105.     if (!justcheck || !exists(filename)) {
  106.     db.pkgs = faOpen(filename, mode, 0644);
  107.     if (!db.pkgs) {
  108.         rpmError(RPMERR_DBOPEN, _("failed to open %s\n"), filename);
  109.         return 1;
  110.     }
  111.  
  112.     /* try and get a lock - this is released by the kernel when we close
  113.        the file */
  114.     lockinfo.l_whence = 0;
  115.     lockinfo.l_start = 0;
  116.     lockinfo.l_len = 0;
  117.     
  118.     if (mode & O_RDWR) {
  119.         lockinfo.l_type = F_WRLCK;
  120.         if (fcntl(db.pkgs->fd, F_SETLK, (void *) &lockinfo)) {
  121.         rpmError(RPMERR_FLOCK, _("cannot get %s lock on database"), 
  122.              _("exclusive"));
  123.         return 1;
  124.         } 
  125.     } else {
  126.         lockinfo.l_type = F_RDLCK;
  127.         if (fcntl(db.pkgs->fd, F_SETLK, (void *) &lockinfo)) {
  128.         rpmError(RPMERR_FLOCK, _("cannot get %s lock on database"), 
  129.              _("shared"));
  130.         return 1;
  131.         } 
  132.     }
  133.     }
  134.     
  135.     strcpy(filename, prefix); 
  136.     strcat(filename, dbpath);
  137.     strcat(filename, "nameindex.rpm");
  138.  
  139.     if (!justcheck || !exists(filename)) {
  140.     db.nameIndex = dbiOpenIndex(filename, mode, 0644);
  141.     if (!db.nameIndex) {
  142.         faClose(db.pkgs);
  143.         return 1;
  144.     }
  145.     }
  146.  
  147.     strcpy(filename, prefix); 
  148.     strcat(filename, dbpath);
  149.     strcat(filename, "fileindex.rpm");
  150.  
  151.     if (!justcheck || !exists(filename)) {
  152.     db.fileIndex = dbiOpenIndex(filename, mode, 0644);
  153.     if (!db.fileIndex) {
  154.         faClose(db.pkgs);
  155.         dbiCloseIndex(db.nameIndex);
  156.         return 1;
  157.     }
  158.     }
  159.     
  160.     strcpy(filename, prefix); 
  161.     strcat(filename, dbpath);
  162.     strcat(filename, "groupindex.rpm");
  163.  
  164.     if (!justcheck || !exists(filename)) {
  165.     db.groupIndex = dbiOpenIndex(filename, mode, 0644);
  166.     if (!db.groupIndex) {
  167.         faClose(db.pkgs);
  168.         dbiCloseIndex(db.nameIndex);
  169.         dbiCloseIndex(db.fileIndex);
  170.         return 1;
  171.     }
  172.     }
  173.  
  174.     strcpy(filename, prefix); 
  175.     strcat(filename, dbpath);
  176.     strcat(filename, "providesindex.rpm");
  177.  
  178.     if (!justcheck || !exists(filename)) {
  179.     db.providesIndex = dbiOpenIndex(filename, mode, 0644);
  180.     if (!db.providesIndex) {
  181.         faClose(db.pkgs);
  182.         dbiCloseIndex(db.fileIndex);
  183.         dbiCloseIndex(db.nameIndex);
  184.         dbiCloseIndex(db.groupIndex);
  185.         return 1;
  186.     }
  187.     }
  188.  
  189.     strcpy(filename, prefix); 
  190.     strcat(filename, dbpath);
  191.     strcat(filename, "requiredby.rpm");
  192.  
  193.     if (!justcheck || !exists(filename)) {
  194.     db.requiredbyIndex = dbiOpenIndex(filename, mode, 0644);
  195.     if (!db.requiredbyIndex) {
  196.         faClose(db.pkgs);
  197.         dbiCloseIndex(db.fileIndex);
  198.         dbiCloseIndex(db.nameIndex);
  199.         dbiCloseIndex(db.groupIndex);
  200.         dbiCloseIndex(db.providesIndex);
  201.         return 1;
  202.     }
  203.     }
  204.  
  205.     strcpy(filename, prefix); 
  206.     strcat(filename, dbpath);
  207.     strcat(filename, "conflictsindex.rpm");
  208.  
  209.     if (!justcheck || !exists(filename)) {
  210.     db.conflictsIndex = dbiOpenIndex(filename, mode, 0644);
  211.     if (!db.conflictsIndex) {
  212.         faClose(db.pkgs);
  213.         dbiCloseIndex(db.fileIndex);
  214.         dbiCloseIndex(db.nameIndex);
  215.         dbiCloseIndex(db.groupIndex);
  216.         dbiCloseIndex(db.providesIndex);
  217.         dbiCloseIndex(db.requiredbyIndex);
  218.         return 1;
  219.     }
  220.     }
  221.  
  222.     *rpmdbp = malloc(sizeof(struct rpmdb_s));
  223.     **rpmdbp = db;
  224.  
  225.     if (justcheck) {
  226.     rpmdbClose(*rpmdbp);
  227.     }
  228.  
  229.     return 0;
  230. }
  231.  
  232. void rpmdbClose (rpmdb db) {
  233.     if (db->pkgs) faClose(db->pkgs);
  234.     if (db->fileIndex) dbiCloseIndex(db->fileIndex);
  235.     if (db->groupIndex) dbiCloseIndex(db->groupIndex);
  236.     if (db->nameIndex) dbiCloseIndex(db->nameIndex);
  237.     if (db->providesIndex) dbiCloseIndex(db->providesIndex);
  238.     if (db->requiredbyIndex) dbiCloseIndex(db->requiredbyIndex);
  239.     if (db->conflictsIndex) dbiCloseIndex(db->conflictsIndex);
  240.     free(db);
  241. }
  242.  
  243. int rpmdbFirstRecNum(rpmdb db) {
  244.     return faFirstOffset(db->pkgs);
  245. }
  246.  
  247. int rpmdbNextRecNum(rpmdb db, unsigned int lastOffset) {
  248.     /* 0 at end */
  249.     return faNextOffset(db->pkgs, lastOffset);
  250. }
  251.  
  252. Header rpmdbGetRecord(rpmdb db, unsigned int offset) {
  253.     lseek(db->pkgs->fd, offset, SEEK_SET);
  254.  
  255.     return headerRead(db->pkgs->fd, HEADER_MAGIC_NO);
  256. }
  257.  
  258. int rpmdbFindByFile(rpmdb db, char * filespec, dbiIndexSet * matches) {
  259.     char * fs;
  260.     char * src, * dst;
  261.  
  262.     /* we try and canonicalize the filespec a bit before doing the search */
  263.  
  264.     fs = alloca(strlen(filespec) + 1);
  265.     for (src = filespec, dst = fs; *src; ) { 
  266.     switch (*src) {
  267.       case '/':
  268.         if ((dst == fs) || (*(dst - 1) != '/'))
  269.         *dst++ = *src;
  270.         src++;
  271.         break;
  272.       default:
  273.         *dst++ = *src++;
  274.     }
  275.     }
  276.     *dst-- = '\0';
  277.     if (*dst == '/') *dst = '\0';
  278.  
  279.     return dbiSearchIndex(db->fileIndex, fs, matches);
  280. }
  281.  
  282. int rpmdbFindByProvides(rpmdb db, char * filespec, dbiIndexSet * matches) {
  283.     return dbiSearchIndex(db->providesIndex, filespec, matches);
  284. }
  285.  
  286. int rpmdbFindByRequiredBy(rpmdb db, char * filespec, dbiIndexSet * matches) {
  287.     return dbiSearchIndex(db->requiredbyIndex, filespec, matches);
  288. }
  289.  
  290. int rpmdbFindByConflicts(rpmdb db, char * filespec, dbiIndexSet * matches) {
  291.     return dbiSearchIndex(db->conflictsIndex, filespec, matches);
  292. }
  293.  
  294. int rpmdbFindByGroup(rpmdb db, char * group, dbiIndexSet * matches) {
  295.     return dbiSearchIndex(db->groupIndex, group, matches);
  296. }
  297.  
  298. int rpmdbFindPackage(rpmdb db, char * name, dbiIndexSet * matches) {
  299.     return dbiSearchIndex(db->nameIndex, name, matches);
  300. }
  301.  
  302. static void removeIndexEntry(dbiIndex * dbi, char * key, dbiIndexRecord rec,
  303.                      int tolerant, char * idxName) {
  304.     int rc;
  305.     dbiIndexSet matches;
  306.     
  307.     rc = dbiSearchIndex(dbi, key, &matches);
  308.     switch (rc) {
  309.       case 0:
  310.     if (dbiRemoveIndexRecord(&matches, rec) && !tolerant) {
  311.         rpmError(RPMERR_DBCORRUPT, _("package %s not listed in %s"),
  312.           key, idxName);
  313.     } else {
  314.         dbiUpdateIndex(dbi, key, &matches);
  315.            /* errors from above will be reported from dbindex.c */
  316.     }
  317.  
  318.     dbiFreeIndexRecord(matches);
  319.     break;
  320.       case 1:
  321.     if (!tolerant) 
  322.         rpmError(RPMERR_DBCORRUPT, _("package %s not found in %s"), 
  323.             key, idxName);
  324.     break;
  325.       case 2:
  326.     break;   /* error message already generated from dbindex.c */
  327.     }
  328. }
  329.  
  330. int rpmdbRemove(rpmdb db, unsigned int offset, int tolerant) {
  331.     Header h;
  332.     char * name, * group;
  333.     int type;
  334.     unsigned int count;
  335.     dbiIndexRecord rec;
  336.     char ** fileList, ** providesList, ** requiredbyList;
  337.     char ** conflictList;
  338.     int i;
  339.  
  340.     rec.recOffset = offset;
  341.     rec.fileNumber = 0;
  342.  
  343.     h = rpmdbGetRecord(db, offset);
  344.     if (!h) {
  345.     rpmError(RPMERR_DBCORRUPT, _("cannot read header at %d for uninstall"),
  346.           offset);
  347.     return 1;
  348.     }
  349.  
  350.     blockSignals();
  351.  
  352.     if (!headerGetEntry(h, RPMTAG_NAME, &type, (void **) &name, &count)) {
  353.     rpmError(RPMERR_DBCORRUPT, _("package has no name"));
  354.     } else {
  355.     rpmMessage(RPMMESS_DEBUG, "removing name index\n");
  356.     removeIndexEntry(db->nameIndex, name, rec, tolerant, "name index");
  357.     }
  358.  
  359.     if (!headerGetEntry(h, RPMTAG_GROUP, &type, (void **) &group, &count)) {
  360.     rpmMessage(RPMMESS_DEBUG, "package has no group\n");
  361.     } else {
  362.     rpmMessage(RPMMESS_DEBUG, "removing group index\n");
  363.     removeIndexEntry(db->groupIndex, group, rec, tolerant, "group index");
  364.     }
  365.  
  366.     if (headerGetEntry(h, RPMTAG_PROVIDES, &type, (void **) &providesList, 
  367.      &count)) {
  368.     for (i = 0; i < count; i++) {
  369.         rpmMessage(RPMMESS_DEBUG, "removing provides index for %s\n", 
  370.             providesList[i]);
  371.         removeIndexEntry(db->providesIndex, providesList[i], rec, tolerant, 
  372.                  "providesfile index");
  373.     }
  374.     free(providesList);
  375.     }
  376.  
  377.     if (headerGetEntry(h, RPMTAG_REQUIRENAME, &type, (void **) &requiredbyList, 
  378.      &count)) {
  379.     for (i = 0; i < count; i++) {
  380.         rpmMessage(RPMMESS_DEBUG, "removing requiredby index for %s\n", 
  381.             requiredbyList[i]);
  382.         removeIndexEntry(db->requiredbyIndex, requiredbyList[i], rec, 
  383.                  tolerant, "requiredby index");
  384.     }
  385.     free(requiredbyList);
  386.     }
  387.  
  388.     if (headerGetEntry(h, RPMTAG_CONFLICTNAME, &type, (void **) &conflictList, 
  389.      &count)) {
  390.     for (i = 0; i < count; i++) {
  391.         rpmMessage(RPMMESS_DEBUG, "removing conflict index for %s\n", 
  392.             conflictList[i]);
  393.         removeIndexEntry(db->conflictsIndex, conflictList[i], rec, 
  394.                  tolerant, "conflict index");
  395.     }
  396.     free(conflictList);
  397.     }
  398.  
  399.     if (headerGetEntry(h, RPMTAG_FILENAMES, &type, (void **) &fileList, 
  400.      &count)) {
  401.     for (i = 0; i < count; i++) {
  402.         rpmMessage(RPMMESS_DEBUG, "removing file index for %s\n", fileList[i]);
  403.         rec.fileNumber = i;
  404.         removeIndexEntry(db->fileIndex, fileList[i], rec, tolerant, 
  405.                  "file index");
  406.     }
  407.     free(fileList);
  408.     } else {
  409.     rpmMessage(RPMMESS_DEBUG, "package has no files\n");
  410.     }
  411.  
  412.     faFree(db->pkgs, offset);
  413.  
  414.     dbiSyncIndex(db->nameIndex);
  415.     dbiSyncIndex(db->groupIndex);
  416.     dbiSyncIndex(db->fileIndex);
  417.  
  418.     unblockSignals();
  419.  
  420.     headerFree(h);
  421.  
  422.     return 0;
  423. }
  424.  
  425. static int addIndexEntry(dbiIndex * idx, char * index, unsigned int offset,
  426.                  unsigned int fileNumber) {
  427.     dbiIndexSet set;
  428.     dbiIndexRecord irec;   
  429.     int rc;
  430.  
  431.     irec.recOffset = offset;
  432.     irec.fileNumber = fileNumber;
  433.  
  434.     rc = dbiSearchIndex(idx, index, &set);
  435.     if (rc == -1)          /* error */
  436.     return 1;
  437.  
  438.     if (rc == 1)          /* new item */
  439.     set = dbiCreateIndexRecord();
  440.     dbiAppendIndexRecord(&set, irec);
  441.     if (dbiUpdateIndex(idx, index, &set))
  442.     exit(1);
  443.     dbiFreeIndexRecord(set);
  444.     return 0;
  445. }
  446.  
  447. int rpmdbAdd(rpmdb db, Header dbentry) {
  448.     unsigned int dboffset;
  449.     unsigned int i;
  450.     char ** fileList;
  451.     char ** providesList;
  452.     char ** requiredbyList;
  453.     char ** conflictList;
  454.     char * name, * group;
  455.     int count, providesCount, requiredbyCount, conflictCount;
  456.     int type;
  457.     int rc = 0;
  458.  
  459.     headerGetEntry(dbentry, RPMTAG_NAME, &type, (void **) &name, &count);
  460.     headerGetEntry(dbentry, RPMTAG_GROUP, &type, (void **) &group, &count);
  461.  
  462.     if (!group) group = "Unknown";
  463.  
  464.     if (!headerGetEntry(dbentry, RPMTAG_FILENAMES, &type, (void **) &fileList, 
  465.      &count)) {
  466.     count = 0;
  467.     } 
  468.  
  469.     if (!headerGetEntry(dbentry, RPMTAG_PROVIDES, &type, (void **) &providesList, 
  470.      &providesCount)) {
  471.     providesCount = 0;
  472.     } 
  473.  
  474.     if (!headerGetEntry(dbentry, RPMTAG_REQUIRENAME, &type, 
  475.           (void **) &requiredbyList, &requiredbyCount)) {
  476.     requiredbyCount = 0;
  477.     } 
  478.  
  479.     if (!headerGetEntry(dbentry, RPMTAG_CONFLICTNAME, &type, 
  480.           (void **) &conflictList, &conflictCount)) {
  481.     conflictCount = 0;
  482.     } 
  483.  
  484.     blockSignals();
  485.  
  486.     dboffset = faAlloc(db->pkgs, headerSizeof(dbentry, HEADER_MAGIC_NO));
  487.     if (!dboffset) {
  488.     rpmError(RPMERR_DBCORRUPT, _("cannot allocate space for database"));
  489.     unblockSignals();
  490.     if (providesCount) free(providesList);
  491.     if (requiredbyCount) free(requiredbyList);
  492.     if (count) free(fileList);
  493.     return 1;
  494.     }
  495.     lseek(db->pkgs->fd, dboffset, SEEK_SET);
  496.  
  497.     headerWrite(db->pkgs->fd, dbentry, HEADER_MAGIC_NO);
  498.  
  499.     /* Now update the appropriate indexes */
  500.     if (addIndexEntry(db->nameIndex, name, dboffset, 0))
  501.     rc = 1;
  502.     if (addIndexEntry(db->groupIndex, group, dboffset, 0))
  503.     rc = 1;
  504.  
  505.     for (i = 0; i < conflictCount; i++) {
  506.     if (addIndexEntry(db->conflictsIndex, conflictList[i], dboffset, 0))
  507.         rc = 1;
  508.     }
  509.  
  510.     for (i = 0; i < requiredbyCount; i++) {
  511.     if (addIndexEntry(db->requiredbyIndex, requiredbyList[i], dboffset, 0))
  512.         rc = 1;
  513.     }
  514.  
  515.     for (i = 0; i < providesCount; i++) {
  516.     if (addIndexEntry(db->providesIndex, providesList[i], dboffset, 0))
  517.         rc = 1;
  518.     }
  519.  
  520.     for (i = 0; i < count; i++) {
  521.     if (addIndexEntry(db->fileIndex, fileList[i], dboffset, i))
  522.         rc = 1;
  523.     }
  524.  
  525.     dbiSyncIndex(db->nameIndex);
  526.     dbiSyncIndex(db->groupIndex);
  527.     dbiSyncIndex(db->fileIndex);
  528.     dbiSyncIndex(db->providesIndex);
  529.     dbiSyncIndex(db->requiredbyIndex);
  530.  
  531.     unblockSignals();
  532.  
  533.     if (requiredbyCount) free(requiredbyList);
  534.     if (providesCount) free(providesList);
  535.     if (count) free(fileList);
  536.  
  537.     return rc;
  538. }
  539.  
  540. int rpmdbUpdateRecord(rpmdb db, int offset, Header newHeader) {
  541.     Header oldHeader;
  542.     int oldSize;
  543.  
  544.     oldHeader = rpmdbGetRecord(db, offset);
  545.     if (!oldHeader) {
  546.     rpmError(RPMERR_DBCORRUPT, _("cannot read header at %d for update"),
  547.         offset);
  548.     return 1;
  549.     }
  550.  
  551.     oldSize = headerSizeof(oldHeader, HEADER_MAGIC_NO);
  552.     headerFree(oldHeader);
  553.  
  554.     if (oldSize != headerSizeof(newHeader, HEADER_MAGIC_NO)) {
  555.     rpmMessage(RPMMESS_DEBUG, "header changed size!");
  556.     if (rpmdbRemove(db, offset, 1))
  557.         return 1;
  558.  
  559.     if (rpmdbAdd(db, newHeader)) 
  560.         return 1;
  561.     } else {
  562.     blockSignals();
  563.  
  564.     lseek(db->pkgs->fd, offset, SEEK_SET);
  565.  
  566.     headerWrite(db->pkgs->fd, newHeader, HEADER_MAGIC_NO);
  567.  
  568.     unblockSignals();
  569.     }
  570.  
  571.     return 0;
  572. }
  573.  
  574. static void blockSignals(void) {
  575.     sigset_t newMask;
  576.  
  577.     sigfillset(&newMask);        /* block all signals */
  578.     sigprocmask(SIG_BLOCK, &newMask, &signalMask);
  579. }
  580.  
  581. static void unblockSignals(void) {
  582.     sigprocmask(SIG_SETMASK, &signalMask, NULL);
  583. }
  584.  
  585. void rpmdbRemoveDatabase(char * rootdir, char * dbpath) { 
  586.     int i;
  587.     char * filename;
  588.  
  589.     i = strlen(dbpath);
  590.     if (dbpath[i - 1] != '/') {
  591.     filename = alloca(i);
  592.     strcpy(filename, dbpath);
  593.     filename[i] = '/';
  594.     filename[i + 1] = '\0';
  595.     dbpath = filename;
  596.     }
  597.     
  598.     filename = alloca(strlen(rootdir) + strlen(dbpath) + 40);
  599.  
  600.     sprintf(filename, "%s/%s/packages.rpm", rootdir, dbpath);
  601.     unlink(filename);
  602.  
  603.     sprintf(filename, "%s/%s/nameindex.rpm", rootdir, dbpath);
  604.     unlink(filename);
  605.  
  606.     sprintf(filename, "%s/%s/fileindex.rpm", rootdir, dbpath);
  607.     unlink(filename);
  608.  
  609.     sprintf(filename, "%s/%s/groupindex.rpm", rootdir, dbpath);
  610.     unlink(filename);
  611.  
  612.     sprintf(filename, "%s/%s/requiredby.rpm", rootdir, dbpath);
  613.     unlink(filename);
  614.  
  615.     sprintf(filename, "%s/%s/providesindex.rpm", rootdir, dbpath);
  616.     unlink(filename);
  617.  
  618.     sprintf(filename, "%s/%s/conflictsindex.rpm", rootdir, dbpath);
  619.     unlink(filename);
  620. }
  621.  
  622. int rpmdbMoveDatabase(char * rootdir, char * olddbpath, char * newdbpath) {
  623.     int i;
  624.     char * ofilename, * nfilename;
  625.     int rc = 0;
  626.  
  627.     i = strlen(olddbpath);
  628.     if (olddbpath[i - 1] != '/') {
  629.     ofilename = alloca(i + 2);
  630.     strcpy(ofilename, olddbpath);
  631.     ofilename[i] = '/';
  632.     ofilename[i + 1] = '\0';
  633.     olddbpath = ofilename;
  634.     }
  635.     
  636.     i = strlen(newdbpath);
  637.     if (newdbpath[i - 1] != '/') {
  638.     nfilename = alloca(i + 2);
  639.     strcpy(nfilename, newdbpath);
  640.     nfilename[i] = '/';
  641.     nfilename[i + 1] = '\0';
  642.     newdbpath = nfilename;
  643.     }
  644.     
  645.     ofilename = alloca(strlen(rootdir) + strlen(olddbpath) + 40);
  646.     nfilename = alloca(strlen(rootdir) + strlen(newdbpath) + 40);
  647.  
  648.     sprintf(ofilename, "%s/%s/packages.rpm", rootdir, olddbpath);
  649.     sprintf(nfilename, "%s/%s/packages.rpm", rootdir, newdbpath);
  650.     if (rename(ofilename, nfilename)) rc = 1;
  651.  
  652.     sprintf(ofilename, "%s/%s/nameindex.rpm", rootdir, olddbpath);
  653.     sprintf(nfilename, "%s/%s/nameindex.rpm", rootdir, newdbpath);
  654.     if (rename(ofilename, nfilename)) rc = 1;
  655.  
  656.     sprintf(ofilename, "%s/%s/fileindex.rpm", rootdir, olddbpath);
  657.     sprintf(nfilename, "%s/%s/fileindex.rpm", rootdir, newdbpath);
  658.     if (rename(ofilename, nfilename)) rc = 1;
  659.  
  660.     sprintf(ofilename, "%s/%s/groupindex.rpm", rootdir, olddbpath);
  661.     sprintf(nfilename, "%s/%s/groupindex.rpm", rootdir, newdbpath);
  662.     if (rename(ofilename, nfilename)) rc = 1;
  663.  
  664.     sprintf(ofilename, "%s/%s/requiredby.rpm", rootdir, olddbpath);
  665.     sprintf(nfilename, "%s/%s/requiredby.rpm", rootdir, newdbpath);
  666.     if (rename(ofilename, nfilename)) rc = 1;
  667.  
  668.     sprintf(ofilename, "%s/%s/providesindex.rpm", rootdir, olddbpath);
  669.     sprintf(nfilename, "%s/%s/providesindex.rpm", rootdir, newdbpath);
  670.     if (rename(ofilename, nfilename)) rc = 1;
  671.  
  672.     sprintf(ofilename, "%s/%s/conflictsindex.rpm", rootdir, olddbpath);
  673.     sprintf(nfilename, "%s/%s/conflictsindex.rpm", rootdir, newdbpath);
  674.     if (rename(ofilename, nfilename)) rc = 1;
  675.  
  676.     return rc;
  677. }
  678.