0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 #include <linux/earlycpio.h>
0021 #include <linux/kernel.h>
0022 #include <linux/string.h>
0023
0024 enum cpio_fields {
0025 C_MAGIC,
0026 C_INO,
0027 C_MODE,
0028 C_UID,
0029 C_GID,
0030 C_NLINK,
0031 C_MTIME,
0032 C_FILESIZE,
0033 C_MAJ,
0034 C_MIN,
0035 C_RMAJ,
0036 C_RMIN,
0037 C_NAMESIZE,
0038 C_CHKSUM,
0039 C_NFIELDS
0040 };
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059 struct cpio_data find_cpio_data(const char *path, void *data,
0060 size_t len, long *nextoff)
0061 {
0062 const size_t cpio_header_len = 8*C_NFIELDS - 2;
0063 struct cpio_data cd = { NULL, 0, "" };
0064 const char *p, *dptr, *nptr;
0065 unsigned int ch[C_NFIELDS], *chp, v;
0066 unsigned char c, x;
0067 size_t mypathsize = strlen(path);
0068 int i, j;
0069
0070 p = data;
0071
0072 while (len > cpio_header_len) {
0073 if (!*p) {
0074
0075 p += 4;
0076 len -= 4;
0077 continue;
0078 }
0079
0080 j = 6;
0081 chp = ch;
0082 for (i = C_NFIELDS; i; i--) {
0083 v = 0;
0084 while (j--) {
0085 v <<= 4;
0086 c = *p++;
0087
0088 x = c - '0';
0089 if (x < 10) {
0090 v += x;
0091 continue;
0092 }
0093
0094 x = (c | 0x20) - 'a';
0095 if (x < 6) {
0096 v += x + 10;
0097 continue;
0098 }
0099
0100 goto quit;
0101 }
0102 *chp++ = v;
0103 j = 8;
0104 }
0105
0106 if ((ch[C_MAGIC] - 0x070701) > 1)
0107 goto quit;
0108
0109 len -= cpio_header_len;
0110
0111 dptr = PTR_ALIGN(p + ch[C_NAMESIZE], 4);
0112 nptr = PTR_ALIGN(dptr + ch[C_FILESIZE], 4);
0113
0114 if (nptr > p + len || dptr < p || nptr < dptr)
0115 goto quit;
0116
0117 if ((ch[C_MODE] & 0170000) == 0100000 &&
0118 ch[C_NAMESIZE] >= mypathsize &&
0119 !memcmp(p, path, mypathsize)) {
0120
0121 if (nextoff)
0122 *nextoff = (long)nptr - (long)data;
0123
0124 if (ch[C_NAMESIZE] - mypathsize >= MAX_CPIO_FILE_NAME) {
0125 pr_warn(
0126 "File %s exceeding MAX_CPIO_FILE_NAME [%d]\n",
0127 p, MAX_CPIO_FILE_NAME);
0128 }
0129 strlcpy(cd.name, p + mypathsize, MAX_CPIO_FILE_NAME);
0130
0131 cd.data = (void *)dptr;
0132 cd.size = ch[C_FILESIZE];
0133 return cd;
0134 }
0135 len -= (nptr - p);
0136 p = nptr;
0137 }
0138
0139 quit:
0140 return cd;
0141 }