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;
00026 unsigned int freePrev;
00027 unsigned int isFree;
00028
00029
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
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 return fd ;
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
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
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
00125
00126
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
00145
00146
00147
00148
00149 if (headerIsEntry(h, RPMTAG_DIRNAMES)) {
00150 xx = hre(h, RPMTAG_OLDFILENAMES);
00151 return;
00152 }
00153
00154 if (!hge(h, RPMTAG_OLDFILENAMES, &fnt, (void **) &fileNames, &count))
00155 return;
00156 if (fileNames == NULL || count <= 0)
00157 return;
00158
00159 dirNames = alloca(sizeof(*dirNames) * count);
00160 baseNames = alloca(sizeof(*dirNames) * count);
00161 dirIndexes = alloca(sizeof(*dirIndexes) * count);
00162
00163 if (fileNames[0][0] != '/') {
00164
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
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)
00182 continue;
00183 baseName = strrchr(fileNames[i], '/') + 1;
00184 len = baseName - fileNames[i];
00185 needle = dirNames;
00186 savechar = *baseName;
00187 *baseName = '\0';
00188
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
00199
00200 *baseName = savechar;
00201 baseNames[i] = baseName;
00202 }
00203
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
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
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
00257
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