1*1da177e4SLinus Torvalds #include <netinet/in.h> 2*1da177e4SLinus Torvalds #ifdef __sun__ 3*1da177e4SLinus Torvalds #include <inttypes.h> 4*1da177e4SLinus Torvalds #else 5*1da177e4SLinus Torvalds #include <stdint.h> 6*1da177e4SLinus Torvalds #endif 7*1da177e4SLinus Torvalds #include <ctype.h> 8*1da177e4SLinus Torvalds #include <errno.h> 9*1da177e4SLinus Torvalds #include <string.h> 10*1da177e4SLinus Torvalds #include "modpost.h" 11*1da177e4SLinus Torvalds 12*1da177e4SLinus Torvalds /* 13*1da177e4SLinus Torvalds * Stolen form Cryptographic API. 14*1da177e4SLinus Torvalds * 15*1da177e4SLinus Torvalds * MD4 Message Digest Algorithm (RFC1320). 16*1da177e4SLinus Torvalds * 17*1da177e4SLinus Torvalds * Implementation derived from Andrew Tridgell and Steve French's 18*1da177e4SLinus Torvalds * CIFS MD4 implementation, and the cryptoapi implementation 19*1da177e4SLinus Torvalds * originally based on the public domain implementation written 20*1da177e4SLinus Torvalds * by Colin Plumb in 1993. 21*1da177e4SLinus Torvalds * 22*1da177e4SLinus Torvalds * Copyright (c) Andrew Tridgell 1997-1998. 23*1da177e4SLinus Torvalds * Modified by Steve French (sfrench@us.ibm.com) 2002 24*1da177e4SLinus Torvalds * Copyright (c) Cryptoapi developers. 25*1da177e4SLinus Torvalds * Copyright (c) 2002 David S. Miller (davem@redhat.com) 26*1da177e4SLinus Torvalds * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> 27*1da177e4SLinus Torvalds * 28*1da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify 29*1da177e4SLinus Torvalds * it under the terms of the GNU General Public License as published by 30*1da177e4SLinus Torvalds * the Free Software Foundation; either version 2 of the License, or 31*1da177e4SLinus Torvalds * (at your option) any later version. 32*1da177e4SLinus Torvalds * 33*1da177e4SLinus Torvalds */ 34*1da177e4SLinus Torvalds #define MD4_DIGEST_SIZE 16 35*1da177e4SLinus Torvalds #define MD4_HMAC_BLOCK_SIZE 64 36*1da177e4SLinus Torvalds #define MD4_BLOCK_WORDS 16 37*1da177e4SLinus Torvalds #define MD4_HASH_WORDS 4 38*1da177e4SLinus Torvalds 39*1da177e4SLinus Torvalds struct md4_ctx { 40*1da177e4SLinus Torvalds uint32_t hash[MD4_HASH_WORDS]; 41*1da177e4SLinus Torvalds uint32_t block[MD4_BLOCK_WORDS]; 42*1da177e4SLinus Torvalds uint64_t byte_count; 43*1da177e4SLinus Torvalds }; 44*1da177e4SLinus Torvalds 45*1da177e4SLinus Torvalds static inline uint32_t lshift(uint32_t x, unsigned int s) 46*1da177e4SLinus Torvalds { 47*1da177e4SLinus Torvalds x &= 0xFFFFFFFF; 48*1da177e4SLinus Torvalds return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s)); 49*1da177e4SLinus Torvalds } 50*1da177e4SLinus Torvalds 51*1da177e4SLinus Torvalds static inline uint32_t F(uint32_t x, uint32_t y, uint32_t z) 52*1da177e4SLinus Torvalds { 53*1da177e4SLinus Torvalds return (x & y) | ((~x) & z); 54*1da177e4SLinus Torvalds } 55*1da177e4SLinus Torvalds 56*1da177e4SLinus Torvalds static inline uint32_t G(uint32_t x, uint32_t y, uint32_t z) 57*1da177e4SLinus Torvalds { 58*1da177e4SLinus Torvalds return (x & y) | (x & z) | (y & z); 59*1da177e4SLinus Torvalds } 60*1da177e4SLinus Torvalds 61*1da177e4SLinus Torvalds static inline uint32_t H(uint32_t x, uint32_t y, uint32_t z) 62*1da177e4SLinus Torvalds { 63*1da177e4SLinus Torvalds return x ^ y ^ z; 64*1da177e4SLinus Torvalds } 65*1da177e4SLinus Torvalds 66*1da177e4SLinus Torvalds #define ROUND1(a,b,c,d,k,s) (a = lshift(a + F(b,c,d) + k, s)) 67*1da177e4SLinus Torvalds #define ROUND2(a,b,c,d,k,s) (a = lshift(a + G(b,c,d) + k + (uint32_t)0x5A827999,s)) 68*1da177e4SLinus Torvalds #define ROUND3(a,b,c,d,k,s) (a = lshift(a + H(b,c,d) + k + (uint32_t)0x6ED9EBA1,s)) 69*1da177e4SLinus Torvalds 70*1da177e4SLinus Torvalds /* XXX: this stuff can be optimized */ 71*1da177e4SLinus Torvalds static inline void le32_to_cpu_array(uint32_t *buf, unsigned int words) 72*1da177e4SLinus Torvalds { 73*1da177e4SLinus Torvalds while (words--) { 74*1da177e4SLinus Torvalds *buf = ntohl(*buf); 75*1da177e4SLinus Torvalds buf++; 76*1da177e4SLinus Torvalds } 77*1da177e4SLinus Torvalds } 78*1da177e4SLinus Torvalds 79*1da177e4SLinus Torvalds static inline void cpu_to_le32_array(uint32_t *buf, unsigned int words) 80*1da177e4SLinus Torvalds { 81*1da177e4SLinus Torvalds while (words--) { 82*1da177e4SLinus Torvalds *buf = htonl(*buf); 83*1da177e4SLinus Torvalds buf++; 84*1da177e4SLinus Torvalds } 85*1da177e4SLinus Torvalds } 86*1da177e4SLinus Torvalds 87*1da177e4SLinus Torvalds static void md4_transform(uint32_t *hash, uint32_t const *in) 88*1da177e4SLinus Torvalds { 89*1da177e4SLinus Torvalds uint32_t a, b, c, d; 90*1da177e4SLinus Torvalds 91*1da177e4SLinus Torvalds a = hash[0]; 92*1da177e4SLinus Torvalds b = hash[1]; 93*1da177e4SLinus Torvalds c = hash[2]; 94*1da177e4SLinus Torvalds d = hash[3]; 95*1da177e4SLinus Torvalds 96*1da177e4SLinus Torvalds ROUND1(a, b, c, d, in[0], 3); 97*1da177e4SLinus Torvalds ROUND1(d, a, b, c, in[1], 7); 98*1da177e4SLinus Torvalds ROUND1(c, d, a, b, in[2], 11); 99*1da177e4SLinus Torvalds ROUND1(b, c, d, a, in[3], 19); 100*1da177e4SLinus Torvalds ROUND1(a, b, c, d, in[4], 3); 101*1da177e4SLinus Torvalds ROUND1(d, a, b, c, in[5], 7); 102*1da177e4SLinus Torvalds ROUND1(c, d, a, b, in[6], 11); 103*1da177e4SLinus Torvalds ROUND1(b, c, d, a, in[7], 19); 104*1da177e4SLinus Torvalds ROUND1(a, b, c, d, in[8], 3); 105*1da177e4SLinus Torvalds ROUND1(d, a, b, c, in[9], 7); 106*1da177e4SLinus Torvalds ROUND1(c, d, a, b, in[10], 11); 107*1da177e4SLinus Torvalds ROUND1(b, c, d, a, in[11], 19); 108*1da177e4SLinus Torvalds ROUND1(a, b, c, d, in[12], 3); 109*1da177e4SLinus Torvalds ROUND1(d, a, b, c, in[13], 7); 110*1da177e4SLinus Torvalds ROUND1(c, d, a, b, in[14], 11); 111*1da177e4SLinus Torvalds ROUND1(b, c, d, a, in[15], 19); 112*1da177e4SLinus Torvalds 113*1da177e4SLinus Torvalds ROUND2(a, b, c, d,in[ 0], 3); 114*1da177e4SLinus Torvalds ROUND2(d, a, b, c, in[4], 5); 115*1da177e4SLinus Torvalds ROUND2(c, d, a, b, in[8], 9); 116*1da177e4SLinus Torvalds ROUND2(b, c, d, a, in[12], 13); 117*1da177e4SLinus Torvalds ROUND2(a, b, c, d, in[1], 3); 118*1da177e4SLinus Torvalds ROUND2(d, a, b, c, in[5], 5); 119*1da177e4SLinus Torvalds ROUND2(c, d, a, b, in[9], 9); 120*1da177e4SLinus Torvalds ROUND2(b, c, d, a, in[13], 13); 121*1da177e4SLinus Torvalds ROUND2(a, b, c, d, in[2], 3); 122*1da177e4SLinus Torvalds ROUND2(d, a, b, c, in[6], 5); 123*1da177e4SLinus Torvalds ROUND2(c, d, a, b, in[10], 9); 124*1da177e4SLinus Torvalds ROUND2(b, c, d, a, in[14], 13); 125*1da177e4SLinus Torvalds ROUND2(a, b, c, d, in[3], 3); 126*1da177e4SLinus Torvalds ROUND2(d, a, b, c, in[7], 5); 127*1da177e4SLinus Torvalds ROUND2(c, d, a, b, in[11], 9); 128*1da177e4SLinus Torvalds ROUND2(b, c, d, a, in[15], 13); 129*1da177e4SLinus Torvalds 130*1da177e4SLinus Torvalds ROUND3(a, b, c, d,in[ 0], 3); 131*1da177e4SLinus Torvalds ROUND3(d, a, b, c, in[8], 9); 132*1da177e4SLinus Torvalds ROUND3(c, d, a, b, in[4], 11); 133*1da177e4SLinus Torvalds ROUND3(b, c, d, a, in[12], 15); 134*1da177e4SLinus Torvalds ROUND3(a, b, c, d, in[2], 3); 135*1da177e4SLinus Torvalds ROUND3(d, a, b, c, in[10], 9); 136*1da177e4SLinus Torvalds ROUND3(c, d, a, b, in[6], 11); 137*1da177e4SLinus Torvalds ROUND3(b, c, d, a, in[14], 15); 138*1da177e4SLinus Torvalds ROUND3(a, b, c, d, in[1], 3); 139*1da177e4SLinus Torvalds ROUND3(d, a, b, c, in[9], 9); 140*1da177e4SLinus Torvalds ROUND3(c, d, a, b, in[5], 11); 141*1da177e4SLinus Torvalds ROUND3(b, c, d, a, in[13], 15); 142*1da177e4SLinus Torvalds ROUND3(a, b, c, d, in[3], 3); 143*1da177e4SLinus Torvalds ROUND3(d, a, b, c, in[11], 9); 144*1da177e4SLinus Torvalds ROUND3(c, d, a, b, in[7], 11); 145*1da177e4SLinus Torvalds ROUND3(b, c, d, a, in[15], 15); 146*1da177e4SLinus Torvalds 147*1da177e4SLinus Torvalds hash[0] += a; 148*1da177e4SLinus Torvalds hash[1] += b; 149*1da177e4SLinus Torvalds hash[2] += c; 150*1da177e4SLinus Torvalds hash[3] += d; 151*1da177e4SLinus Torvalds } 152*1da177e4SLinus Torvalds 153*1da177e4SLinus Torvalds static inline void md4_transform_helper(struct md4_ctx *ctx) 154*1da177e4SLinus Torvalds { 155*1da177e4SLinus Torvalds le32_to_cpu_array(ctx->block, sizeof(ctx->block) / sizeof(uint32_t)); 156*1da177e4SLinus Torvalds md4_transform(ctx->hash, ctx->block); 157*1da177e4SLinus Torvalds } 158*1da177e4SLinus Torvalds 159*1da177e4SLinus Torvalds static void md4_init(struct md4_ctx *mctx) 160*1da177e4SLinus Torvalds { 161*1da177e4SLinus Torvalds mctx->hash[0] = 0x67452301; 162*1da177e4SLinus Torvalds mctx->hash[1] = 0xefcdab89; 163*1da177e4SLinus Torvalds mctx->hash[2] = 0x98badcfe; 164*1da177e4SLinus Torvalds mctx->hash[3] = 0x10325476; 165*1da177e4SLinus Torvalds mctx->byte_count = 0; 166*1da177e4SLinus Torvalds } 167*1da177e4SLinus Torvalds 168*1da177e4SLinus Torvalds static void md4_update(struct md4_ctx *mctx, 169*1da177e4SLinus Torvalds const unsigned char *data, unsigned int len) 170*1da177e4SLinus Torvalds { 171*1da177e4SLinus Torvalds const uint32_t avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f); 172*1da177e4SLinus Torvalds 173*1da177e4SLinus Torvalds mctx->byte_count += len; 174*1da177e4SLinus Torvalds 175*1da177e4SLinus Torvalds if (avail > len) { 176*1da177e4SLinus Torvalds memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), 177*1da177e4SLinus Torvalds data, len); 178*1da177e4SLinus Torvalds return; 179*1da177e4SLinus Torvalds } 180*1da177e4SLinus Torvalds 181*1da177e4SLinus Torvalds memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), 182*1da177e4SLinus Torvalds data, avail); 183*1da177e4SLinus Torvalds 184*1da177e4SLinus Torvalds md4_transform_helper(mctx); 185*1da177e4SLinus Torvalds data += avail; 186*1da177e4SLinus Torvalds len -= avail; 187*1da177e4SLinus Torvalds 188*1da177e4SLinus Torvalds while (len >= sizeof(mctx->block)) { 189*1da177e4SLinus Torvalds memcpy(mctx->block, data, sizeof(mctx->block)); 190*1da177e4SLinus Torvalds md4_transform_helper(mctx); 191*1da177e4SLinus Torvalds data += sizeof(mctx->block); 192*1da177e4SLinus Torvalds len -= sizeof(mctx->block); 193*1da177e4SLinus Torvalds } 194*1da177e4SLinus Torvalds 195*1da177e4SLinus Torvalds memcpy(mctx->block, data, len); 196*1da177e4SLinus Torvalds } 197*1da177e4SLinus Torvalds 198*1da177e4SLinus Torvalds static void md4_final_ascii(struct md4_ctx *mctx, char *out, unsigned int len) 199*1da177e4SLinus Torvalds { 200*1da177e4SLinus Torvalds const unsigned int offset = mctx->byte_count & 0x3f; 201*1da177e4SLinus Torvalds char *p = (char *)mctx->block + offset; 202*1da177e4SLinus Torvalds int padding = 56 - (offset + 1); 203*1da177e4SLinus Torvalds 204*1da177e4SLinus Torvalds *p++ = 0x80; 205*1da177e4SLinus Torvalds if (padding < 0) { 206*1da177e4SLinus Torvalds memset(p, 0x00, padding + sizeof (uint64_t)); 207*1da177e4SLinus Torvalds md4_transform_helper(mctx); 208*1da177e4SLinus Torvalds p = (char *)mctx->block; 209*1da177e4SLinus Torvalds padding = 56; 210*1da177e4SLinus Torvalds } 211*1da177e4SLinus Torvalds 212*1da177e4SLinus Torvalds memset(p, 0, padding); 213*1da177e4SLinus Torvalds mctx->block[14] = mctx->byte_count << 3; 214*1da177e4SLinus Torvalds mctx->block[15] = mctx->byte_count >> 29; 215*1da177e4SLinus Torvalds le32_to_cpu_array(mctx->block, (sizeof(mctx->block) - 216*1da177e4SLinus Torvalds sizeof(uint64_t)) / sizeof(uint32_t)); 217*1da177e4SLinus Torvalds md4_transform(mctx->hash, mctx->block); 218*1da177e4SLinus Torvalds cpu_to_le32_array(mctx->hash, sizeof(mctx->hash) / sizeof(uint32_t)); 219*1da177e4SLinus Torvalds 220*1da177e4SLinus Torvalds snprintf(out, len, "%08X%08X%08X%08X", 221*1da177e4SLinus Torvalds mctx->hash[0], mctx->hash[1], mctx->hash[2], mctx->hash[3]); 222*1da177e4SLinus Torvalds } 223*1da177e4SLinus Torvalds 224*1da177e4SLinus Torvalds static inline void add_char(unsigned char c, struct md4_ctx *md) 225*1da177e4SLinus Torvalds { 226*1da177e4SLinus Torvalds md4_update(md, &c, 1); 227*1da177e4SLinus Torvalds } 228*1da177e4SLinus Torvalds 229*1da177e4SLinus Torvalds static int parse_string(const char *file, unsigned long len, 230*1da177e4SLinus Torvalds struct md4_ctx *md) 231*1da177e4SLinus Torvalds { 232*1da177e4SLinus Torvalds unsigned long i; 233*1da177e4SLinus Torvalds 234*1da177e4SLinus Torvalds add_char(file[0], md); 235*1da177e4SLinus Torvalds for (i = 1; i < len; i++) { 236*1da177e4SLinus Torvalds add_char(file[i], md); 237*1da177e4SLinus Torvalds if (file[i] == '"' && file[i-1] != '\\') 238*1da177e4SLinus Torvalds break; 239*1da177e4SLinus Torvalds } 240*1da177e4SLinus Torvalds return i; 241*1da177e4SLinus Torvalds } 242*1da177e4SLinus Torvalds 243*1da177e4SLinus Torvalds static int parse_comment(const char *file, unsigned long len) 244*1da177e4SLinus Torvalds { 245*1da177e4SLinus Torvalds unsigned long i; 246*1da177e4SLinus Torvalds 247*1da177e4SLinus Torvalds for (i = 2; i < len; i++) { 248*1da177e4SLinus Torvalds if (file[i-1] == '*' && file[i] == '/') 249*1da177e4SLinus Torvalds break; 250*1da177e4SLinus Torvalds } 251*1da177e4SLinus Torvalds return i; 252*1da177e4SLinus Torvalds } 253*1da177e4SLinus Torvalds 254*1da177e4SLinus Torvalds /* FIXME: Handle .s files differently (eg. # starts comments) --RR */ 255*1da177e4SLinus Torvalds static int parse_file(const signed char *fname, struct md4_ctx *md) 256*1da177e4SLinus Torvalds { 257*1da177e4SLinus Torvalds signed char *file; 258*1da177e4SLinus Torvalds unsigned long i, len; 259*1da177e4SLinus Torvalds 260*1da177e4SLinus Torvalds file = grab_file(fname, &len); 261*1da177e4SLinus Torvalds if (!file) 262*1da177e4SLinus Torvalds return 0; 263*1da177e4SLinus Torvalds 264*1da177e4SLinus Torvalds for (i = 0; i < len; i++) { 265*1da177e4SLinus Torvalds /* Collapse and ignore \ and CR. */ 266*1da177e4SLinus Torvalds if (file[i] == '\\' && (i+1 < len) && file[i+1] == '\n') { 267*1da177e4SLinus Torvalds i++; 268*1da177e4SLinus Torvalds continue; 269*1da177e4SLinus Torvalds } 270*1da177e4SLinus Torvalds 271*1da177e4SLinus Torvalds /* Ignore whitespace */ 272*1da177e4SLinus Torvalds if (isspace(file[i])) 273*1da177e4SLinus Torvalds continue; 274*1da177e4SLinus Torvalds 275*1da177e4SLinus Torvalds /* Handle strings as whole units */ 276*1da177e4SLinus Torvalds if (file[i] == '"') { 277*1da177e4SLinus Torvalds i += parse_string(file+i, len - i, md); 278*1da177e4SLinus Torvalds continue; 279*1da177e4SLinus Torvalds } 280*1da177e4SLinus Torvalds 281*1da177e4SLinus Torvalds /* Comments: ignore */ 282*1da177e4SLinus Torvalds if (file[i] == '/' && file[i+1] == '*') { 283*1da177e4SLinus Torvalds i += parse_comment(file+i, len - i); 284*1da177e4SLinus Torvalds continue; 285*1da177e4SLinus Torvalds } 286*1da177e4SLinus Torvalds 287*1da177e4SLinus Torvalds add_char(file[i], md); 288*1da177e4SLinus Torvalds } 289*1da177e4SLinus Torvalds release_file(file, len); 290*1da177e4SLinus Torvalds return 1; 291*1da177e4SLinus Torvalds } 292*1da177e4SLinus Torvalds 293*1da177e4SLinus Torvalds /* We have dir/file.o. Open dir/.file.o.cmd, look for deps_ line to 294*1da177e4SLinus Torvalds * figure out source file. */ 295*1da177e4SLinus Torvalds static int parse_source_files(const char *objfile, struct md4_ctx *md) 296*1da177e4SLinus Torvalds { 297*1da177e4SLinus Torvalds char *cmd, *file, *line, *dir; 298*1da177e4SLinus Torvalds const char *base; 299*1da177e4SLinus Torvalds unsigned long flen, pos = 0; 300*1da177e4SLinus Torvalds int dirlen, ret = 0, check_files = 0; 301*1da177e4SLinus Torvalds 302*1da177e4SLinus Torvalds cmd = NOFAIL(malloc(strlen(objfile) + sizeof("..cmd"))); 303*1da177e4SLinus Torvalds 304*1da177e4SLinus Torvalds base = strrchr(objfile, '/'); 305*1da177e4SLinus Torvalds if (base) { 306*1da177e4SLinus Torvalds base++; 307*1da177e4SLinus Torvalds dirlen = base - objfile; 308*1da177e4SLinus Torvalds sprintf(cmd, "%.*s.%s.cmd", dirlen, objfile, base); 309*1da177e4SLinus Torvalds } else { 310*1da177e4SLinus Torvalds dirlen = 0; 311*1da177e4SLinus Torvalds sprintf(cmd, ".%s.cmd", objfile); 312*1da177e4SLinus Torvalds } 313*1da177e4SLinus Torvalds dir = NOFAIL(malloc(dirlen + 1)); 314*1da177e4SLinus Torvalds strncpy(dir, objfile, dirlen); 315*1da177e4SLinus Torvalds dir[dirlen] = '\0'; 316*1da177e4SLinus Torvalds 317*1da177e4SLinus Torvalds file = grab_file(cmd, &flen); 318*1da177e4SLinus Torvalds if (!file) { 319*1da177e4SLinus Torvalds fprintf(stderr, "Warning: could not find %s for %s\n", 320*1da177e4SLinus Torvalds cmd, objfile); 321*1da177e4SLinus Torvalds goto out; 322*1da177e4SLinus Torvalds } 323*1da177e4SLinus Torvalds 324*1da177e4SLinus Torvalds /* There will be a line like so: 325*1da177e4SLinus Torvalds deps_drivers/net/dummy.o := \ 326*1da177e4SLinus Torvalds drivers/net/dummy.c \ 327*1da177e4SLinus Torvalds $(wildcard include/config/net/fastroute.h) \ 328*1da177e4SLinus Torvalds include/linux/config.h \ 329*1da177e4SLinus Torvalds $(wildcard include/config/h.h) \ 330*1da177e4SLinus Torvalds include/linux/module.h \ 331*1da177e4SLinus Torvalds 332*1da177e4SLinus Torvalds Sum all files in the same dir or subdirs. 333*1da177e4SLinus Torvalds */ 334*1da177e4SLinus Torvalds while ((line = get_next_line(&pos, file, flen)) != NULL) { 335*1da177e4SLinus Torvalds signed char* p = line; 336*1da177e4SLinus Torvalds if (strncmp(line, "deps_", sizeof("deps_")-1) == 0) { 337*1da177e4SLinus Torvalds check_files = 1; 338*1da177e4SLinus Torvalds continue; 339*1da177e4SLinus Torvalds } 340*1da177e4SLinus Torvalds if (!check_files) 341*1da177e4SLinus Torvalds continue; 342*1da177e4SLinus Torvalds 343*1da177e4SLinus Torvalds /* Continue until line does not end with '\' */ 344*1da177e4SLinus Torvalds if ( *(p + strlen(p)-1) != '\\') 345*1da177e4SLinus Torvalds break; 346*1da177e4SLinus Torvalds /* Terminate line at first space, to get rid of final ' \' */ 347*1da177e4SLinus Torvalds while (*p) { 348*1da177e4SLinus Torvalds if (isspace(*p)) { 349*1da177e4SLinus Torvalds *p = '\0'; 350*1da177e4SLinus Torvalds break; 351*1da177e4SLinus Torvalds } 352*1da177e4SLinus Torvalds p++; 353*1da177e4SLinus Torvalds } 354*1da177e4SLinus Torvalds 355*1da177e4SLinus Torvalds /* Check if this file is in same dir as objfile */ 356*1da177e4SLinus Torvalds if ((strstr(line, dir)+strlen(dir)-1) == strrchr(line, '/')) { 357*1da177e4SLinus Torvalds if (!parse_file(line, md)) { 358*1da177e4SLinus Torvalds fprintf(stderr, 359*1da177e4SLinus Torvalds "Warning: could not open %s: %s\n", 360*1da177e4SLinus Torvalds line, strerror(errno)); 361*1da177e4SLinus Torvalds goto out_file; 362*1da177e4SLinus Torvalds } 363*1da177e4SLinus Torvalds 364*1da177e4SLinus Torvalds } 365*1da177e4SLinus Torvalds 366*1da177e4SLinus Torvalds } 367*1da177e4SLinus Torvalds 368*1da177e4SLinus Torvalds /* Everyone parsed OK */ 369*1da177e4SLinus Torvalds ret = 1; 370*1da177e4SLinus Torvalds out_file: 371*1da177e4SLinus Torvalds release_file(file, flen); 372*1da177e4SLinus Torvalds out: 373*1da177e4SLinus Torvalds free(dir); 374*1da177e4SLinus Torvalds free(cmd); 375*1da177e4SLinus Torvalds return ret; 376*1da177e4SLinus Torvalds } 377*1da177e4SLinus Torvalds 378*1da177e4SLinus Torvalds /* Calc and record src checksum. */ 379*1da177e4SLinus Torvalds void get_src_version(const char *modname, char sum[], unsigned sumlen) 380*1da177e4SLinus Torvalds { 381*1da177e4SLinus Torvalds void *file; 382*1da177e4SLinus Torvalds unsigned long len; 383*1da177e4SLinus Torvalds struct md4_ctx md; 384*1da177e4SLinus Torvalds char *sources, *end, *fname; 385*1da177e4SLinus Torvalds const char *basename; 386*1da177e4SLinus Torvalds char filelist[strlen(getenv("MODVERDIR")) + strlen("/") + 387*1da177e4SLinus Torvalds strlen(modname) - strlen(".o") + strlen(".mod") + 1 ]; 388*1da177e4SLinus Torvalds 389*1da177e4SLinus Torvalds /* Source files for module are in .tmp_versions/modname.mod, 390*1da177e4SLinus Torvalds after the first line. */ 391*1da177e4SLinus Torvalds if (strrchr(modname, '/')) 392*1da177e4SLinus Torvalds basename = strrchr(modname, '/') + 1; 393*1da177e4SLinus Torvalds else 394*1da177e4SLinus Torvalds basename = modname; 395*1da177e4SLinus Torvalds sprintf(filelist, "%s/%.*s.mod", getenv("MODVERDIR"), 396*1da177e4SLinus Torvalds (int) strlen(basename) - 2, basename); 397*1da177e4SLinus Torvalds 398*1da177e4SLinus Torvalds file = grab_file(filelist, &len); 399*1da177e4SLinus Torvalds if (!file) { 400*1da177e4SLinus Torvalds fprintf(stderr, "Warning: could not find versions for %s\n", 401*1da177e4SLinus Torvalds filelist); 402*1da177e4SLinus Torvalds return; 403*1da177e4SLinus Torvalds } 404*1da177e4SLinus Torvalds 405*1da177e4SLinus Torvalds sources = strchr(file, '\n'); 406*1da177e4SLinus Torvalds if (!sources) { 407*1da177e4SLinus Torvalds fprintf(stderr, "Warning: malformed versions file for %s\n", 408*1da177e4SLinus Torvalds modname); 409*1da177e4SLinus Torvalds goto release; 410*1da177e4SLinus Torvalds } 411*1da177e4SLinus Torvalds 412*1da177e4SLinus Torvalds sources++; 413*1da177e4SLinus Torvalds end = strchr(sources, '\n'); 414*1da177e4SLinus Torvalds if (!end) { 415*1da177e4SLinus Torvalds fprintf(stderr, "Warning: bad ending versions file for %s\n", 416*1da177e4SLinus Torvalds modname); 417*1da177e4SLinus Torvalds goto release; 418*1da177e4SLinus Torvalds } 419*1da177e4SLinus Torvalds *end = '\0'; 420*1da177e4SLinus Torvalds 421*1da177e4SLinus Torvalds md4_init(&md); 422*1da177e4SLinus Torvalds while ((fname = strsep(&sources, " ")) != NULL) { 423*1da177e4SLinus Torvalds if (!*fname) 424*1da177e4SLinus Torvalds continue; 425*1da177e4SLinus Torvalds if (!parse_source_files(fname, &md)) 426*1da177e4SLinus Torvalds goto release; 427*1da177e4SLinus Torvalds } 428*1da177e4SLinus Torvalds 429*1da177e4SLinus Torvalds md4_final_ascii(&md, sum, sumlen); 430*1da177e4SLinus Torvalds release: 431*1da177e4SLinus Torvalds release_file(file, len); 432*1da177e4SLinus Torvalds } 433*1da177e4SLinus Torvalds 434*1da177e4SLinus Torvalds static void write_version(const char *filename, const char *sum, 435*1da177e4SLinus Torvalds unsigned long offset) 436*1da177e4SLinus Torvalds { 437*1da177e4SLinus Torvalds int fd; 438*1da177e4SLinus Torvalds 439*1da177e4SLinus Torvalds fd = open(filename, O_RDWR); 440*1da177e4SLinus Torvalds if (fd < 0) { 441*1da177e4SLinus Torvalds fprintf(stderr, "Warning: changing sum in %s failed: %s\n", 442*1da177e4SLinus Torvalds filename, strerror(errno)); 443*1da177e4SLinus Torvalds return; 444*1da177e4SLinus Torvalds } 445*1da177e4SLinus Torvalds 446*1da177e4SLinus Torvalds if (lseek(fd, offset, SEEK_SET) == (off_t)-1) { 447*1da177e4SLinus Torvalds fprintf(stderr, "Warning: changing sum in %s:%lu failed: %s\n", 448*1da177e4SLinus Torvalds filename, offset, strerror(errno)); 449*1da177e4SLinus Torvalds goto out; 450*1da177e4SLinus Torvalds } 451*1da177e4SLinus Torvalds 452*1da177e4SLinus Torvalds if (write(fd, sum, strlen(sum)+1) != strlen(sum)+1) { 453*1da177e4SLinus Torvalds fprintf(stderr, "Warning: writing sum in %s failed: %s\n", 454*1da177e4SLinus Torvalds filename, strerror(errno)); 455*1da177e4SLinus Torvalds goto out; 456*1da177e4SLinus Torvalds } 457*1da177e4SLinus Torvalds out: 458*1da177e4SLinus Torvalds close(fd); 459*1da177e4SLinus Torvalds } 460*1da177e4SLinus Torvalds 461*1da177e4SLinus Torvalds static int strip_rcs_crap(signed char *version) 462*1da177e4SLinus Torvalds { 463*1da177e4SLinus Torvalds unsigned int len, full_len; 464*1da177e4SLinus Torvalds 465*1da177e4SLinus Torvalds if (strncmp(version, "$Revision", strlen("$Revision")) != 0) 466*1da177e4SLinus Torvalds return 0; 467*1da177e4SLinus Torvalds 468*1da177e4SLinus Torvalds /* Space for version string follows. */ 469*1da177e4SLinus Torvalds full_len = strlen(version) + strlen(version + strlen(version) + 1) + 2; 470*1da177e4SLinus Torvalds 471*1da177e4SLinus Torvalds /* Move string to start with version number: prefix will be 472*1da177e4SLinus Torvalds * $Revision$ or $Revision: */ 473*1da177e4SLinus Torvalds len = strlen("$Revision"); 474*1da177e4SLinus Torvalds if (version[len] == ':' || version[len] == '$') 475*1da177e4SLinus Torvalds len++; 476*1da177e4SLinus Torvalds while (isspace(version[len])) 477*1da177e4SLinus Torvalds len++; 478*1da177e4SLinus Torvalds memmove(version, version+len, full_len-len); 479*1da177e4SLinus Torvalds full_len -= len; 480*1da177e4SLinus Torvalds 481*1da177e4SLinus Torvalds /* Preserve up to next whitespace. */ 482*1da177e4SLinus Torvalds len = 0; 483*1da177e4SLinus Torvalds while (version[len] && !isspace(version[len])) 484*1da177e4SLinus Torvalds len++; 485*1da177e4SLinus Torvalds memmove(version + len, version + strlen(version), 486*1da177e4SLinus Torvalds full_len - strlen(version)); 487*1da177e4SLinus Torvalds return 1; 488*1da177e4SLinus Torvalds } 489*1da177e4SLinus Torvalds 490*1da177e4SLinus Torvalds /* Clean up RCS-style version numbers. */ 491*1da177e4SLinus Torvalds void maybe_frob_rcs_version(const char *modfilename, 492*1da177e4SLinus Torvalds char *version, 493*1da177e4SLinus Torvalds void *modinfo, 494*1da177e4SLinus Torvalds unsigned long version_offset) 495*1da177e4SLinus Torvalds { 496*1da177e4SLinus Torvalds if (strip_rcs_crap(version)) 497*1da177e4SLinus Torvalds write_version(modfilename, version, version_offset); 498*1da177e4SLinus Torvalds } 499