diff -Nru a/include/linux/module.h b/include/linux/module.h --- a/include/linux/module.h 2004-10-20 10:16:28 -07:00 +++ b/include/linux/module.h 2004-10-20 10:16:28 -07:00 @@ -308,6 +308,12 @@ /* Fake kernel param for refcnt. */ struct kernel_param refcnt_param; #endif + struct kernel_param author_param; + struct kernel_param version_param; + struct kernel_param license_param; + char *author; + char *version; + char *license; #ifdef CONFIG_KALLSYMS /* We keep the symbol and string tables for kallsyms. */ diff -Nru a/kernel/module.c b/kernel/module.c --- a/kernel/module.c 2004-10-20 10:16:28 -07:00 +++ b/kernel/module.c 2004-10-20 10:16:28 -07:00 @@ -1094,6 +1094,25 @@ .store = module_attr_store, }; +#define MOD_SYSFS(field) \ +static int field##_get_fn(char *buffer, struct kernel_param *kp) \ +{ \ + struct module *mod = container_of(kp, struct module, field##_param); \ + return sprintf(buffer, "%s", mod->field); \ +} \ +static int sysfs_##field##_setup(struct module *mod) \ +{ \ + if (!mod->field) \ + return 0; \ + mod->field##_param.name = __stringify(field); \ + mod->field##_param.perm = 0444; \ + mod->field##_param.get = field##_get_fn; \ + return add_attribute(mod, &mod->field##_param); \ +} +MOD_SYSFS(author); +MOD_SYSFS(version); +MOD_SYSFS(license); + static void module_kobj_release(struct kobject *kobj) { kfree(container_of(kobj, struct module_kobject, kobj)); @@ -1114,7 +1133,7 @@ /* We overallocate: not every param is in sysfs, and maybe no refcnt */ mod->mkobj = kmalloc(sizeof(*mod->mkobj) - + sizeof(mod->mkobj->attr[0]) * (num_params+1), + + sizeof(mod->mkobj->attr[0]) * (num_params+4), GFP_KERNEL); if (!mod->mkobj) return -ENOMEM; @@ -1140,6 +1159,15 @@ err = sysfs_unload_setup(mod); if (err) goto out_unreg; + err = sysfs_author_setup(mod); + if (err) + goto out_unreg; + err = sysfs_version_setup(mod); + if (err) + goto out_unreg; + err = sysfs_license_setup(mod); + if (err) + goto out_unreg; return 0; out_unreg: @@ -1160,6 +1188,9 @@ sysfs_remove_file(&mod->mkobj->kobj,&mod->mkobj->attr[i].attr); /* Calls module_kobj_release */ kobject_unregister(&mod->mkobj->kobj); + kfree(mod->author); + kfree(mod->license); + kfree(mod->version); } /* Free a module, remove from lists, etc (must hold module mutex). */ @@ -1346,11 +1377,25 @@ || strcmp(license, "Dual MPL/GPL") == 0); } +static char *strdup(const char *str) +{ + char *s; + + if (!str) + return NULL; + s = kmalloc(strlen(str)+1, GFP_KERNEL); + if (!s) + return NULL; + strcpy(s, str); + return s; +} + static void set_license(struct module *mod, const char *license) { if (!license) license = "unspecified"; + mod->license = strdup(license); mod->license_gplok = license_is_gpl_compatible(license); if (!mod->license_gplok && !(tainted & TAINT_PROPRIETARY_MODULE)) { printk(KERN_WARNING "%s: module license '%s' taints kernel.\n", @@ -1696,6 +1741,9 @@ /* Set up license info based on the info section */ set_license(mod, get_modinfo(sechdrs, infoindex, "license")); + + mod->author = strdup(get_modinfo(sechdrs, infoindex, "author")); + mod->version = strdup(get_modinfo(sechdrs, infoindex, "version")); /* Fix up syms, so that st_value is a pointer to location. */ err = simplify_symbols(sechdrs, symindex, strtab, versindex, pcpuindex,