笔者基于rpm-devel 开发了一个C程序,用来读取RPM文件的基本信息并打印到标准输出。如果你对前面章节介绍的知识已经理解并掌握了,下面这段代码就比较容易阅读了。
核心代码片段如下:
char * readHeaderString (Header header, int_32 tag_id)
{
int_32 type;
void *pointer;
int_32 data_size;
//获取header中的一个string
int header_status = headerGetEntry (header,
tag_id, &type, &pointer, &data_size);
if (header_status)
{
if (type == RPM_STRING_TYPE)
{
return pointer;
}
}
return NULL;
}
int samplerpm (const char *szrpm)
{
char g_szname[1024] = {0};
FD_t fd = Fopen (szrpm, "r");
memset (g_szname, 0, 1024);
sprintf (g_szname, "%s", szrpm);
fflush (stdin);
fflush (stdout);
if (!fd)
{
printf ("open file '%s' failed\n", szrpm);
return 0;
}
struct rpmlead plead;
int lead = readLead (fd, &plead);//读取lead结构体
if (lead)
{
printf ("readLead of '%s' failed\n", szrpm);
Fclose (fd);
return 0;
}
Header header;
//读取第一个header structure—signature
rpmRC ret = rpmReadSignature (fd, &header, plead.signature_type);
if (ret != RPMRC_OK)
{
printf ("rpmReadSignature of '%s' failed\n", szrpm);
Fclose (fd);
return 0;
}
//读取第一个header structure—header
Header newheader =
headerRead (fd, (plead.major >= 3) HEADER_MAGIC_YES : HEADER_MAGIC_NO);
if (!newheader)
{
printf ("headerRead of '%s' failed\n", szrpm);
Fclose (fd);
return 0;
}
//读取各个TAG
const char *name = readHeaderString (newheader, RPMTAG_NAME);
const char *version = readHeaderString (newheader, RPMTAG_VERSION);
const char *release = readHeaderString (newheader, RPMTAG_RELEASE);
const char *group = readHeaderString (newheader, RPMTAG_GROUP);
const char *packager = readHeaderString (newheader, RPMTAG_PACKAGER);
if (!group) group = "NONE_GROUP";
if (!packager) packager = "NONE_PACKAGER";
printf ("name:%s\nversion:%s\nrelease:%s\ngroup:%s\npackager:%s\n\n",
name, version, release, group, packager);
Fclose (fd);
return 1;
}
可执行程序的编译方法如下:
gcc test.c -I/usr/include/rpm -lrpm -lrpmdb -lrpmio -lpopt -o test_rpm
可以通过以下方法进行测试:
./test_rpm ./mysql-server-5.0.77-4.el5_6.6.x86_64.rpm
输出如下:
name:mysql-server
version:5.0.77
release:4.el5_6.6
group:Applications/Databases
packager:Red Hat, Inc.
可以看到,test_rpm这个程序解析并打印了指定RPM文件的基本信息,读者可以参考文档对该程序进行功能细化。
由于笔者并没阅读rpm命令或者rpmbuild 的源码,因此对RPM格式的剖析只能到此深度,不过rpmbuild的实现应该也是类似的,感兴趣的读者可以参考 RPM 的文档和源码进一步学习。