一. mkimage.sh
1. android目录下的mkimage.sh
2. mkbootfs分析
mkbootfs在system/core/cpio/mkbootfs.c中
mkbootfs $OUT
/root
main
--> archive(*argv, x); //*argv 要打包的源文件路径, x是打包后的文件路径
--> _archive_dir(in, out, strlen(in), strlen(out)); //in要打包的源文件路径, out是打包后的文件路径
-
static void _archive_dir(char *in, char *out, int ilen, int olen)
-
{
-
int i, t;
-
DIR *d;
-
struct dirent *de;
-
DIR* d = opendir(in); //打开目录
-
-
int size = 32;
-
int entries = 0;
-
char** names = malloc(size * sizeof(char*)); //每次分配32个文件名的内存
-
//将./out/target/product/rk30sdk/root目录下所有的文件名存在name数组中
-
while((de = readdir(d)) != 0){
-
if(de->d_name[0] == '.') continue; //跳过.目录
-
if(!strcmp(de->d_name, "root")) continue; //排除root,这是为了什么?
-
if (entries >= size) {
-
size *= 2; //如果超出32个文件名,则再多分配32*2个,依次类推
-
names = realloc(names, size * sizeof(char*)); //realloc,又学习了一招
-
}
-
names[entries] = strdup(de->d_name); //strdup可以分配内存并复制
-
++entries;
-
}
-
//对name数组中的文件名进行排序
-
qsort(names, entries, sizeof(char*), compare);
-
-
for (i = 0; i < entries; ++i) {
-
t = strlen(names[i]);
-
in[ilen] = '/';
-
memcpy(in + ilen + 1, names[i], t + 1);
-
-
if(olen > 0) { //out为空
-
out[olen] = '/';
-
memcpy(out + olen + 1, names[i], t + 1);
-
_archive(in, out, ilen + t + 1, olen + t + 1);
-
} else {
-
memcpy(out, names[i], t + 1); //将文件名复制到out中
-
_archive(in, out, ilen + t + 1, t); //将这个文件打包到ramdisk.img中
-
}
-
-
in[ilen] = 0;
-
out[olen] = 0;
-
-
free(names[i]);
-
}
-
free(names);
-
}
mkbootfs $OUT
/root
main
--> archive(*argv, x); //*argv 要打包的源文件路径, x是打包后的文件路径
--> _archive_dir(in, out, strlen(in), strlen(out)); //in要打包的源文件路径, out是打包后的文件路径
--> _archive //对普通文件 目录 链接分开处理
-
static void _archive(char *in, char *out, int ilen, int olen)
-
{
-
struct stat s;
-
if(S_ISREG(s.st_mode)){ //1.对普通文件的处理
-
int fd = open(in, O_RDONLY);
-
char* tmp = (char*) malloc(s.st_size);
-
read(fd, tmp, s.st_size);
-
_eject(&s, out, olen, tmp, s.st_size);
-
free(tmp);
-
close(fd);
-
} else if(S_ISDIR(s.st_mode)) { //2.对目录的处理
-
_eject(&s, out, olen, 0, 0);
-
_archive_dir(in, out, ilen, olen);
-
} else if(S_ISLNK(s.st_mode)) { //3.对链接文件的处理
-
char buf[1024];
-
int size;
-
size = readlink(in, buf, 1024); //调用readlink读符号链接的大小及内容
-
_eject(&s, out, olen, buf, size);
-
} else {
-
die("Unknown '%s' (mode %d)?\n", in, s.st_mode);
-
}
-
}
注: 符号链接
假设有这样的符号连接
ln -s /home/cong/Desktop/record.txt link
则调用readlink后,buf="/home/cong/Desktop/record.txt", size=sizeof("/home/cong/Desktop/record.txt");
即realink所读到的就是link所指向的路径的内容及长度
函数的作用是:把文件的信息与文件的内容写到ramdisk.img中去
mkbootfs $OUT
/root
main
--> archive(*argv, x); //*argv 要打包的源文件路径, x是打包后的文件路径
--> _archive_dir(in, out, strlen(in), strlen(out)); //in要打包的源文件路径, out是打包后的文件路径
--> _archive //对普通文件 目录 链接分开处理
--> _eject //将文件信息与内容写入到ramdisk.img中去
-
static void _eject(struct stat *s, char *out, int olen, char *data, unsigned datasize)
-
{
-
static unsigned next_inode = 300000;
-
-
while(total_size & 3) {
-
total_size++;
-
putchar(0);
-
}
-
-
fix_stat(out, s);
-
//这儿的printf实际上是要写入到ramdisk.img中去的
-
printf("%06x%08x%08x%08x%08x%08x%08x"
-
"%08x%08x%08x%08x%08x%08x%08x%s%c",
-
0x070701, <<<<--- 标志
-
next_inode++, // s.st_ino, //inode_number
-
s->st_mode, //mode
-
0, // s.st_uid, //uid
-
0, // s.st_gid, //gid
-
1, // s.st_nlink, //链接数
-
0, // s.st_mtime, //最后修改时间
-
datasize, //文件长度
-
0, // volmajor //主号
-
0, // volminor //次号
-
0, // devmajor //主设备号
-
0, // devminor, //次设备号
-
olen + 1, //name_len名字长度
-
0, --->>>>
-
out,
-
0
-
);
-
-
total_size += 6 + 8*13 + olen + 1;
-
-
-
while(total_size & 3) {
-
total_size++;
-
putchar(0);
-
}
-
-
if(datasize) {
-
fwrite(data, datasize, 1, stdout); //这是文件的内容
-
total_size += datasize;
-
}
-
}
最后写入一个结束标志:
-
static void _eject_trailer()
-
{
-
struct stat s;
-
memset(&s, 0, sizeof(s));
-
_eject(&s, "TRAILER!!!", 10, 0, 0);
-
-
while(total_size & 0xff) {
-
total_size++;
-
putchar(0);
-
}
-
}
注: CPIO 的结构包括:
110字节的Head(6
+ 8
*13)
不定长的文件名(文件名的长度是olen)
结束字符 \0
文件的内容
.... //重复上面4个
最后的文件名是一个 TRAILER!!!
附1. ramdisk.img的解压过程
-
cong@ubuntu:/tmp/test$ file ./bak/ramdisk.img
-
./bak/ramdisk.img: gzip compressed data, from Unix
-
cong@ubuntu:/tmp/test$ cp ./bak/ramdisk.img ./bak/ramdisk.img_bak.gz //重新copy一份
-
cong@ubuntu:/tmp/test$ gunzip ./bak/ramdisk.img_bak.gz //gunzip解压缩
-
cong@ubuntu:/tmp/test$ ls ./bak/
-
ramdisk.img ramdisk.img_bak ramdisk.img.gz
-
cong@ubuntu:/tmp/test$ file ./bak/ramdisk.img_bak //解压后的文件就是cpio格式的
-
./bak/ramdisk.img_bak: ASCII cpio archive (SVR4 with no CRC)
-
cong@ubuntu:/tmp/test$ cpio -i -F ./bak/ramdisk.img_bak //解压cpio格式
-
463 blocks
-
cong@ubuntu:/tmp/test$ ls //这就能看到所有文件了
-
bak data default.prop dev forlinx.rc init init.goldfish.rc init.rc linuxrc proc sbin sys system ueventd.goldfish.rc ueventd.rc
-
cong@ubuntu:/tmp/test$
阅读(7663) | 评论(0) | 转发(1) |