cpio文件系统的解压和制作方法


cpio解压方法:
    1.  # gunzip  XXX.cpio.gz
    2. cpio -idmv < XXX.cpio

制作cpio格式文件系统的方法:
    1. 执行gen_initramfs_list.sh脚本:
    # gen_initramfs_list.sh ./Filesystem/ >filelist  
    其中 Filesystem文件夹是由上一步解压出来的cpio文件系统目录
    2. 执行gen_init_cpio产生cpio文件:
    #   gen_init_cpio filelist >rootfs.cpio
    3. 压缩cpio生成cpio.gz文件:
    #  gzip rootfs.cpio

所使用文件说明:
gen_initramfs_list.sh:用于产生filelist
gen_init_cpio.c :工具 gen_init_cpio的源码,编译后可以用
gen_init_cpio:用于产生cpio格式文件系统的可执行文件


gen_initramfs_list.sh的源码:

[plain]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. #!/bin/sh  
  2. # Copyright (C) Martin Schlemmer <azarah@nosferatu.za.org>  
  3. # Copyright (C) 2006 Sam Ravnborg <sam@ravnborg.org>  
  4. #  
  5. # Released under the terms of the GNU GPL  
  6. #  
  7. # Generate a cpio packed initramfs. It uses gen_init_cpio to generate  
  8. # the cpio archive, and then compresses it.  
  9. # The script may also be used to generate the inputfile used for gen_init_cpio  
  10. # This script assumes that gen_init_cpio is located in usr/ directory  
  11.   
  12. # error out on errors  
  13. set -e  
  14.   
  15. usage() {  
  16. cat << EOF  
  17. Usage:  
  18. $0 [-o <file>] [-u <uid>] [-g <gid>] {-d | <cpio_source>} ...  
  19.     -o <file>      Create compressed initramfs file named <file> using  
  20.                gen_init_cpio and compressor depending on the extension  
  21.     -u <uid>       User ID to map to user ID 0 (root).  
  22.                <uid> is only meaningful if <cpio_source> is a  
  23.                directory.  "squash" forces all files to uid 0.  
  24.     -g <gid>       Group ID to map to group ID 0 (root).  
  25.                <gid> is only meaningful if <cpio_source> is a  
  26.                directory.  "squash" forces all files to gid 0.  
  27.     <cpio_source>  File list or directory for cpio archive.  
  28.                If <cpio_source> is a .cpio file it will be used  
  29.                as direct input to initramfs.  
  30.     -d             Output the default cpio list.  
  31.   
  32. All options except -o and -l may be repeated and are interpreted  
  33. sequentially and immediately.  -u and -g states are preserved across  
  34. <cpio_source> options so an explicit "-u 0 -g 0" is required  
  35. to reset the root/group mapping.  
  36. EOF  
  37. }  
  38.   
  39. # awk style field access  
  40. # $1 - field number; rest is argument string  
  41. field() {  
  42.     shift $1 ; echo $1  
  43. }  
  44.   
  45. list_default_initramfs() {  
  46.     # echo usr/kinit/kinit  
  47.     :  
  48. }  
  49.   
  50. default_initramfs() {  
  51.     cat <<-EOF >> ${output}  
  52.         # This is a very simple, default initramfs  
  53.   
  54.         dir /dev 0755 0 0  
  55.         nod /dev/console 0600 0 0 c 5 1  
  56.         dir /root 0700 0 0  
  57.         # file /kinit usr/kinit/kinit 0755 0 0  
  58.         # slink /init kinit 0755 0 0  
  59.     EOF  
  60. }  
  61.   
  62. filetype() {  
  63.     local argv1="$1"  
  64.   
  65.     # symlink test must come before file test  
  66.     if [ -L "${argv1}" ]; then  
  67.         echo "slink"  
  68.     elif [ -f "${argv1}" ]; then  
  69.         echo "file"  
  70.     elif [ -d "${argv1}" ]; then  
  71.         echo "dir"  
  72.     elif [ -b "${argv1}" -o -c "${argv1}" ]; then  
  73.         echo "nod"  
  74.     elif [ -p "${argv1}" ]; then  
  75.         echo "pipe"  
  76.     elif [ -S "${argv1}" ]; then  
  77.         echo "sock"  
  78.     else  
  79.         echo "invalid"  
  80.     fi  
  81.     return 0  
  82. }  
  83.   
  84. list_print_mtime() {  
  85.     :  
  86. }  
  87.   
  88. print_mtime() {  
  89.     local my_mtime="0"  
  90.   
  91.     if [ -e "$1" ]; then  
  92.         my_mtime=$(find "$1" -printf "%T@\n" | sort -r | head -n 1)  
  93.     fi  
  94.   
  95.     echo "# Last modified: ${my_mtime}" >> ${output}  
  96.     echo "" >> ${output}  
  97. }  
  98.   
  99. list_parse() {  
  100.     [ ! -L "$1" ] && echo "$1 \\" || :  
  101. }  
  102.   
  103. # for each file print a line in following format  
  104. # <filetype> <name> <path to file> <octal mode> <uid> <gid>  
  105. # for links, devices etc the format differs. See gen_init_cpio for details  
  106. parse() {  
  107.     local location="$1"  
  108.     local name="/${location#${srcdir}}"  
  109.     # change '//' into '/'  
  110.     name=$(echo "$name" | sed -e 's://*:/:g')  
  111.     local mode="$2"  
  112.     local uid="$3"  
  113.     local gid="$4"  
  114.     local ftype=$(filetype "${location}")  
  115.     # remap uid/gid to 0 if necessary  
  116.     [ "$root_uid" = "squash" ] && uid=0 || [ "$uid" -eq "$root_uid" ] && uid=0  
  117.     [ "$root_gid" = "squash" ] && gid=0 || [ "$gid" -eq "$root_gid" ] && gid=0  
  118.     local str="${mode} ${uid} ${gid}"  
  119.   
  120.     [ "${ftype}" = "invalid" ] && return 0  
  121.     [ "${location}" = "${srcdir}" ] && return 0  
  122.   
  123.     case "${ftype}" in  
  124.         "file")  
  125.             str="${ftype} ${name} ${location} ${str}"  
  126.             ;;  
  127.         "nod")  
  128.             local dev=`LC_ALL=C ls -l "${location}"`  
  129.             local maj=`field 5 ${dev}`  
  130.             local min=`field 6 ${dev}`  
  131.             maj=${maj%,}  
  132.   
  133.             [ -b "${location}" ] && dev="b" || dev="c"  
  134.   
  135.             str="${ftype} ${name} ${str} ${dev} ${maj} ${min}"  
  136.             ;;  
  137.         "slink")  
  138.             local target=`readlink "${location}"`  
  139.             str="${ftype} ${name} ${target} ${str}"  
  140.             ;;  
  141.         *)  
  142.             str="${ftype} ${name} ${str}"  
  143.             ;;  
  144.     esac  
  145.   
  146.     echo "${str}" >> ${output}  
  147.   
  148.     return 0  
  149. }  
  150.   
  151. unknown_option() {  
  152.     printf "ERROR: unknown option \"$arg\"\n" >&2  
  153.     printf "If the filename validly begins with '-', " >&2  
  154.     printf "then it must be prefixed\n" >&2  
  155.     printf "by './' so that it won't be interpreted as an option." >&2  
  156.     printf "\n" >&2  
  157.     usage >&2  
  158.     exit 1  
  159. }  
  160.   
  161. list_header() {  
  162.     :  
  163. }  
  164.   
  165. header() {  
  166.     printf "\n#####################\n# $1\n" >> ${output}  
  167. }  
  168.   
  169. # process one directory (incl sub-directories)  
  170. dir_filelist() {  
  171.     ${dep_list}header "$1"  
  172.   
  173.     srcdir=$(echo "$1" | sed -e 's://*:/:g')  
  174.     dirlist=$(find "${srcdir}" -printf "%p %m %U %G\n")  
  175.   
  176.     # If $dirlist is only one line, then the directory is empty  
  177.     if [  "$(echo "${dirlist}" | wc -l)" -gt 1 ]; then  
  178.         ${dep_list}print_mtime "$1"  
  179.   
  180.         echo "${dirlist}" | \  
  181.         while read x; do  
  182.             ${dep_list}parse ${x}  
  183.         done  
  184.     fi  
  185. }  
  186.   
  187. # if only one file is specified and it is .cpio file then use it direct as fs  
  188. # if a directory is specified then add all files in given direcotry to fs  
  189. # if a regular file is specified assume it is in gen_initramfs format  
  190. input_file() {  
  191.     source="$1"  
  192.     if [ -f "$1" ]; then  
  193.         ${dep_list}header "$1"  
  194.         is_cpio="$(echo "$1" | sed 's/^.*\.cpio \.. \?/cpio/')"  
  195.         if [ $2 -eq 0 -a ${is_cpio} = "cpio" ]; then  
  196.             cpio_file=$1  
  197.             echo "$1" | grep -q '^.*\.cpio\..*' && is_cpio_compressed="compressed"  
  198.             [ ! -z ${dep_list} ] && echo "$1"  
  199.             return 0  
  200.         fi  
  201.         if [ -z ${dep_list} ]; then  
  202.             print_mtime "$1" >> ${output}  
  203.             cat "$1"         >> ${output}  
  204.         else  
  205.                 echo "$1 \\"  
  206.             cat "$1" | while read type dir file perm ; do  
  207.                 if [ "$type" = "file" ]; then  
  208.                     echo "$file \\";  
  209.                 fi  
  210.             done  
  211.         fi  
  212.     elif [ -d "$1" ]; then  
  213.         dir_filelist "$1"  
  214.     else  
  215.         echo "  ${prog}: Cannot open '$1'" >&2  
  216.         exit 1  
  217.     fi  
  218. }  
  219.   
  220. prog=$0  
  221. root_uid=0  
  222. root_gid=0  
  223. dep_list=  
  224. cpio_file=  
  225. cpio_list=  
  226. output="/dev/stdout"  
  227. output_file=""  
  228. is_cpio_compressed=  
  229. compr="gzip -n -9 -f"  
  230.   
  231. arg="$1"  
  232. case "$arg" in  
  233.     "-l")   # files included in initramfs - used by kbuild  
  234.         dep_list="list_"  
  235.         echo "deps_initramfs := $0 \\"  
  236.         shift  
  237.         ;;  
  238.     "-o")   # generate compressed cpio image named $1  
  239.         shift  
  240.         output_file="$1"  
  241.         cpio_list="$(mktemp ${TMPDIR:-/tmp}/cpiolist.XXXXXX)"  
  242.         output=${cpio_list}  
  243.         echo "$output_file" | grep -q "\.gz$" && compr="gzip -n -9 -f"  
  244.         echo "$output_file" | grep -q "\.bz2$" && compr="bzip2 -9 -f"  
  245.         echo "$output_file" | grep -q "\.lzma$" && compr="lzma -9 -f"  
  246.         echo "$output_file" | grep -q "\.xz$" && \  
  247.                 compr="xz --check=crc32 --lzma2=dict=1MiB"  
  248.         echo "$output_file" | grep -q "\.lzo$" && compr="lzop -9 -f"  
  249.         echo "$output_file" | grep -q "\.cpio$" && compr="cat"  
  250.         shift  
  251.         ;;  
  252. esac  
  253. while [ $# -gt 0 ]; do  
  254.     arg="$1"  
  255.     shift  
  256.     case "$arg" in  
  257.         "-u")   # map $1 to uid=0 (root)  
  258.             root_uid="$1"  
  259.             shift  
  260.             ;;  
  261.         "-g")   # map $1 to gid=0 (root)  
  262.             root_gid="$1"  
  263.             shift  
  264.             ;;  
  265.         "-d")   # display default initramfs list  
  266.             default_list="$arg"  
  267.             ${dep_list}default_initramfs  
  268.             ;;  
  269.         "-h")  
  270.             usage  
  271.             exit 0  
  272.             ;;  
  273.         *)  
  274.             case "$arg" in  
  275.                 "-"*)  
  276.                     unknown_option  
  277.                     ;;  
  278.                 *)  # input file/dir - process it  
  279.                     input_file "$arg" "$#"  
  280.                     ;;  
  281.             esac  
  282.             ;;  
  283.     esac  
  284. done  
  285.   
  286. # If output_file is set we will generate cpio archive and compress it  
  287. # we are careful to delete tmp files  
  288. if [ ! -z ${output_file} ]; then  
  289.     if [ -z ${cpio_file} ]; then  
  290.         timestamp=  
  291.         if test -n "$KBUILD_BUILD_TIMESTAMP"; then  
  292.             timestamp="$(date -d"$KBUILD_BUILD_TIMESTAMP" +%s || :)"  
  293.             if test -n "$timestamp"; then  
  294.                 timestamp="-t $timestamp"  
  295.             fi  
  296.         fi  
  297.         cpio_tfile="$(mktemp ${TMPDIR:-/tmp}/cpiofile.XXXXXX)"  
  298.         usr/gen_init_cpio $timestamp ${cpio_list} > ${cpio_tfile}  
  299.     else  
  300.         cpio_tfile=${cpio_file}  
  301.     fi  
  302.     rm ${cpio_list}  
  303.     if [ "${is_cpio_compressed}" = "compressed" ]; then  
  304.         cat ${cpio_tfile} > ${output_file}  
  305.     else  
  306.         (cat ${cpio_tfile} | ${compr}  - > ${output_file}) \  
  307.         || (rm -f ${output_file} ; false)  
  308.     fi  
  309.     [ -z ${cpio_file} ] && rm ${cpio_tfile}  
  310. fi  
  311. exit 0  


gen_init_cpio.c的源码:

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <sys/types.h>  
  4. #include <sys/stat.h>  
  5. #include <string.h>  
  6. #include <unistd.h>  
  7. #include <time.h>  
  8. #include <fcntl.h>  
  9. #include <errno.h>  
  10. #include <ctype.h>  
  11. #include <limits.h>  
  12.   
  13. /* 
  14.  * Original work by Jeff Garzik 
  15.  * 
  16.  * External file lists, symlink, pipe and fifo support by Thayne Harbaugh 
  17.  * Hard link support by Luciano Rocha 
  18.  */  
  19.   
  20. #define xstr(s) #s  
  21. #define str(s) xstr(s)  
  22.   
  23. static unsigned int offset;  
  24. static unsigned int ino = 721;  
  25. static time_t default_mtime;  
  26.   
  27. struct file_handler {  
  28.     const char *type;  
  29.     int (*handler)(const char *line);  
  30. };  
  31.   
  32. static void push_string(const char *name)  
  33. {  
  34.     unsigned int name_len = strlen(name) + 1;  
  35.   
  36.     fputs(name, stdout);  
  37.     putchar(0);  
  38.     offset += name_len;  
  39. }  
  40.   
  41. static void push_pad (void)  
  42. {  
  43.     while (offset & 3) {  
  44.         putchar(0);  
  45.         offset++;  
  46.     }  
  47. }  
  48.   
  49. static void push_rest(const char *name)  
  50. {  
  51.     unsigned int name_len = strlen(name) + 1;  
  52.     unsigned int tmp_ofs;  
  53.   
  54.     fputs(name, stdout);  
  55.     putchar(0);  
  56.     offset += name_len;  
  57.   
  58.     tmp_ofs = name_len + 110;  
  59.     while (tmp_ofs & 3) {  
  60.         putchar(0);  
  61.         offset++;  
  62.         tmp_ofs++;  
  63.     }  
  64. }  
  65.   
  66. static void push_hdr(const char *s)  
  67. {  
  68.     fputs(s, stdout);  
  69.     offset += 110;  
  70. }  
  71.   
  72. static void cpio_trailer(void)  
  73. {  
  74.     char s[256];  
  75.     const char name[] = "TRAILER!!!";  
  76.   
  77.     sprintf(s, "%s%08X%08X%08lX%08lX%08X%08lX"  
  78.            "%08X%08X%08X%08X%08X%08X%08X",  
  79.         "070701",       /* magic */  
  80.         0,          /* ino */  
  81.         0,          /* mode */  
  82.         (long) 0,       /* uid */  
  83.         (long) 0,       /* gid */  
  84.         1,          /* nlink */  
  85.         (long) 0,       /* mtime */  
  86.         0,          /* filesize */  
  87.         0,          /* major */  
  88.         0,          /* minor */  
  89.         0,          /* rmajor */  
  90.         0,          /* rminor */  
  91.         (unsigned)strlen(name)+1, /* namesize */  
  92.         0);         /* chksum */  
  93.     push_hdr(s);  
  94.     push_rest(name);  
  95.   
  96.     while (offset % 512) {  
  97.         putchar(0);  
  98.         offset++;  
  99.     }  
  100. }  
  101.   
  102. static int cpio_mkslink(const char *name, const char *target,  
  103.              unsigned int mode, uid_t uid, gid_t gid)  
  104. {  
  105.     char s[256];  
  106.   
  107.     if (name[0] == '/')  
  108.         name++;  
  109.     sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"  
  110.            "%08X%08X%08X%08X%08X%08X%08X",  
  111.         "070701",       /* magic */  
  112.         ino++,          /* ino */  
  113.         S_IFLNK | mode,     /* mode */  
  114.         (long) uid,     /* uid */  
  115.         (long) gid,     /* gid */  
  116.         1,          /* nlink */  
  117.         (long) default_mtime,   /* mtime */  
  118.         (unsigned)strlen(target)+1, /* filesize */  
  119.         3,          /* major */  
  120.         1,          /* minor */  
  121.         0,          /* rmajor */  
  122.         0,          /* rminor */  
  123.         (unsigned)strlen(name) + 1,/* namesize */  
  124.         0);         /* chksum */  
  125.     push_hdr(s);  
  126.     push_string(name);  
  127.     push_pad();  
  128.     push_string(target);  
  129.     push_pad();  
  130.     return 0;  
  131. }  
  132.   
  133. static int cpio_mkslink_line(const char *line)  
  134. {  
  135.     char name[PATH_MAX + 1];  
  136.     char target[PATH_MAX + 1];  
  137.     unsigned int mode;  
  138.     int uid;  
  139.     int gid;  
  140.     int rc = -1;  
  141.   
  142.     if (5 != sscanf(line, "%" str(PATH_MAX) "s %" str(PATH_MAX) "s %o %d %d", name, target, &mode, &uid, &gid)) {  
  143.         fprintf(stderr, "Unrecognized dir format '%s'", line);  
  144.         goto fail;  
  145.     }  
  146.     rc = cpio_mkslink(name, target, mode, uid, gid);  
  147.  fail:  
  148.     return rc;  
  149. }  
  150.   
  151. static int cpio_mkgeneric(const char *name, unsigned int mode,  
  152.                uid_t uid, gid_t gid)  
  153. {  
  154.     char s[256];  
  155.   
  156.     if (name[0] == '/')  
  157.         name++;  
  158.     sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"  
  159.            "%08X%08X%08X%08X%08X%08X%08X",  
  160.         "070701",       /* magic */  
  161.         ino++,          /* ino */  
  162.         mode,           /* mode */  
  163.         (long) uid,     /* uid */  
  164.         (long) gid,     /* gid */  
  165.         2,          /* nlink */  
  166.         (long) default_mtime,   /* mtime */  
  167.         0,          /* filesize */  
  168.         3,          /* major */  
  169.         1,          /* minor */  
  170.         0,          /* rmajor */  
  171.         0,          /* rminor */  
  172.         (unsigned)strlen(name) + 1,/* namesize */  
  173.         0);         /* chksum */  
  174.     push_hdr(s);  
  175.     push_rest(name);  
  176.     return 0;  
  177. }  
  178.   
  179. enum generic_types {  
  180.     GT_DIR,  
  181.     GT_PIPE,  
  182.     GT_SOCK  
  183. };  
  184.   
  185. struct generic_type {  
  186.     const char *type;  
  187.     mode_t mode;  
  188. };  
  189.   
  190. static struct generic_type generic_type_table[] = {  
  191.     [GT_DIR] = {  
  192.         .type = "dir",  
  193.         .mode = S_IFDIR  
  194.     },  
  195.     [GT_PIPE] = {  
  196.         .type = "pipe",  
  197.         .mode = S_IFIFO  
  198.     },  
  199.     [GT_SOCK] = {  
  200.         .type = "sock",  
  201.         .mode = S_IFSOCK  
  202.     }  
  203. };  
  204.   
  205. static int cpio_mkgeneric_line(const char *line, enum generic_types gt)  
  206. {  
  207.     char name[PATH_MAX + 1];  
  208.     unsigned int mode;  
  209.     int uid;  
  210.     int gid;  
  211.     int rc = -1;  
  212.   
  213.     if (4 != sscanf(line, "%" str(PATH_MAX) "s %o %d %d", name, &mode, &uid, &gid)) {  
  214.         fprintf(stderr, "Unrecognized %s format '%s'",  
  215.             line, generic_type_table[gt].type);  
  216.         goto fail;  
  217.     }  
  218.     mode |= generic_type_table[gt].mode;  
  219.     rc = cpio_mkgeneric(name, mode, uid, gid);  
  220.  fail:  
  221.     return rc;  
  222. }  
  223.   
  224. static int cpio_mkdir_line(const char *line)  
  225. {  
  226.     return cpio_mkgeneric_line(line, GT_DIR);  
  227. }  
  228.   
  229. static int cpio_mkpipe_line(const char *line)  
  230. {  
  231.     return cpio_mkgeneric_line(line, GT_PIPE);  
  232. }  
  233.   
  234. static int cpio_mksock_line(const char *line)  
  235. {  
  236.     return cpio_mkgeneric_line(line, GT_SOCK);  
  237. }  
  238.   
  239. static int cpio_mknod(const char *name, unsigned int mode,  
  240.                uid_t uid, gid_t gid, char dev_type,  
  241.                unsigned int maj, unsigned int min)  
  242. {  
  243.     char s[256];  
  244.   
  245.     if (dev_type == 'b')  
  246.         mode |= S_IFBLK;  
  247.     else  
  248.         mode |= S_IFCHR;  
  249.   
  250.     if (name[0] == '/')  
  251.         name++;  
  252.     sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"  
  253.            "%08X%08X%08X%08X%08X%08X%08X",  
  254.         "070701",       /* magic */  
  255.         ino++,          /* ino */  
  256.         mode,           /* mode */  
  257.         (long) uid,     /* uid */  
  258.         (long) gid,     /* gid */  
  259.         1,          /* nlink */  
  260.         (long) default_mtime,   /* mtime */  
  261.         0,          /* filesize */  
  262.         3,          /* major */  
  263.         1,          /* minor */  
  264.         maj,            /* rmajor */  
  265.         min,            /* rminor */  
  266.         (unsigned)strlen(name) + 1,/* namesize */  
  267.         0);         /* chksum */  
  268.     push_hdr(s);  
  269.     push_rest(name);  
  270.     return 0;  
  271. }  
  272.   
  273. static int cpio_mknod_line(const char *line)  
  274. {  
  275.     char name[PATH_MAX + 1];  
  276.     unsigned int mode;  
  277.     int uid;  
  278.     int gid;  
  279.     char dev_type;  
  280.     unsigned int maj;  
  281.     unsigned int min;  
  282.     int rc = -1;  
  283.   
  284.     if (7 != sscanf(line, "%" str(PATH_MAX) "s %o %d %d %c %u %u",  
  285.              name, &mode, &uid, &gid, &dev_type, &maj, &min)) {  
  286.         fprintf(stderr, "Unrecognized nod format '%s'", line);  
  287.         goto fail;  
  288.     }  
  289.     rc = cpio_mknod(name, mode, uid, gid, dev_type, maj, min);  
  290.  fail:  
  291.     return rc;  
  292. }  
  293.   
  294. static int cpio_mkfile(const char *name, const char *location,  
  295.             unsigned int mode, uid_t uid, gid_t gid,  
  296.             unsigned int nlinks)  
  297. {  
  298.     char s[256];  
  299.     char *filebuf = NULL;  
  300.     struct stat buf;  
  301.     long size;  
  302.     int file = -1;  
  303.     int retval;  
  304.     int rc = -1;  
  305.     int namesize;  
  306.     int i;  
  307.   
  308.     mode |= S_IFREG;  
  309.   
  310.     file = open (location, O_RDONLY);  
  311.     if (file < 0) {  
  312.         fprintf (stderr, "File %s could not be opened for reading\n", location);  
  313.         goto error;  
  314.     }  
  315.   
  316.     retval = fstat(file, &buf);  
  317.     if (retval) {  
  318.         fprintf(stderr, "File %s could not be stat()'ed\n", location);  
  319.         goto error;  
  320.     }  
  321.   
  322.     filebuf = malloc(buf.st_size);  
  323.     if (!filebuf) {  
  324.         fprintf (stderr, "out of memory\n");  
  325.         goto error;  
  326.     }  
  327.   
  328.     retval = read (file, filebuf, buf.st_size);  
  329.     if (retval < 0) {  
  330.         fprintf (stderr, "Can not read %s file\n", location);  
  331.         goto error;  
  332.     }  
  333.   
  334.     size = 0;  
  335.     for (i = 1; i <= nlinks; i++) {  
  336.         /* data goes on last link */  
  337.         if (i == nlinks) size = buf.st_size;  
  338.   
  339.         if (name[0] == '/')  
  340.             name++;  
  341.         namesize = strlen(name) + 1;  
  342.         sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"  
  343.                "%08lX%08X%08X%08X%08X%08X%08X",  
  344.             "070701",       /* magic */  
  345.             ino,            /* ino */  
  346.             mode,           /* mode */  
  347.             (long) uid,     /* uid */  
  348.             (long) gid,     /* gid */  
  349.             nlinks,         /* nlink */  
  350.             (long) buf.st_mtime,    /* mtime */  
  351.             size,           /* filesize */  
  352.             3,          /* major */  
  353.             1,          /* minor */  
  354.             0,          /* rmajor */  
  355.             0,          /* rminor */  
  356.             namesize,       /* namesize */  
  357.             0);         /* chksum */  
  358.         push_hdr(s);  
  359.         push_string(name);  
  360.         push_pad();  
  361.   
  362.         if (size) {  
  363.             if (fwrite(filebuf, size, 1, stdout) != 1) {  
  364.                 fprintf(stderr, "writing filebuf failed\n");  
  365.                 goto error;  
  366.             }  
  367.             offset += size;  
  368.             push_pad();  
  369.         }  
  370.   
  371.         name += namesize;  
  372.     }  
  373.     ino++;  
  374.     rc = 0;  
  375.       
  376. error:  
  377.     if (filebuf) free(filebuf);  
  378.     if (file >= 0) close(file);  
  379.     return rc;  
  380. }  
  381.   
  382. static char *cpio_replace_env(char *new_location)  
  383. {  
  384.        char expanded[PATH_MAX + 1];  
  385.        char env_var[PATH_MAX + 1];  
  386.        char *start;  
  387.        char *end;  
  388.   
  389.        for (start = NULL; (start = strstr(new_location, "${")); ) {  
  390.                end = strchr(start, '}');  
  391.                if (start < end) {  
  392.                        *env_var = *expanded = '\0';  
  393.                        strncat(env_var, start + 2, end - start - 2);  
  394.                        strncat(expanded, new_location, start - new_location);  
  395.                        strncat(expanded, getenv(env_var), PATH_MAX);  
  396.                        strncat(expanded, end + 1, PATH_MAX);  
  397.                        strncpy(new_location, expanded, PATH_MAX);  
  398.                } else  
  399.                        break;  
  400.        }  
  401.   
  402.        return new_location;  
  403. }  
  404.   
  405.   
  406. static int cpio_mkfile_line(const char *line)  
  407. {  
  408.     char name[PATH_MAX + 1];  
  409.     char *dname = NULL; /* malloc'ed buffer for hard links */  
  410.     char location[PATH_MAX + 1];  
  411.     unsigned int mode;  
  412.     int uid;  
  413.     int gid;  
  414.     int nlinks = 1;  
  415.     int end = 0, dname_len = 0;  
  416.     int rc = -1;  
  417.   
  418.     if (5 > sscanf(line, "%" str(PATH_MAX) "s %" str(PATH_MAX)  
  419.                 "s %o %d %d %n",  
  420.                 name, location, &mode, &uid, &gid, &end)) {  
  421.         fprintf(stderr, "Unrecognized file format '%s'", line);  
  422.         goto fail;  
  423.     }  
  424.     if (end && isgraph(line[end])) {  
  425.         int len;  
  426.         int nend;  
  427.   
  428.         dname = malloc(strlen(line));  
  429.         if (!dname) {  
  430.             fprintf (stderr, "out of memory (%d)\n", dname_len);  
  431.             goto fail;  
  432.         }  
  433.   
  434.         dname_len = strlen(name) + 1;  
  435.         memcpy(dname, name, dname_len);  
  436.   
  437.         do {  
  438.             nend = 0;  
  439.             if (sscanf(line + end, "%" str(PATH_MAX) "s %n",  
  440.                     name, &nend) < 1)  
  441.                 break;  
  442.             len = strlen(name) + 1;  
  443.             memcpy(dname + dname_len, name, len);  
  444.             dname_len += len;  
  445.             nlinks++;  
  446.             end += nend;  
  447.         } while (isgraph(line[end]));  
  448.     } else {  
  449.         dname = name;  
  450.     }  
  451.     rc = cpio_mkfile(dname, cpio_replace_env(location),  
  452.                      mode, uid, gid, nlinks);  
  453.  fail:  
  454.     if (dname_len) free(dname);  
  455.     return rc;  
  456. }  
  457.   
  458. static void usage(const char *prog)  
  459. {  
  460.     fprintf(stderr, "Usage:\n"  
  461.         "\t%s [-t <timestamp>] <cpio_list>\n"  
  462.         "\n"  
  463.         "<cpio_list> is a file containing newline separated entries that\n"  
  464.         "describe the files to be included in the initramfs archive:\n"  
  465.         "\n"  
  466.         "# a comment\n"  
  467.         "file <name> <location> <mode> <uid> <gid> [<hard links>]\n"  
  468.         "dir <name> <mode> <uid> <gid>\n"  
  469.         "nod <name> <mode> <uid> <gid> <dev_type> <maj> <min>\n"  
  470.         "slink <name> <target> <mode> <uid> <gid>\n"  
  471.         "pipe <name> <mode> <uid> <gid>\n"  
  472.         "sock <name> <mode> <uid> <gid>\n"  
  473.         "\n"  
  474.         "<name>       name of the file/dir/nod/etc in the archive\n"  
  475.         "<location>   location of the file in the current filesystem\n"  
  476.         "             expands shell variables quoted with ${}\n"  
  477.         "<target>     link target\n"  
  478.         "<mode>       mode/permissions of the file\n"  
  479.         "<uid>        user id (0=root)\n"  
  480.         "<gid>        group id (0=root)\n"  
  481.         "<dev_type>   device type (b=block, c=character)\n"  
  482.         "<maj>        major number of nod\n"  
  483.         "<min>        minor number of nod\n"  
  484.         "<hard links> space separated list of other links to file\n"  
  485.         "\n"  
  486.         "example:\n"  
  487.         "# A simple initramfs\n"  
  488.         "dir /dev 0755 0 0\n"  
  489.         "nod /dev/console 0600 0 0 c 5 1\n"  
  490.         "dir /root 0700 0 0\n"  
  491.         "dir /sbin 0755 0 0\n"  
  492.         "file /sbin/kinit /usr/src/klibc/kinit/kinit 0755 0 0\n"  
  493.         "\n"  
  494.         "<timestamp> is time in seconds since Epoch that will be used\n"  
  495.         "as mtime for symlinks, special files and directories. The default\n"  
  496.         "is to use the current time for these entries.\n",  
  497.         prog);  
  498. }  
  499.   
  500. struct file_handler file_handler_table[] = {  
  501.     {  
  502.         .type    = "file",  
  503.         .handler = cpio_mkfile_line,  
  504.     }, {  
  505.         .type    = "nod",  
  506.         .handler = cpio_mknod_line,  
  507.     }, {  
  508.         .type    = "dir",  
  509.         .handler = cpio_mkdir_line,  
  510.     }, {  
  511.         .type    = "slink",  
  512.         .handler = cpio_mkslink_line,  
  513.     }, {  
  514.         .type    = "pipe",  
  515.         .handler = cpio_mkpipe_line,  
  516.     }, {  
  517.         .type    = "sock",  
  518.         .handler = cpio_mksock_line,  
  519.     }, {  
  520.         .type    = NULL,  
  521.         .handler = NULL,  
  522.     }  
  523. };  
  524.   
  525. #define LINE_SIZE (2 * PATH_MAX + 50)  
  526.   
  527. int main (int argc, char *argv[])  
  528. {  
  529.     FILE *cpio_list;  
  530.     char line[LINE_SIZE];  
  531.     char *args, *type;  
  532.     int ec = 0;  
  533.     int line_nr = 0;  
  534.     const char *filename;  
  535.   
  536.     default_mtime = time(NULL);  
  537.     while (1) {  
  538.         int opt = getopt(argc, argv, "t:h");  
  539.         char *invalid;  
  540.   
  541.         if (opt == -1)  
  542.             break;  
  543.         switch (opt) {  
  544.         case 't':  
  545.             default_mtime = strtol(optarg, &invalid, 10);  
  546.             if (!*optarg || *invalid) {  
  547.                 fprintf(stderr, "Invalid timestamp: %s\n",  
  548.                         optarg);  
  549.                 usage(argv[0]);  
  550.                 exit(1);  
  551.             }  
  552.             break;  
  553.         case 'h':  
  554.         case '?':  
  555.             usage(argv[0]);  
  556.             exit(opt == 'h' ? 0 : 1);  
  557.         }  
  558.     }  
  559.   
  560.     if (argc - optind != 1) {  
  561.         usage(argv[0]);  
  562.         exit(1);  
  563.     }  
  564.     filename = argv[optind];  
  565.     if (!strcmp(filename, "-"))  
  566.         cpio_list = stdin;  
  567.     else if (!(cpio_list = fopen(filename, "r"))) {  
  568.         fprintf(stderr, "ERROR: unable to open '%s': %s\n\n",  
  569.             filename, strerror(errno));  
  570.         usage(argv[0]);  
  571.         exit(1);  
  572.     }  
  573.   
  574.     while (fgets(line, LINE_SIZE, cpio_list)) {  
  575.         int type_idx;  
  576.         size_t slen = strlen(line);  
  577.   
  578.         line_nr++;  
  579.   
  580.         if ('#' == *line) {  
  581.             /* comment - skip to next line */  
  582.             continue;  
  583.         }  
  584.   
  585.         if (! (type = strtok(line, " \t"))) {  
  586.             fprintf(stderr,  
  587.                 "ERROR: incorrect format, could not locate file type line %d: '%s'\n",  
  588.                 line_nr, line);  
  589.             ec = -1;  
  590.             break;  
  591.         }  
  592.   
  593.         if ('\n' == *type) {  
  594.             /* a blank line */  
  595.             continue;  
  596.         }  
  597.   
  598.         if (slen == strlen(type)) {  
  599.             /* must be an empty line */  
  600.             continue;  
  601.         }  
  602.   
  603.         if (! (args = strtok(NULL, "\n"))) {  
  604.             fprintf(stderr,  
  605.                 "ERROR: incorrect format, newline required line %d: '%s'\n",  
  606.                 line_nr, line);  
  607.             ec = -1;  
  608.         }  
  609.   
  610.         for (type_idx = 0; file_handler_table[type_idx].type; type_idx++) {  
  611.             int rc;  
  612.             if (! strcmp(line, file_handler_table[type_idx].type)) {  
  613.                 if ((rc = file_handler_table[type_idx].handler(args))) {  
  614.                     ec = rc;  
  615.                     fprintf(stderr, " line %d\n", line_nr);  
  616.                 }  
  617.                 break;  
  618.             }  
  619.         }  
  620.   
  621.         if (NULL == file_handler_table[type_idx].type) {  
  622.             fprintf(stderr, "unknown file type line %d: '%s'\n",  
  623.                 line_nr, line);  
  624.         }  
  625.     }  
  626.     if (ec == 0)  
  627.         cpio_trailer();  
  628.   
  629.     exit(ec);  
  630. }  


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值