windows下android打包工具

来源:互联网 发布:宇宙骑士 知乎 编辑:程序博客网 时间:2024/06/07 07:12

windows下android打包工具

  这是我的第一篇博客,以前总想写点什么,但总是迟迟不见行动,会有各种借口来放弃,最近反思自己,这样真的好吗,呵呵,改变从现在开始。

  首先我来说下为什么我要写windows下android打包工具,我们的android4.2项目开发是在windows上的,大家用的是eclipse,各自写好的APK最后交于一人,由他来合成最后的system.img.ext4,然后发于客户升级,合成环境也是在windows上,一开始,我们找到了“ROM助手”这款软件,用来打包apk,以及so,用用还可以,但随着客户的增多,以及其他类型的文件需要打包,这款软件开始出现其弊端,因为需要手工去点击操作,而不是批量化生成,效率比较低而且容易出错,鉴于此我打算写一款工具,用来满足我们的工作需求。

  想过几种方案,最简单的莫过于在Ubuntu上写个脚本,直接用现成的make_ext4fs工具来生成,但我们要求在winddows上,所以排除了,至于为什么不用Ubuntu,那理由很low,就不说了。

  后来想到了cygwin下能编译Linux上的软件,所以将make_ext4fs的源代码拷出,放于cygwin上编译,编译通过,哈哈,竟然能在windows上生成system.img.ext4了,开心了会,但又发现了问题,权限不对,全部变为0755了,而且不支持链接文件,这不符合我们的要求啊,而且要求系统工程师提供的原始system.img.ext4文件已经全部解压开来,汗。发现了问题,那就要解决问题。

   现在需要解决的问题有:

   1.system.img.ext4在windows下解压开来,要求记录链接文件以及权限,uid等信息。

   2. 修改make_ext4fs程序,使之支持读取我们记录下来的权限等信息。

   对于第一个问题,我们知道system.img.ext4其实不是ext4格式的,具体叫什么格式,我也不知道,呵呵,只知道Linux下有个simg2img 工具,可以将system.img.ext4转化为裸的ext4格式的image,暂且就叫system.img.ext4为simg格式吧,这种格式其实就是用一个个的chunk,有CHUNK_TYPE_RAW,CHUNK_TYPE_DONT_CARE类型,CHUNK_TYPE_RAW记录实际的文件数据,CHUNK_TYPE_DONT_CARE记录的是image中的0块,这样就可以实现文件的精简,原理其实和wince的xip格式也差不多,都是为了跳过大块的0区域。

   simg2img 工具的实现可以按照实现make_ext4fs在cygwin实现的方式一样。但我自己又实现了一种简单的转化函数,效果一样,看源码:

// 转化函数bool simg2ext4(char *srcPath, char *desPath){       // 打开文件       HANDLE hFile =CreateFile(srcPath, GENERIC_WRITE|GENERIC_READ,                                                               FILE_SHARE_READ,NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN,                                                               NULL);                                                                     if (hFile ==INVALID_HANDLE_VALUE)       {              printf("%snot exist \r\n", srcPath);              return false;       }             // 得到文件大小       int dwfileSize = GetFileSize(hFile,NULL);       printf("dwfileSize= %d \r\n", dwfileSize);                           // 文件映射       HANDLE hFileMapping =CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);       if (NULL ==hFileMapping)       {              printf("CreateFileMappingerror\r\n");              CloseHandle(hFile);              return false;       }       CloseHandle(hFile);             // 得到文件内存指针       unsigned char*lpbMapAddress = (unsigned char *)MapViewOfFile(hFileMapping, FILE_MAP_READ, 0,0, dwfileSize);        if (lpbMapAddress ==NULL)        {               printf("MapViewOfFileerror \r\n");              return false;       }             //--------------------- 解析文件-----------------------       unsigned intblock_size = 0;       unsigned int chunk_cnt= 0;       unsigned int filelen =dwfileSize;       unsigned char*pfileBuffer = NULL;       unsigned int datalen;       unsigned longu8WriteAddr = 0;       sparse_header_t*ptSparseHeader = NULL;       chunk_header_t  *ptChunkHeader = NULL;             // 1. 获取sparse的头       ptSparseHeader =(sparse_header_t *)lpbMapAddress;       block_size =ptSparseHeader->blk_sz;       chunk_cnt =ptSparseHeader->total_chunks;             printf("ptSparseHeader->blk_sz = 0X%x\r\n", ptSparseHeader->blk_sz);       printf("ptSparseHeader->total_blks = 0X%x\r\n",ptSparseHeader->total_blks);       printf("ptSparseHeader->total_chunks = 0X%x\r\n",ptSparseHeader->total_chunks);             // 2. 内容开始出       pfileBuffer =lpbMapAddress + sizeof(sparse_header_t);       filelen -=sizeof(sparse_header_t);             // 3. 用0填充文件       HANDLE hFileWrite =CreateFile(desPath, GENERIC_WRITE|GENERIC_READ,                                                               FILE_SHARE_READ,NULL, CREATE_ALWAYS, 0, 0);       void *buff =malloc(ptSparseHeader->blk_sz);       memset(buff, 0x00,ptSparseHeader->blk_sz);       unsigned longdwNumberOfBytesWritten;       for (unsigned int i=0;i<ptSparseHeader->total_blks; i++)       {              WriteFile(hFileWrite,buff, ptSparseHeader->blk_sz, &dwNumberOfBytesWritten, 0);       }       free(buff);             // 4. 将数据写入文件       while((chunk_cnt>0) && (filelen>0))       {              ptChunkHeader =(chunk_header_t *)pfileBuffer;              datalen =ptChunkHeader->chunk_sz * block_size;                           printf("ptChunkHeader->chunk_type = %d\r\n",ptChunkHeader->chunk_type);              printf("ptChunkHeader->chunk_sz = 0X%x\r\n",ptChunkHeader->chunk_sz);              printf("datalen = 0X%x\r\n", datalen);               if(CHUNK_TYPE_RAW == ptChunkHeader->chunk_type)              {                     pfileBuffer+= CHUNK_HEADER_LEN;                     SetFilePointer(hFileWrite,u8WriteAddr, 0, FILE_BEGIN);                     WriteFile(hFileWrite,pfileBuffer, datalen, &dwNumberOfBytesWritten, 0);                            filelen-= ptChunkHeader->total_sz;                     chunk_cnt--;                     pfileBuffer+=datalen;                     u8WriteAddr+= datalen;              }              else if(CHUNK_TYPE_DONT_CARE == ptChunkHeader->chunk_type)              {                     u8WriteAddr+= datalen;                     pfileBuffer+= ptChunkHeader->total_sz;                     filelen-= ptChunkHeader->total_sz;                     chunk_cnt--;              }              else              {                     printf("ptChunkHeader->chunk_type error\r\n");                     CloseHandle(hFileWrite);                     DeleteFile(desPath);                     // 撤销文件映像                     UnmapViewOfFile(lpbMapAddress);                     CloseHandle(hFileMapping);                     returnfalse;              }       }             CloseHandle(hFileWrite);       //-------------------- 解析文件结束--------------------        // 撤销文件映像        UnmapViewOfFile(lpbMapAddress);       CloseHandle(hFileMapping);       return true;}


首先是将system.img.ext4文件做文件映射,然后再生成一个全部是0的system.img文件,接着,就一个一个chunk的写入,哈哈,最后转化成功,还是比较简单的。
   我们用simg2img 工具生成system.img,接下来,我们就要实现在windows下读取释放所有system.img中的文件。在github上,我发现了一款人气比较旺的软件ex2read,该软件可以读取system.img的文件信息,已经文件的内容,所以我试着改写其代码,实现文件的读取以及文件信息的保存,其中有点问题的是,ex2read没有实现链接文件的读取,自己实现了下,然后将文件信息写入对应文件夹的linux_files_info.cxj文件中。

// 释放imagebool release_image(Ext2File *dir, char *path){char fileInfo[1024];char fileInfoName[1024];char relasePath[1024];int status;DWORD dWrited;// 创建文件夹memset(relasePath, 0x00, 1024);strcat(relasePath, path);strcat(relasePath, "\\");strcat(relasePath, dir->file_name.c_str());status = mkdir(relasePath);if (status != 0){printf("mkdir %s error \n", relasePath);return false; }   // 读取文件夹 EXT2DIRENT *dir_rent = app->mPartotion->open_dir(dir);// 创建文件属性文件 memset(fileInfoName, 0x00, 1024);strcat(fileInfoName, relasePath);strcat(fileInfoName, "\\linux_files_info.cxj");HANDLE hFileinfo = CreateFileA(fileInfoName, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, 0 );Ext2File *files;while((files = app->mPartotion->read_dir(dir_rent)) != NULL){if (EXT2_S_ISDIR(files->inode.i_mode)){// 将属性写入文件 memset(fileInfo, 0x00, 1024);sprintf(fileInfo, "%s,D,0x%04x,0x%04x,0x%04x\n", files->file_name.c_str(),files->inode.i_mode, files->inode.i_uid, files->inode.i_gid);printf("%s", fileInfo);WriteFile(hFileinfo, fileInfo, strlen(fileInfo), &dWrited, 0);// 文件夹递归 release_image(files, relasePath);}else if (EXT2_S_ISREG(files->inode.i_mode)){// 将属性写入文件 memset(fileInfo, 0x00, 1024);sprintf(fileInfo, "%s,F,0x%04x,0x%04x,0x%04x\n", files->file_name.c_str(),files->inode.i_mode, files->inode.i_uid, files->inode.i_gid);printf("%s", fileInfo);WriteFile(hFileinfo, fileInfo, strlen(fileInfo), &dWrited, 0);// 释放文件 char relaseFile[1024];memset(relaseFile, 0x00, 1024);strcat(relaseFile, relasePath);strcat(relaseFile, "\\");strcat(relaseFile, files->file_name.c_str());copy_file(files, relaseFile);}else if (EXT2_S_ISLINK(files->inode.i_mode)){// 将属性写入文件 memset(fileInfo, 0x00, 1024);sprintf(fileInfo, "%s,L,0x%04x,0x%04x,0x%04x\n", files->file_name.c_str(),files->inode.i_mode, files->inode.i_uid, files->inode.i_gid);printf("%s", fileInfo);WriteFile(hFileinfo, fileInfo, strlen(fileInfo), &dWrited, 0);// 释放链接文件 char relaseFile[1024];memset(relaseFile, 0x00, 1024);strcat(relaseFile, relasePath);strcat(relaseFile, "\\");strcat(relaseFile, files->file_name.c_str());readLinkfile(files, relaseFile);}}// 关闭并保存文件 CloseHandle(hFileinfo);app->mPartotion->close_dir(dir_rent);} // 拷贝文件 bool copy_file(Ext2File *srcfile, char* destfile){DWORD dWrited;lloff_t blocks, blkindex;int ret, extra;int blksize = srcfile->partition->get_blocksize();char *buffer = new char [blksize];HANDLE filetosave = CreateFileA(destfile, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, 0 );//printf("blksize=%d \n", blksize);//printf("file_size=%d \n", srcfile->file_size);blocks = srcfile->file_size / blksize;for (blkindex=0; blkindex<blocks; blkindex++){ret = srcfile->partition->read_data_block(&srcfile->inode, blkindex, buffer);if (ret < 0){CloseHandle(filetosave);printf("read_data_block error \n");return false;}WriteFile(filetosave, buffer, blksize, &dWrited, 0);}extra = srcfile->file_size % blksize;if(extra)  {ret = srcfile->partition->read_data_block(&srcfile->inode, blkindex, buffer);if(ret < 0){CloseHandle(filetosave);printf("read_data_block error \n");return false;}WriteFile(filetosave, buffer, extra, &dWrited, 0);}CloseHandle(filetosave);delete [] buffer;return true;}// 读取软连接文件 bool readLinkfile(Ext2File *srcfile, char* destfile){DWORD dWrited;lloff_t blocks, blkindex;int ret, extra;int blksize = srcfile->partition->get_blocksize();char *buffer = new char [blksize];HANDLE filetosave = CreateFileA(destfile, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, 0 );memcpy(buffer, srcfile->inode.i_block, srcfile->file_size);WriteFile(filetosave, buffer, srcfile->file_size, &dWrited, 0);CloseHandle(filetosave);delete [] buffer;return true;}


这样我们就构建好了文件架构,实现了链接文件的保存已经文件信息的记录。


接下来,我们就要改写make_ext4fs工具了,研究make_ext4fs的源码我们发现,其架构是在build_directory_structure函数中完成的,此函数是递归函数,根据文件夹的目录来分配entry_inode,并且通过链表dentries来记录文件所在的路径,在最后写imag的时候可以打开文件实现文件内容的写入。我们的目标就是改写此函数,用我们的linux_files_info.cxj来构建系统,而不是扫描文件夹,具体见代码
/* Read a local directory and create the same tree in the generated filesystem.   Calls itself recursively with each directory in the given directory */static u32 build_directory_structure(const char *full_path, const char *dir_path,u32 dir_inode, fs_config_func_t fs_config_func,struct selabel_handle *sehnd){// cxj modify#if 0int entries = 0;struct dentry *dentries;struct dirent **namelist = NULL;struct stat stat;int ret;int i;u32 inode;u32 entry_inode;u32 dirs = 0;bool needs_lost_and_found = false;if (full_path) {entries = scandir(full_path, &namelist, filter_dot, (void*)alphasort);if (entries < 0) {error_errno("scandir");return EXT4_ALLOCATE_FAILED;}}if (dir_inode == 0) {/* root directory, check if lost+found already exists */for (i = 0; i < entries; i++)if (strcmp(namelist[i]->d_name, "lost+found") == 0)break;if (i == entries)needs_lost_and_found = true;}dentries = calloc(entries, sizeof(struct dentry));if (dentries == NULL)critical_error_errno("malloc");// cxj addprintf("------------------- \n");for (i = 0; i < entries; i++) {dentries[i].filename = strdup(namelist[i]->d_name);if (dentries[i].filename == NULL)critical_error_errno("strdup");asprintf(&dentries[i].path, "%s/%s", dir_path, namelist[i]->d_name);asprintf(&dentries[i].full_path, "%s/%s", full_path, namelist[i]->d_name);// cxj add//printf("------------------- \n");printf("%s \n", dentries[i].path);printf("%s \n", dentries[i].full_path);free(namelist[i]);ret = lstat(dentries[i].full_path, &stat);if (ret < 0) {error_errno("lstat");i--;entries--;continue;}dentries[i].size = stat.st_size;dentries[i].mode = stat.st_mode & (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO);dentries[i].mtime = stat.st_mtime;if (fs_config_func != NULL) {#ifdef ANDROIDunsigned int mode = 0;unsigned int uid = 0;unsigned int gid = 0;int dir = S_ISDIR(stat.st_mode);fs_config_func(dentries[i].path, dir, &uid, &gid, &mode);dentries[i].mode = mode;dentries[i].uid = uid;dentries[i].gid = gid;#elseerror("can't set android permissions - built without android support");#endif}#ifdef HAVE_SELINUXif (sehnd) {char *sepath = NULL;asprintf(&sepath, "/%s", dentries[i].path);if (selabel_lookup(sehnd, &dentries[i].secon, sepath, stat.st_mode) < 0) {error("cannot lookup security context for %s", sepath);}if (dentries[i].secon)printf("Labeling %s as %s\n", sepath, dentries[i].secon);free(sepath);}#endifif (S_ISREG(stat.st_mode)) {dentries[i].file_type = EXT4_FT_REG_FILE;} else if (S_ISDIR(stat.st_mode)) {dentries[i].file_type = EXT4_FT_DIR;dirs++;} else if (S_ISCHR(stat.st_mode)) {dentries[i].file_type = EXT4_FT_CHRDEV;} else if (S_ISBLK(stat.st_mode)) {dentries[i].file_type = EXT4_FT_BLKDEV;} else if (S_ISFIFO(stat.st_mode)) {dentries[i].file_type = EXT4_FT_FIFO;} else if (S_ISSOCK(stat.st_mode)) {dentries[i].file_type = EXT4_FT_SOCK;} else if (S_ISLNK(stat.st_mode)) {dentries[i].file_type = EXT4_FT_SYMLINK;dentries[i].link = calloc(info.block_size, 1);readlink(dentries[i].full_path, dentries[i].link, info.block_size - 1);} else {error("unknown file type on %s", dentries[i].path);i--;entries--;}}free(namelist);if (needs_lost_and_found) {/* insert a lost+found directory at the beginning of the dentries */struct dentry *tmp = calloc(entries + 1, sizeof(struct dentry));memset(tmp, 0, sizeof(struct dentry));memcpy(tmp + 1, dentries, entries * sizeof(struct dentry));dentries = tmp;dentries[0].filename = strdup("lost+found");asprintf(&dentries[0].path, "%s/lost+found", dir_path);dentries[0].full_path = NULL;dentries[0].size = 0;dentries[0].mode = S_IRWXU;dentries[0].file_type = EXT4_FT_DIR;dentries[0].uid = 0;dentries[0].gid = 0;#ifdef HAVE_SELINUXif (sehnd) {char *sepath = NULL;asprintf(&sepath, "/%s", dentries[0].path);if (selabel_lookup(sehnd, &dentries[0].secon, sepath, dentries[0].mode) < 0)error("cannot lookup security context for %s", dentries[0].path);free(sepath);}#endifentries++;dirs++;}inode = make_directory(dir_inode, entries, dentries, dirs);for (i = 0; i < entries; i++) {if (dentries[i].file_type == EXT4_FT_REG_FILE) {entry_inode = make_file(dentries[i].full_path, dentries[i].size);} else if (dentries[i].file_type == EXT4_FT_DIR) {entry_inode = build_directory_structure(dentries[i].full_path,dentries[i].path, inode, fs_config_func, sehnd);} else if (dentries[i].file_type == EXT4_FT_SYMLINK) {entry_inode = make_link(dentries[i].full_path, dentries[i].link);} else {error("unknown file type on %s", dentries[i].path);entry_inode = 0;}*dentries[i].inode = entry_inode;ret = inode_set_permissions(entry_inode, dentries[i].mode,dentries[i].uid, dentries[i].gid,dentries[i].mtime);if (ret)error("failed to set permissions on %s\n", dentries[i].path);ret = inode_set_selinux(entry_inode, dentries[i].secon);if (ret)error("failed to set SELinux context on %s\n", dentries[i].path);free(dentries[i].path);free(dentries[i].full_path);free(dentries[i].link);free((void *)dentries[i].filename);free(dentries[i].secon);}free(dentries);return inode;#elseint entries = 0;struct dentry *dentries;struct dirent **namelist = NULL;struct stat stat;int ret;int i;u32 inode;u32 entry_inode;u32 dirs = 0;bool needs_lost_and_found = false;char fileInfoName[1024];char *fileContent;int filesize = 0;int hFile;char *pLine;char *token;int infostep;// 找出文件属性文件memset(fileInfoName, 0x00, 1024);strcat(fileInfoName, full_path);strcat(fileInfoName, "/linux_files_info.cxj");printf("fileInfoName=%s \r\n", fileInfoName);hFile = open(fileInfoName, O_RDONLY);if (hFile < 0){error_errno("open %s error \n", fileInfoName);return EXT4_ALLOCATE_FAILED;}// 读取属性文件ret = lstat(fileInfoName, &stat);if (ret < 0){error_errno("lstat");return EXT4_ALLOCATE_FAILED;}printf("size=%d \n", stat.st_size);if (stat.st_size == 0){goto KONGDIR;}filesize = stat.st_size;fileContent = calloc(filesize, 1);if (fileContent == NULL){close(hFile);critical_error_errno("malloc");return EXT4_ALLOCATE_FAILED;}read(hFile, fileContent, filesize);close(hFile);// 一行一行解析entries = readLines(fileContent, filesize);printf("entries = %d \r\n", entries);dentries = calloc(entries, sizeof(struct dentry));if (dentries == NULL){// 释放分配的内存free(fileContent);critical_error_errno("malloc");return EXT4_ALLOCATE_FAILED;}for(i=0; i<entries; i++){char *stopstring;//printf("%s\n", readLine(fileContent, filesize, i));pLine = readLine(fileContent, filesize, i);token=strtok(pLine, ",");infostep = 0;while (token != NULL){switch(infostep){// namecase 0:dentries[i].filename = strdup(token);asprintf(&dentries[i].path, "%s/%s", dir_path, token);asprintf(&dentries[i].full_path, "%s/%s", full_path, token);//printf("%s \n", dentries[i].path);//printf("%s \n", dentries[i].full_path);lstat(dentries[i].full_path, &stat);dentries[i].size = stat.st_size;dentries[i].mtime = 0;break;//  typecase 1:if (token[0] == 'F'){dentries[i].file_type = EXT4_FT_REG_FILE;} else if (token[0] == 'D'){dentries[i].file_type = EXT4_FT_DIR;dirs++;}else if (token[0] == 'L'){int hLinkFile;dentries[i].file_type = EXT4_FT_SYMLINK;dentries[i].link = calloc(info.block_size, 1);hLinkFile = open(dentries[i].full_path, O_RDONLY);read(hLinkFile, dentries[i].link, info.block_size - 1);close(hLinkFile);}break;//  modecase 2:dentries[i].mode = strtol(token, &stopstring, 16);break;//  uidcase 3:dentries[i].uid = strtol(token, &stopstring, 16);break;// gidcase 4:dentries[i].gid = strtol(token, &stopstring, 16);break;}infostep++;        token = strtok(NULL, ",");    }}// 释放分配的内存free(fileContent);#if 0if (dir_inode == 0){for (i=0; i<entries; i++){if (dentries[i].filename, "lost+found") == 0)break;}if (i == entries){needs_lost_and_found = true;}}if (needs_lost_and_found){struct dentry *tmp = calloc(entries + 1, sizeof(struct dentry));memset(tmp, 0, sizeof(struct dentry));memcpy(tmp + 1, dentries, entries * sizeof(struct dentry));free(dentries);dentries = tmp;dentries[0].filename = strdup("lost+found");asprintf(&dentries[0].path, "%s/lost+found", dir_path);dentries[0].full_path = NULL;dentries[0].size = 0;dentries[0].mode = S_IRWXU;dentries[0].file_type = EXT4_FT_DIR;dentries[0].uid = 0;dentries[0].gid = 0;entries++;dirs++;}#endifKONGDIR:inode = make_directory(dir_inode, entries, dentries, dirs);for (i=0; i<entries; i++){if (dentries[i].file_type == EXT4_FT_REG_FILE){entry_inode = make_file(dentries[i].full_path, dentries[i].size);}else if (dentries[i].file_type == EXT4_FT_DIR){entry_inode = build_directory_structure(dentries[i].full_path,dentries[i].path, inode, fs_config_func, sehnd);}else if (dentries[i].file_type == EXT4_FT_SYMLINK){entry_inode = make_link(dentries[i].full_path, dentries[i].link);}else{error("unknown file type on %s", dentries[i].path);entry_inode = 0;}*dentries[i].inode = entry_inode;ret = inode_set_permissions(entry_inode, dentries[i].mode,dentries[i].uid, dentries[i].gid, dentries[i].mtime);if (ret){error("failed to set permissions on %s\n", dentries[i].path);}free(dentries[i].path);free(dentries[i].full_path);free(dentries[i].link);free((void *)dentries[i].filename);}// 释放分配的内存if (dentries != NULL){free(dentries);}return inode;#endif}#endif// ----------------------------- cxj add ------------------------------------int readLines(char *data, int size){int i;int lines = 0;for (i=0; i<size; i++){if (data[i] == '\n'){lines++;}}// 最后一行没有回车的情况下if (data[i-1] != '\n'){lines++;}return lines;}static char pLineData[1024];char* readLine(char *data, int size, int lineNum){int i, j;int line = 0;memset(pLineData, 0x00, 1024);if (lineNum == 0){for (j=0; j<size; j++){if (data[j] == '\n'){return pLineData;}pLineData[j] = data[j];}return pLineData;}// 找到lineNum的开始处for (i=0; i<size; i++){if (data[i] == '\n'){line++;if (line == lineNum){break;}}}for (j=i+1; j<size; j++){if (data[j] == '\n'){return pLineData;}pLineData[j-i-1] = data[j];}return pLineData;}// ----------------------------- cxj end ------------------------------------

改写make_ext4fs工具成功,这样,我们是不是就实现了一种流程,将原始的system.img.ext4释放全部变成windows下的文件,然后通过make_ext4fs合成,又生成了system.img.ext4文件。 这样,我们就可以在中间步骤中,拷贝自己的文件到system.img.ext4释放出来的文件系统中,修改相应的linux_files_info.cxj就可以了,可以合成我们想要的system.img.ext4,实现了打包功能,中间不需要人为操作了。
   最后实现文件拷贝等,我是用python2.7写的,就不多说了,直接上代码
# coding=utf-8__author__ = 'snomy'import osimport os.pathimport shutil# ----------------- 全局变量定义 ------------------android_system_dir = r".\system"merge_dir = r"..\files\system"delList_file = r"..\files\delList.txt"# ------------------- 函数定义 --------------------# 函数: parseInfofile# 解析 linux_files_info.cxj文件def parseInfofile(fineName):    info = []    if not os.path.exists(fineName):        print "not exists", fineName        return info    hInfoFile = open(fineName, "r")    for line in hInfoFile:        info.append(line.strip().split(","))    hInfoFile.close()    return info# 函数: writeInfo2file# 回写属性文件def writeInfo2file(filename, info):    hInfoFile = open(filename, "w")    for infor_item in info:        str_infor_item = "%s,%s,%s,%s,%s\n" % (infor_item[0], infor_item[1], infor_item[2], infor_item[3], infor_item[4])        hInfoFile.write(str_infor_item)    hInfoFile.close()# 函数:delFilesItem# 删除属性文件的相应的项def delFilesItem(delfilename):    filepath, filename = os.path.split(delfilename)    filesinfo = parseInfofile(filepath + r"\linux_files_info.cxj")    for info_item in filesinfo:        if filename == info_item[0]:            filesinfo.remove(info_item)            break    # 回写    writeInfo2file(filepath + r"\linux_files_info.cxj", filesinfo)# 函数: delFiles_from_list# 解析要删除的列表,并且删除 linux_files_info.cxj 对应的项def delFiles_from_list():    if not os.path.exists(delList_file):        print "not exists", delList_file        return    hDelListFile = open(delList_file, "r")    for line in hDelListFile:        if line.find("/system/") == -1:            continue        # 删除在android中对应的文件        delfilename = line[1:].strip()        if os.path.exists(delfilename):            if os.path.isfile(delfilename):                os.remove(delfilename)                print "del file", delfilename                delFilesItem(delfilename)            else:                shutil.rmtree(delfilename)                print "del dir", delfilename                delFilesItem(delfilename)        else:            print "not find", delfilename, ", del fail!"    hDelListFile.close()# ------------------- main --------------------# 1. 解析 delList.txt 文件,并删除文件以及对应的属性条目delFiles_from_list()# 2. 扫描 system 文件夹,拷贝文件并且添加对应的属性条目for parent,dirnames,filenames in os.walk(merge_dir):    android_parent = parent[9:]    print android_parent+r"\linux_files_info.cxj"    # 解析 android_parent 目录下的文件属性    infofilename = ".\\" + android_parent + r"\linux_files_info.cxj"    filesinfo = parseInfofile(infofilename)    # 创建不存在的文件夹    for dirname in dirnames:        android_dir = android_parent + "\\" + dirname        if not os.path.exists(android_dir):            os.mkdir(android_dir)            print android_dir            dir_item = [dirname, "D", "0x41ed", "0x0000", "0x0000"]            filesinfo.append(dir_item)    # 拷贝文件    for filename in filenames:        android_filename = android_parent + "\\" + filename        merge_filename = parent + "\\" + filename        shutil.copyfile(merge_filename, android_filename)        print merge_filename        # 存在的条目不改写        fg_exist = 0;        for info_item in filesinfo:            if filename == info_item[0]:                fg_exist = 1                break        # 不存在的条目添加        if fg_exist == 0:            file_item = [filename, "F", "0x81ed", "0x0000", "0x0000"]            filesinfo.append(file_item)    # 将属性文件回写    writeInfo2file(android_parent+"\\linux_files_info.cxj", filesinfo)# walk end

到此,本文写完了,鉴于第一次写博客,可能表达的不是很清楚,以后多多改进。
工具我已经上传到我的空间中,需要的朋友可以去下载,谢谢。
http://download.csdn.net/detail/snomy/9537628
但是源码太大了,放不下,需要的朋友请留下邮箱地址,我发给你们



1 0
原创粉丝点击