lkml.org 
[lkml]   [2004]   [Feb]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    SubjectRe: Question on MODULE_VERSION macro
    Date
    In message <20040223211718.GA7610@mars.ravnborg.org> you write:
    > But this information is already available in the .module.o.cmd file,
    > so no reason to parse that information up from the .c file -
    > and eventually having troubles with .s files.
    >
    > You can get rid of parse_cpp_line(), include_file(),
    > and some of the helpers when implementing this algorithm. So all
    > in all a good simplification.

    Yep, fixed this, and fixed the broken modules_install for Andrew.
    This one actually boot tested.

    > Note also that in the original implementation you have missed
    > release_file() in a few places. But when you implement the above
    > you will hit them.

    Fixed them too.

    Rusty.
    --
    Anyone who quotes me in their sig is an idiot. -- Rusty Russell.

    Name: Add a MODULE_VERSION macro
    Author: Rusty Russell
    Status: Tested on 2.6.3-bk4

    At the kernel summit, various people asked for a MODULE_VERSION
    macro to store module strings (for later access through sysfs).
    A simple md4 is needed to identify changes in modules which,
    inevitably, do not update the version. It skips whitespace and
    comments, and includes #includes which are in the same dir.

    The module versions should be set according to this definition,
    based on the RPM one, or CVS Revision tags. Violators will be shot.

    [<epoch>`:']<version>[`-'<extraversion>]
    <epoch>: A (small) unsigned integer which allows you to start versions
    anew. If not mentioned, it's zero. eg. "2:1.0" is after
    "1:2.0".
    <version>: The <version> may contain only alphanumerics.
    <extraversion>: Like <version>, but inserted for local
    customizations, eg "rh3" or "rusty1".

    Comparison of two versions (assuming same epoch):

    Split each into all-digit and all-alphabetical parts. Compare each
    one one at a time: digit parts numerically, alphabetical in ASCII
    order. So 0.10 comes after 0.9.

    diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .29265-linux-2.6.3-bk4/include/linux/module.h .29265-linux-2.6.3-bk4.updated/include/linux/module.h
    --- .29265-linux-2.6.3-bk4/include/linux/module.h 2004-02-04 15:39:14.000000000 +1100
    +++ .29265-linux-2.6.3-bk4.updated/include/linux/module.h 2004-02-24 13:31:33.000000000 +1100
    @@ -127,6 +127,24 @@ extern const struct gtype##_id __mod_##g
    #define MODULE_DEVICE_TABLE(type,name) \
    MODULE_GENERIC_TABLE(type##_device,name)

    +/* Version of form [<epoch>:]<version>[-<extra-version>].
    + Or for CVS/RCS ID version, everything but the number is stripped.
    + <epoch>: A (small) unsigned integer which allows you to start versions
    + anew. If not mentioned, it's zero. eg. "2:1.0" is after
    + "1:2.0".
    + <version>: The <version> may contain only alphanumerics and the
    + character `.'. Ordered by numeric sort for numeric parts,
    + ascii sort for ascii parts (as per RPM or DEB algorithm).
    + <extraversion>: Like <version>, but inserted for local
    + customizations, eg "rh3" or "rusty1".
    +
    + Using this automatically adds a checksum of the .c files and the
    + local headers to the end. Use MODULE_VERSION("") if you want just
    + this. Macro includes room for this.
    +*/
    +#define MODULE_VERSION(_version) \
    + MODULE_INFO(version, _version "\0xxxxxxxxxxxxxxxxxxxxxxxx")
    +
    /* Given an address, look for it in the exception tables */
    const struct exception_table_entry *search_exception_tables(unsigned long add);

    diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .29265-linux-2.6.3-bk4/scripts/Makefile .29265-linux-2.6.3-bk4.updated/scripts/Makefile
    --- .29265-linux-2.6.3-bk4/scripts/Makefile 2003-09-29 10:26:16.000000000 +1000
    +++ .29265-linux-2.6.3-bk4.updated/scripts/Makefile 2004-02-24 13:31:33.000000000 +1100
    @@ -12,7 +12,7 @@ host-progs := fixdep split-include conma
    mk_elfconfig pnmtologo bin2c
    always := $(host-progs) empty.o

    -modpost-objs := modpost.o file2alias.o
    +modpost-objs := modpost.o file2alias.o sumversion.o

    subdir-$(CONFIG_MODVERSIONS) += genksyms

    @@ -24,7 +24,7 @@ $(addprefix $(obj)/,$(filter-out fixdep,

    # dependencies on generated files need to be listed explicitly

    -$(obj)/modpost.o $(obj)/file2alias.o: $(obj)/elfconfig.h
    +$(obj)/modpost.o $(obj)/file2alias.o $(obj)/sumversion.o: $(obj)/elfconfig.h

    quiet_cmd_elfconfig = MKELF $@
    cmd_elfconfig = $(obj)/mk_elfconfig $(ARCH) < $< > $@
    diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .29265-linux-2.6.3-bk4/scripts/Makefile.build .29265-linux-2.6.3-bk4.updated/scripts/Makefile.build
    --- .29265-linux-2.6.3-bk4/scripts/Makefile.build 2003-10-09 18:03:05.000000000 +1000
    +++ .29265-linux-2.6.3-bk4.updated/scripts/Makefile.build 2004-02-24 13:31:33.000000000 +1100
    @@ -64,8 +64,6 @@ endif

    # We keep a list of all modules in $(MODVERDIR)

    -touch-module = @echo $(@:.o=.ko) > $(MODVERDIR)/$(@F:.o=.mod)
    -
    __build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
    $(if $(KBUILD_MODULES),$(obj-m)) \
    $(subdir-ym) $(always)
    @@ -178,7 +176,7 @@ endef

    $(single-used-m): %.o: %.c FORCE
    $(call if_changed_rule,cc_o_c)
    - $(touch-module)
    + @{ echo $(@:.o=.ko); echo $@; } > $(MODVERDIR)/$(@F:.o=.mod)

    quiet_cmd_cc_lst_c = MKLST $@
    cmd_cc_lst_c = $(CC) $(c_flags) -g -c -o $*.o $< && \
    @@ -273,7 +271,7 @@ $(multi-used-y) : %.o: $(multi-objs-y) F

    $(multi-used-m) : %.o: $(multi-objs-m) FORCE
    $(call if_changed,link_multi-m)
    - $(touch-module)
    + @{ echo $(@:.o=.ko); echo $(link_multi_deps); } > $(MODVERDIR)/$(@F:.o=.mod)

    targets += $(multi-used-y) $(multi-used-m)

    diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .29265-linux-2.6.3-bk4/scripts/Makefile.modinst .29265-linux-2.6.3-bk4.updated/scripts/Makefile.modinst
    --- .29265-linux-2.6.3-bk4/scripts/Makefile.modinst 2003-09-22 10:04:52.000000000 +1000
    +++ .29265-linux-2.6.3-bk4.updated/scripts/Makefile.modinst 2004-02-24 13:31:33.000000000 +1100
    @@ -9,7 +9,7 @@ include scripts/Makefile.lib

    #

    -__modules := $(shell cat /dev/null $(wildcard $(MODVERDIR)/*.mod))
    +__modules := $(shell head -q -n1 /dev/null $(wildcard $(MODVERDIR)/*.mod))
    modules := $(patsubst %.o,%.ko,$(wildcard $(__modules:.ko=.o)))

    ifneq ($(filter-out $(modules),$(__modules)),)
    diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .29265-linux-2.6.3-bk4/scripts/Makefile.modpost .29265-linux-2.6.3-bk4.updated/scripts/Makefile.modpost
    --- .29265-linux-2.6.3-bk4/scripts/Makefile.modpost 2003-09-29 10:26:16.000000000 +1000
    +++ .29265-linux-2.6.3-bk4.updated/scripts/Makefile.modpost 2004-02-24 13:31:33.000000000 +1100
    @@ -10,10 +10,11 @@ include scripts/Makefile.lib

    #

    -__modules := $(shell cat /dev/null $(wildcard $(MODVERDIR)/*.mod))
    +__modules := $(shell head -q -n1 /dev/null $(wildcard $(MODVERDIR)/*.mod))
    modules := $(patsubst %.o,%.ko,$(wildcard $(__modules:.ko=.o)))

    ifneq ($(filter-out $(modules),$(__modules)),)
    + $(warning Trouble: $(__modules) )
    $(warning *** Uh-oh, you have stale module entries. You messed with SUBDIRS,)
    $(warning do not complain if something goes wrong.)
    endif
    diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .29265-linux-2.6.3-bk4/scripts/modpost.c .29265-linux-2.6.3-bk4.updated/scripts/modpost.c
    --- .29265-linux-2.6.3-bk4/scripts/modpost.c 2004-02-18 23:54:38.000000000 +1100
    +++ .29265-linux-2.6.3-bk4.updated/scripts/modpost.c 2004-02-24 13:31:33.000000000 +1100
    @@ -65,15 +65,15 @@ new_module(char *modname)
    struct module *mod;
    char *p;

    + mod = NOFAIL(malloc(sizeof(*mod)));
    + memset(mod, 0, sizeof(*mod));
    + mod->name = NOFAIL(strdup(modname));
    +
    /* strip trailing .o */
    - p = strstr(modname, ".o");
    + p = strstr(mod->name, ".o");
    if (p)
    *p = 0;

    - mod = NOFAIL(malloc(sizeof(*mod)));
    - memset(mod, 0, sizeof(*mod));
    - mod->name = modname;
    -
    /* add to list */
    mod->next = modules;
    modules = mod;
    @@ -194,26 +194,25 @@ grab_file(const char *filename, unsigned
    int fd;

    fd = open(filename, O_RDONLY);
    - if (fd < 0) {
    - perror(filename);
    - abort();
    - }
    - if (fstat(fd, &st) != 0) {
    - perror(filename);
    - abort();
    - }
    + if (fstat(fd, &st) != 0)
    + return NULL;

    *size = st.st_size;
    map = mmap(NULL, *size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
    - if (map == MAP_FAILED) {
    - perror(filename);
    - abort();
    - }
    close(fd);
    +
    + if (map == MAP_FAILED)
    + return NULL;
    return map;
    }

    void
    +release_file(void *file, unsigned long size)
    +{
    + munmap(file, size);
    +}
    +
    +void
    parse_elf(struct elf_info *info, const char *filename)
    {
    unsigned int i;
    @@ -222,6 +221,10 @@ parse_elf(struct elf_info *info, const c
    Elf_Sym *sym;

    hdr = grab_file(filename, &info->size);
    + if (!hdr) {
    + perror(filename);
    + abort();
    + }
    info->hdr = hdr;
    if (info->size < sizeof(*hdr))
    goto truncated;
    @@ -239,11 +242,19 @@ parse_elf(struct elf_info *info, const c
    sechdrs[i].sh_offset = TO_NATIVE(sechdrs[i].sh_offset);
    sechdrs[i].sh_size = TO_NATIVE(sechdrs[i].sh_size);
    sechdrs[i].sh_link = TO_NATIVE(sechdrs[i].sh_link);
    + sechdrs[i].sh_name = TO_NATIVE(sechdrs[i].sh_name);
    }
    /* Find symbol table. */
    for (i = 1; i < hdr->e_shnum; i++) {
    + const char *secstrings
    + = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
    +
    if (sechdrs[i].sh_offset > info->size)
    goto truncated;
    + if (strcmp(secstrings+sechdrs[i].sh_name, ".modinfo") == 0) {
    + info->modinfo = (void *)hdr + sechdrs[i].sh_offset;
    + info->modinfo_len = sechdrs[i].sh_size;
    + }
    if (sechdrs[i].sh_type != SHT_SYMTAB)
    continue;

    @@ -274,7 +285,7 @@ parse_elf(struct elf_info *info, const c
    void
    parse_elf_finish(struct elf_info *info)
    {
    - munmap(info->hdr, info->size);
    + release_file(info->hdr, info->size);
    }

    #define CRC_PFX MODULE_SYMBOL_PREFIX "__crc_"
    @@ -372,6 +383,8 @@ read_symbols(char *modname)
    handle_modversions(mod, &info, sym, symname);
    handle_moddevtable(mod, &info, sym, symname);
    }
    + maybe_frob_version(modname, info.modinfo, info.modinfo_len,
    + (void *)info.modinfo - (void *)info.hdr);
    parse_elf_finish(&info);

    /* Our trick to get versioning for struct_module - it's
    diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .29265-linux-2.6.3-bk4/scripts/modpost.h .29265-linux-2.6.3-bk4.updated/scripts/modpost.h
    --- .29265-linux-2.6.3-bk4/scripts/modpost.h 2003-09-22 10:06:44.000000000 +1000
    +++ .29265-linux-2.6.3-bk4.updated/scripts/modpost.h 2004-02-24 13:31:33.000000000 +1100
    @@ -80,9 +80,19 @@ struct elf_info {
    Elf_Sym *symtab_start;
    Elf_Sym *symtab_stop;
    const char *strtab;
    + char *modinfo;
    + unsigned int modinfo_len;
    };

    void handle_moddevtable(struct module *mod, struct elf_info *info,
    Elf_Sym *sym, const char *symname);

    void add_moddevtable(struct buffer *buf, struct module *mod);
    +
    +void maybe_frob_version(const char *modfilename,
    + void *modinfo,
    + unsigned long modinfo_len,
    + unsigned long modinfo_offset);
    +
    +void *grab_file(const char *filename, unsigned long *size);
    +void release_file(void *file, unsigned long size);
    diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .29265-linux-2.6.3-bk4/scripts/sumversion.c .29265-linux-2.6.3-bk4.updated/scripts/sumversion.c
    --- .29265-linux-2.6.3-bk4/scripts/sumversion.c 1970-01-01 10:00:00.000000000 +1000
    +++ .29265-linux-2.6.3-bk4.updated/scripts/sumversion.c 2004-02-24 13:32:58.000000000 +1100
    @@ -0,0 +1,550 @@
    +#include <netinet/in.h>
    +#include <stdint.h>
    +#include <ctype.h>
    +#include <errno.h>
    +#include <string.h>
    +#include "modpost.h"
    +
    +/* Parse tag=value strings from .modinfo section */
    +static char *next_string(char *string, unsigned long *secsize)
    +{
    + /* Skip non-zero chars */
    + while (string[0]) {
    + string++;
    + if ((*secsize)-- <= 1)
    + return NULL;
    + }
    +
    + /* Skip any zero padding. */
    + while (!string[0]) {
    + string++;
    + if ((*secsize)-- <= 1)
    + return NULL;
    + }
    + return string;
    +}
    +
    +static char *get_modinfo(void *modinfo, unsigned long modinfo_len,
    + const char *tag)
    +{
    + char *p;
    + unsigned int taglen = strlen(tag);
    + unsigned long size = modinfo_len;
    +
    + for (p = modinfo; p; p = next_string(p, &size)) {
    + if (strncmp(p, tag, taglen) == 0 && p[taglen] == '=')
    + return p + taglen + 1;
    + }
    + return NULL;
    +}
    +
    +/*
    + * Stolen form Cryptographic API.
    + *
    + * MD4 Message Digest Algorithm (RFC1320).
    + *
    + * Implementation derived from Andrew Tridgell and Steve French's
    + * CIFS MD4 implementation, and the cryptoapi implementation
    + * originally based on the public domain implementation written
    + * by Colin Plumb in 1993.
    + *
    + * Copyright (c) Andrew Tridgell 1997-1998.
    + * Modified by Steve French (sfrench@us.ibm.com) 2002
    + * Copyright (c) Cryptoapi developers.
    + * Copyright (c) 2002 David S. Miller (davem@redhat.com)
    + * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
    + *
    + * This program is free software; you can redistribute it and/or modify
    + * it under the terms of the GNU General Public License as published by
    + * the Free Software Foundation; either version 2 of the License, or
    + * (at your option) any later version.
    + *
    + */
    +#define MD4_DIGEST_SIZE 16
    +#define MD4_HMAC_BLOCK_SIZE 64
    +#define MD4_BLOCK_WORDS 16
    +#define MD4_HASH_WORDS 4
    +
    +struct md4_ctx {
    + uint32_t hash[MD4_HASH_WORDS];
    + uint32_t block[MD4_BLOCK_WORDS];
    + uint64_t byte_count;
    +};
    +
    +static inline uint32_t lshift(uint32_t x, unsigned int s)
    +{
    + x &= 0xFFFFFFFF;
    + return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s));
    +}
    +
    +static inline uint32_t F(uint32_t x, uint32_t y, uint32_t z)
    +{
    + return (x & y) | ((~x) & z);
    +}
    +
    +static inline uint32_t G(uint32_t x, uint32_t y, uint32_t z)
    +{
    + return (x & y) | (x & z) | (y & z);
    +}
    +
    +static inline uint32_t H(uint32_t x, uint32_t y, uint32_t z)
    +{
    + return x ^ y ^ z;
    +}
    +
    +#define ROUND1(a,b,c,d,k,s) (a = lshift(a + F(b,c,d) + k, s))
    +#define ROUND2(a,b,c,d,k,s) (a = lshift(a + G(b,c,d) + k + (uint32_t)0x5A827999,s))
    +#define ROUND3(a,b,c,d,k,s) (a = lshift(a + H(b,c,d) + k + (uint32_t)0x6ED9EBA1,s))
    +
    +/* XXX: this stuff can be optimized */
    +static inline void le32_to_cpu_array(uint32_t *buf, unsigned int words)
    +{
    + while (words--) {
    + *buf = ntohl(*buf);
    + buf++;
    + }
    +}
    +
    +static inline void cpu_to_le32_array(uint32_t *buf, unsigned int words)
    +{
    + while (words--) {
    + *buf = htonl(*buf);
    + buf++;
    + }
    +}
    +
    +static void md4_transform(uint32_t *hash, uint32_t const *in)
    +{
    + uint32_t a, b, c, d;
    +
    + a = hash[0];
    + b = hash[1];
    + c = hash[2];
    + d = hash[3];
    +
    + ROUND1(a, b, c, d, in[0], 3);
    + ROUND1(d, a, b, c, in[1], 7);
    + ROUND1(c, d, a, b, in[2], 11);
    + ROUND1(b, c, d, a, in[3], 19);
    + ROUND1(a, b, c, d, in[4], 3);
    + ROUND1(d, a, b, c, in[5], 7);
    + ROUND1(c, d, a, b, in[6], 11);
    + ROUND1(b, c, d, a, in[7], 19);
    + ROUND1(a, b, c, d, in[8], 3);
    + ROUND1(d, a, b, c, in[9], 7);
    + ROUND1(c, d, a, b, in[10], 11);
    + ROUND1(b, c, d, a, in[11], 19);
    + ROUND1(a, b, c, d, in[12], 3);
    + ROUND1(d, a, b, c, in[13], 7);
    + ROUND1(c, d, a, b, in[14], 11);
    + ROUND1(b, c, d, a, in[15], 19);
    +
    + ROUND2(a, b, c, d,in[ 0], 3);
    + ROUND2(d, a, b, c, in[4], 5);
    + ROUND2(c, d, a, b, in[8], 9);
    + ROUND2(b, c, d, a, in[12], 13);
    + ROUND2(a, b, c, d, in[1], 3);
    + ROUND2(d, a, b, c, in[5], 5);
    + ROUND2(c, d, a, b, in[9], 9);
    + ROUND2(b, c, d, a, in[13], 13);
    + ROUND2(a, b, c, d, in[2], 3);
    + ROUND2(d, a, b, c, in[6], 5);
    + ROUND2(c, d, a, b, in[10], 9);
    + ROUND2(b, c, d, a, in[14], 13);
    + ROUND2(a, b, c, d, in[3], 3);
    + ROUND2(d, a, b, c, in[7], 5);
    + ROUND2(c, d, a, b, in[11], 9);
    + ROUND2(b, c, d, a, in[15], 13);
    +
    + ROUND3(a, b, c, d,in[ 0], 3);
    + ROUND3(d, a, b, c, in[8], 9);
    + ROUND3(c, d, a, b, in[4], 11);
    + ROUND3(b, c, d, a, in[12], 15);
    + ROUND3(a, b, c, d, in[2], 3);
    + ROUND3(d, a, b, c, in[10], 9);
    + ROUND3(c, d, a, b, in[6], 11);
    + ROUND3(b, c, d, a, in[14], 15);
    + ROUND3(a, b, c, d, in[1], 3);
    + ROUND3(d, a, b, c, in[9], 9);
    + ROUND3(c, d, a, b, in[5], 11);
    + ROUND3(b, c, d, a, in[13], 15);
    + ROUND3(a, b, c, d, in[3], 3);
    + ROUND3(d, a, b, c, in[11], 9);
    + ROUND3(c, d, a, b, in[7], 11);
    + ROUND3(b, c, d, a, in[15], 15);
    +
    + hash[0] += a;
    + hash[1] += b;
    + hash[2] += c;
    + hash[3] += d;
    +}
    +
    +static inline void md4_transform_helper(struct md4_ctx *ctx)
    +{
    + le32_to_cpu_array(ctx->block, sizeof(ctx->block) / sizeof(uint32_t));
    + md4_transform(ctx->hash, ctx->block);
    +}
    +
    +static void md4_init(struct md4_ctx *mctx)
    +{
    + mctx->hash[0] = 0x67452301;
    + mctx->hash[1] = 0xefcdab89;
    + mctx->hash[2] = 0x98badcfe;
    + mctx->hash[3] = 0x10325476;
    + mctx->byte_count = 0;
    +}
    +
    +static void md4_update(struct md4_ctx *mctx,
    + const unsigned char *data, unsigned int len)
    +{
    + const uint32_t avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f);
    +
    + mctx->byte_count += len;
    +
    + if (avail > len) {
    + memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
    + data, len);
    + return;
    + }
    +
    + memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
    + data, avail);
    +
    + md4_transform_helper(mctx);
    + data += avail;
    + len -= avail;
    +
    + while (len >= sizeof(mctx->block)) {
    + memcpy(mctx->block, data, sizeof(mctx->block));
    + md4_transform_helper(mctx);
    + data += sizeof(mctx->block);
    + len -= sizeof(mctx->block);
    + }
    +
    + memcpy(mctx->block, data, len);
    +}
    +
    +static void md4_final_ascii(struct md4_ctx *mctx, char *out, unsigned int len)
    +{
    + const unsigned int offset = mctx->byte_count & 0x3f;
    + char *p = (char *)mctx->block + offset;
    + int padding = 56 - (offset + 1);
    +
    + *p++ = 0x80;
    + if (padding < 0) {
    + memset(p, 0x00, padding + sizeof (uint64_t));
    + md4_transform_helper(mctx);
    + p = (char *)mctx->block;
    + padding = 56;
    + }
    +
    + memset(p, 0, padding);
    + mctx->block[14] = mctx->byte_count << 3;
    + mctx->block[15] = mctx->byte_count >> 29;
    + le32_to_cpu_array(mctx->block, (sizeof(mctx->block) -
    + sizeof(uint64_t)) / sizeof(uint32_t));
    + md4_transform(mctx->hash, mctx->block);
    + cpu_to_le32_array(mctx->hash, sizeof(mctx->hash) / sizeof(uint32_t));
    +
    + snprintf(out, len, "%08X%08X%08X%08X",
    + mctx->hash[0], mctx->hash[1], mctx->hash[2], mctx->hash[3]);
    +}
    +
    +static inline void add_char(unsigned char c, struct md4_ctx *md)
    +{
    + md4_update(md, &c, 1);
    +}
    +
    +static int parse_string(const char *file, unsigned long len,
    + struct md4_ctx *md)
    +{
    + unsigned long i;
    +
    + add_char(file[0], md);
    + for (i = 1; i < len; i++) {
    + add_char(file[i], md);
    + if (file[i] == '"' && file[i-1] != '\\')
    + break;
    + }
    + return i;
    +}
    +
    +static int parse_comment(const char *file, unsigned long len)
    +{
    + unsigned long i;
    +
    + for (i = 2; i < len; i++) {
    + if (file[i-1] == '*' && file[i] == '/')
    + break;
    + }
    + return i;
    +}
    +
    +/* FIXME: Handle .s files differently (eg. # starts comments) --RR */
    +static int parse_file(const char *fname, struct md4_ctx *md)
    +{
    + char *file;
    + unsigned long i, len;
    +
    + file = grab_file(fname, &len);
    + if (!file)
    + return 0;
    +
    + for (i = 0; i < len; i++) {
    + /* Collapse and ignore \ and CR. */
    + if (file[i] == '\\' && (i+1 < len) && file[i+1] == '\n') {
    + i++;
    + continue;
    + }
    +
    + /* Ignore whitespace */
    + if (isspace(file[i]))
    + continue;
    +
    + /* Handle strings as whole units */
    + if (file[i] == '"') {
    + i += parse_string(file+i, len - i, md);
    + continue;
    + }
    +
    + /* Comments: ignore */
    + if (file[i] == '/' && file[i+1] == '*') {
    + i += parse_comment(file+i, len - i);
    + continue;
    + }
    +
    + add_char(file[i], md);
    + }
    + release_file(file, len);
    + return 1;
    +}
    +
    +/* We have dir/file.o. Open dir/.file.o.cmd, look for deps_ line to
    + * figure out source file. */
    +static int parse_source_files(const char *objfile, struct md4_ctx *md)
    +{
    + char *cmd, *file, *p, *end;
    + const char *base;
    + unsigned long flen;
    + int dirlen, ret = 0;
    +
    + cmd = malloc(strlen(objfile) + sizeof("..cmd"));
    +
    + base = strrchr(objfile, '/');
    + if (base) {
    + base++;
    + dirlen = base - objfile;
    + sprintf(cmd, "%.*s.%s.cmd", dirlen, objfile, base);
    + } else {
    + dirlen = 0;
    + sprintf(cmd, ".%s.cmd", objfile);
    + }
    +
    + file = grab_file(cmd, &flen);
    + if (!file) {
    + fprintf(stderr, "Warning: could not find %s for %s\n",
    + cmd, objfile);
    + goto out;
    + }
    +
    + /* There will be a line like so:
    + deps_drivers/net/dummy.o := \
    + drivers/net/dummy.c \
    + $(wildcard include/config/net/fastroute.h) \
    + include/linux/config.h \
    + $(wildcard include/config/h.h) \
    + include/linux/module.h \
    +
    + Sum all files in the same dir or subdirs.
    + */
    + /* Strictly illegal: file is not nul terminated. */
    + p = strstr(file, "\ndeps_");
    + if (!p) {
    + fprintf(stderr, "Warning: could not find deps_ line in %s\n",
    + cmd);
    + goto out_file;
    + }
    + p = strstr(p, ":=");
    + if (!p) {
    + fprintf(stderr, "Warning: could not find := line in %s\n",
    + cmd);
    + goto out_file;
    + }
    + p += strlen(":=");
    + p += strspn(p, " \\\n");
    +
    + end = strstr(p, "\n\n");
    + if (!end) {
    + fprintf(stderr, "Warning: could not find end line in %s\n",
    + cmd);
    + goto out_file;
    + }
    +
    + while (p < end) {
    + unsigned int len;
    +
    + len = strcspn(p, " \\\n");
    + if (memcmp(objfile, p, dirlen) == 0) {
    + char source[len + 1];
    +
    + memcpy(source, p, len);
    + source[len] = '\0';
    + printf("parsing %s\n", source);
    + if (!parse_file(source, md)) {
    + fprintf(stderr,
    + "Warning: could not open %s: %s\n",
    + source, strerror(errno));
    + goto out_file;
    + }
    + }
    + p += len;
    + p += strspn(p, " \\\n");
    + }
    +
    + /* Everyone parsed OK */
    + ret = 1;
    +out_file:
    + release_file(file, flen);
    +out:
    + free(cmd);
    + return ret;
    +}
    +
    +static int get_version(const char *modname, char sum[])
    +{
    + void *file;
    + unsigned long len;
    + int ret = 0;
    + struct md4_ctx md;
    + char *sources, *end, *fname;
    + const char *basename;
    + char filelist[sizeof(".tmp_versions/%s.mod") + strlen(modname)];
    +
    + /* Source files for module are in .tmp_versions/modname.mod,
    + after the first line. */
    + if (strrchr(modname, '/'))
    + basename = strrchr(modname, '/') + 1;
    + else
    + basename = modname;
    + sprintf(filelist, ".tmp_versions/%s", basename);
    + /* Truncate .o, add .mod */
    + strcpy(filelist + strlen(filelist)-2, ".mod");
    +
    + file = grab_file(filelist, &len);
    + if (!file) {
    + fprintf(stderr, "Warning: could not find versions for %s\n",
    + filelist);
    + return 0;
    + }
    +
    + sources = strchr(file, '\n');
    + if (!sources) {
    + fprintf(stderr, "Warning: malformed versions file for %s\n",
    + modname);
    + goto release;
    + }
    +
    + sources++;
    + end = strchr(sources, '\n');
    + if (!end) {
    + fprintf(stderr, "Warning: bad ending versions file for %s\n",
    + modname);
    + goto release;
    + }
    + *end = '\0';
    +
    + md4_init(&md);
    + for (fname = strtok(sources, " "); fname; fname = strtok(NULL, " ")) {
    + if (!parse_source_files(fname, &md))
    + goto release;
    + }
    +
    + /* sum is of form \0<padding>. */
    + md4_final_ascii(&md, sum, 1 + strlen(sum+1));
    + ret = 1;
    +release:
    + release_file(file, len);
    + return ret;
    +}
    +
    +static void write_version(const char *filename, const char *sum,
    + unsigned long offset)
    +{
    + int fd;
    +
    + fd = open(filename, O_RDWR);
    + if (fd < 0) {
    + fprintf(stderr, "Warning: changing sum in %s failed: %s\n",
    + filename, strerror(errno));
    + return;
    + }
    +
    + if (lseek(fd, offset, SEEK_SET) == (off_t)-1) {
    + fprintf(stderr, "Warning: changing sum in %s:%lu failed: %s\n",
    + filename, offset, strerror(errno));
    + goto out;
    + }
    +
    + if (write(fd, sum, strlen(sum)+1) != strlen(sum)+1) {
    + fprintf(stderr, "Warning: writing sum in %s failed: %s\n",
    + filename, strerror(errno));
    + goto out;
    + }
    +out:
    + close(fd);
    +}
    +
    +void strip_rcs_crap(char *version)
    +{
    + unsigned int len, full_len;
    +
    + if (strncmp(version, "$Revision", strlen("$Revision")) != 0)
    + return;
    +
    + /* Space for version string follows. */
    + full_len = strlen(version) + strlen(version + strlen(version) + 1) + 2;
    +
    + /* Move string to start with version number: prefix will be
    + * $Revision$ or $Revision: */
    + len = strlen("$Revision");
    + if (version[len] == ':' || version[len] == '$')
    + len++;
    + while (isspace(version[len]))
    + len++;
    + memmove(version, version+len, full_len-len);
    + full_len -= len;
    +
    + /* Preserve up to next whitespace. */
    + len = 0;
    + while (version[len] && !isspace(version[len]))
    + len++;
    + memmove(version + len, version + strlen(version),
    + full_len - strlen(version));
    +}
    +
    +/* If the modinfo contains a "version" value, then set this. */
    +void maybe_frob_version(const char *modfilename,
    + void *modinfo,
    + unsigned long modinfo_len,
    + unsigned long modinfo_offset)
    +{
    + char *version, *csum;
    +
    + version = get_modinfo(modinfo, modinfo_len, "version");
    + if (!version)
    + return;
    +
    + /* RCS $Revision gets stripped out. */
    + strip_rcs_crap(version);
    +
    + /* Check against double sumversion */
    + if (strchr(version, ' '))
    + return;
    +
    + /* Version contains embedded NUL: second half has space for checksum */
    + csum = version + strlen(version);
    + *(csum++) = ' ';
    + if (get_version(modfilename, csum))
    + write_version(modfilename, version,
    + modinfo_offset + (version - (char *)modinfo));
    +}
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/
    \
     
     \ /
      Last update: 2005-03-22 14:01    [W:0.063 / U:59.492 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site