tools/convertdb1.c

Go to the documentation of this file.
00001 #if defined(HAVE_CONFIG_H)
00002 #include "system.h"
00003 const char *__progname;
00004 #else
00005 #include <sys/types.h>
00006 #include <fcntl.h>
00007 #include <string.h>
00008 #endif
00009 
00010 #include <rpmlib.h>
00011 #include <rpmdb.h>
00012 #include <rpmio.h>
00013 #include <rpmmacro.h>
00014 #include "legacy.h"
00015 
00016 #define FA_MAGIC      0x02050920
00017 
00018 struct faFileHeader{
00019     unsigned int magic;
00020     unsigned int firstFree;
00021 };
00022 
00023 struct faHeader {
00024     unsigned int size;                          
00025     unsigned int freeNext; /* offset of the next free block, 0 if none */
00026     unsigned int freePrev; 
00027     unsigned int isFree;
00028 
00029     /* note that the u16's appear last for alignment/space reasons */
00030 };
00031 
00032 
00033 static int fadFileSize;
00034 
00035 static ssize_t Pread(FD_t fd, void * buf, size_t count, off_t offset) {
00036     if (Fseek(fd, offset, SEEK_SET) < 0)
00037         return -1;
00038     return Fread(buf, sizeof(char), count, fd);
00039 }
00040 
00041 static FD_t fadOpen(const char * path)
00042 {
00043     struct faFileHeader newHdr;
00044     FD_t fd;
00045     struct stat stb;
00046 
00047     fd = Fopen(path, "r.fdio");
00048     if (!fd || Ferror(fd))
00049         return NULL;
00050 
00051     if (fstat(Fileno(fd), &stb)) {
00052         Fclose(fd);
00053         return NULL;
00054     }
00055     fadFileSize = stb.st_size;
00056 
00057     /* is this file brand new? */
00058     if (fadFileSize == 0) {
00059         Fclose(fd);
00060         return NULL;
00061     }
00062     if (Pread(fd, &newHdr, sizeof(newHdr), 0) != sizeof(newHdr)) {
00063         Fclose(fd);
00064         return NULL;
00065     }
00066     if (newHdr.magic != FA_MAGIC) {
00067         Fclose(fd);
00068         return NULL;
00069     }
00070     /*@-refcounttrans@*/ return fd /*@=refcounttrans@*/ ;
00071 }
00072 
00073 static int fadNextOffset(FD_t fd, unsigned int lastOffset)
00074 {
00075     struct faHeader header;
00076     int offset;
00077 
00078     offset = (lastOffset)
00079         ? (lastOffset - sizeof(header))
00080         : sizeof(struct faFileHeader);
00081 
00082     if (offset >= fadFileSize)
00083         return 0;
00084 
00085     if (Pread(fd, &header, sizeof(header), offset) != sizeof(header))
00086         return 0;
00087 
00088     if (!lastOffset && !header.isFree)
00089         return (offset + sizeof(header));
00090 
00091     do {
00092         offset += header.size;
00093 
00094         if (Pread(fd, &header, sizeof(header), offset) != sizeof(header))
00095             return 0;
00096 
00097         if (!header.isFree) break;
00098     } while (offset < fadFileSize && header.isFree);
00099 
00100     if (offset < fadFileSize) {
00101         /* Sanity check this to make sure we're not going in loops */
00102         offset += sizeof(header);
00103 
00104         if (offset <= lastOffset) return -1;
00105 
00106         return offset;
00107     } else
00108         return 0;
00109 }
00110 
00111 static int fadFirstOffset(FD_t fd)
00112 {
00113     return fadNextOffset(fd, 0);
00114 }
00115 
00116 /*@-boundsread@*/
00117 static int dncmp(const void * a, const void * b)
00118         /*@*/
00119 {
00120     const char *const * first = a;
00121     const char *const * second = b;
00122     return strcmp(*first, *second);
00123 }
00124 /*@=boundsread@*/
00125 
00126 /*@-bounds@*/
00127 static void compressFilelist(Header h)
00128         /*@*/
00129 {
00130     HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00131     HAE_t hae = (HAE_t)headerAddEntry;
00132     HRE_t hre = (HRE_t)headerRemoveEntry;
00133     HFD_t hfd = headerFreeData;
00134     char ** fileNames;
00135     const char ** dirNames;
00136     const char ** baseNames;
00137     int_32 * dirIndexes;
00138     rpmTagType fnt;
00139     int count;
00140     int i, xx;
00141     int dirIndex = -1;
00142 
00143     /*
00144      * This assumes the file list is already sorted, and begins with a
00145      * single '/'. That assumption isn't critical, but it makes things go
00146      * a bit faster.
00147      */
00148 
00149     if (headerIsEntry(h, RPMTAG_DIRNAMES)) {
00150         xx = hre(h, RPMTAG_OLDFILENAMES);
00151         return;         /* Already converted. */
00152     }
00153 
00154     if (!hge(h, RPMTAG_OLDFILENAMES, &fnt, (void **) &fileNames, &count))
00155         return;         /* no file list */
00156     if (fileNames == NULL || count <= 0)
00157         return;
00158 
00159     dirNames = alloca(sizeof(*dirNames) * count);       /* worst case */
00160     baseNames = alloca(sizeof(*dirNames) * count);
00161     dirIndexes = alloca(sizeof(*dirIndexes) * count);
00162 
00163     if (fileNames[0][0] != '/') {
00164         /* HACK. Source RPM, so just do things differently */
00165         dirIndex = 0;
00166         dirNames[dirIndex] = "";
00167         for (i = 0; i < count; i++) {
00168             dirIndexes[i] = dirIndex;
00169             baseNames[i] = fileNames[i];
00170         }
00171         goto exit;
00172     }
00173 
00174     /*@-branchstate@*/
00175     for (i = 0; i < count; i++) {
00176         const char ** needle;
00177         char savechar;
00178         char * baseName;
00179         int len;
00180 
00181         if (fileNames[i] == NULL)       /* XXX can't happen */
00182             continue;
00183         baseName = strrchr(fileNames[i], '/') + 1;
00184         len = baseName - fileNames[i];
00185         needle = dirNames;
00186         savechar = *baseName;
00187         *baseName = '\0';
00188 /*@-compdef@*/
00189         if (dirIndex < 0 ||
00190             (needle = bsearch(&fileNames[i], dirNames, dirIndex + 1, sizeof(dirNames[0]), dncmp)) == NULL) {
00191             char *s = alloca(len + 1);
00192             memcpy(s, fileNames[i], len + 1);
00193             s[len] = '\0';
00194             dirIndexes[i] = ++dirIndex;
00195             dirNames[dirIndex] = s;
00196         } else
00197             dirIndexes[i] = needle - dirNames;
00198 /*@=compdef@*/
00199 
00200         *baseName = savechar;
00201         baseNames[i] = baseName;
00202     }
00203     /*@=branchstate@*/
00204 
00205 exit:
00206     if (count > 0) {
00207         xx = hae(h, RPMTAG_DIRINDEXES, RPM_INT32_TYPE, dirIndexes, count);
00208         xx = hae(h, RPMTAG_BASENAMES, RPM_STRING_ARRAY_TYPE,
00209                         baseNames, count);
00210         xx = hae(h, RPMTAG_DIRNAMES, RPM_STRING_ARRAY_TYPE,
00211                         dirNames, dirIndex + 1);
00212     }
00213 
00214     fileNames = hfd(fileNames, fnt);
00215 
00216     xx = hre(h, RPMTAG_OLDFILENAMES);
00217 }
00218 /*@=bounds@*/
00219 
00220 static rpmdb db;
00221 
00222 int
00223 main(int argc, char ** argv)
00224 {
00225   FD_t fd;
00226   int offset;
00227   Header h;
00228   const char *name;
00229   const char *version;
00230   const char *release;
00231 
00232   if (argc != 2)
00233     {
00234       fprintf(stderr, "usage: %s <packages.rpm>\n", argv[0]);
00235       exit(1);
00236     }
00237   if ((fd = fadOpen(argv[1])) == 0)
00238     {
00239       fprintf(stderr, "could not open %s\n", argv[1]);
00240       exit(1);
00241     }
00242   rpmInitMacros(NULL, "/usr/lib/rpm/macros");
00243 
00244   /* speed things up */
00245   (void) rpmDefineMacro(NULL, "_rpmdb_rebuild %{nil}", -1);
00246 
00247   if (rpmdbOpen("/", &db, O_RDWR, 0644)) {
00248     fprintf(stderr, "could not open rpm database\n");
00249     exit(1);
00250   }
00251    
00252   for (offset = fadFirstOffset(fd); offset; offset = fadNextOffset(fd, offset))
00253     {
00254       rpmdbMatchIterator mi;
00255 
00256       /* have to use lseek instead of Fseek because headerRead
00257        * uses low level IO
00258        */
00259       if (lseek(Fileno(fd), (off_t)offset, SEEK_SET) == -1)
00260         {
00261           perror("lseek");
00262           continue;
00263         }
00264       h = headerRead(fd, HEADER_MAGIC_NO);
00265       if (!h)
00266         continue;
00267       compressFilelist(h);
00268       providePackageNVR(h);
00269       headerNVR(h, &name, &version, &release);
00270       mi = rpmdbInitIterator(db, RPMTAG_NAME, name, 0);
00271       rpmdbSetIteratorRE(mi, RPMTAG_VERSION, RPMMIRE_DEFAULT, version);
00272       rpmdbSetIteratorRE(mi, RPMTAG_RELEASE, RPMMIRE_DEFAULT, release);
00273       if (rpmdbNextIterator(mi))
00274         {
00275           printf("%s-%s-%s is already in database\n", name, version, release);
00276           rpmdbFreeIterator(mi);
00277           headerFree(h);
00278           continue;
00279         }
00280       rpmdbFreeIterator(mi);
00281       if (rpmdbAdd(db, -1, h, 0, 0))
00282         {
00283           fprintf(stderr, "could not add %s-%s-%s!\n", name, version, release);
00284         }
00285       headerFree(h);
00286     }
00287   Fclose(fd);
00288   rpmdbClose(db);
00289   return 0;
00290 }
00291 

Generated on Mon Mar 5 13:44:07 2007 for rpm by  doxygen 1.5.1