aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Jenkins <alan-jenkins@tuffmail.co.uk>2010-03-02 09:59:00 +0000
committerAlan Jenkins <alan-jenkins@tuffmail.co.uk>2010-03-02 09:59:27 +0000
commit7bfbf4ba583f5da45795856accc9cf1c7bd5623f (patch)
tree56ac40758a8685bb9c4b20b2d84ea1361525f160
parent66876e3ee43d52f1b41c56e5bab542b7c205b91b (diff)
parent8c7c5c102426cafcb2d118e307f246df66d650de (diff)
downloadmodule-init-tools-7bfbf4ba583f5da45795856accc9cf1c7bd5623f.tar.gz
Merge branch 'cleanups' into softdep-merge
Conflicts: modprobe.c
-rw-r--r--configure.ac2
-rw-r--r--depmod.c4
-rw-r--r--doc/modprobe.sgml12
-rw-r--r--elfops.c39
-rw-r--r--elfops.h1
-rw-r--r--insmod.c13
-rw-r--r--m4/ax_enable_builddir.m45
-rw-r--r--modprobe.c231
-rwxr-xr-xtests/test-modprobe/02proc.sh103
-rwxr-xr-xtests/test-modprobe/04config.sh72
-rwxr-xr-xtests/test-modprobe/12whitespace.sh57
-rwxr-xr-xtests/test-modprobe/22recursiveinstall.sh6
-rwxr-xr-xtests/test-modprobe/27cmdline-install-remove.sh3
-rw-r--r--util.c29
-rw-r--r--util.h2
-rw-r--r--zlibsupport.c17
16 files changed, 421 insertions, 175 deletions
diff --git a/configure.ac b/configure.ac
index 75d3b15..b374c33 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,4 +1,4 @@
-AC_INIT(module-init-tools,3.11-rc1)
+AC_INIT(module-init-tools,3.12-pre1)
AC_CANONICAL_SYSTEM
diff --git a/depmod.c b/depmod.c
index 07f8a99..37b3608 100644
--- a/depmod.c
+++ b/depmod.c
@@ -1,6 +1,7 @@
/* New simplified depmod without backwards compat stuff and not
requiring ksyms.
+ (C) 2010 Jon Masters <jcm@jonmasters.org>, and others.
(C) 2002 Rusty Russell IBM Corporation
*/
#define _GNU_SOURCE /* asprintf */
@@ -1150,8 +1151,7 @@ static int parse_config_file(const char *filename,
version = strsep_skipspace(&ptr, "\t ");
subdir = strsep_skipspace(&ptr, "\t ");
- if (strcmp(version, kernelversion) != 0 &&
- strcmp(version, "*") != 0)
+ if (!regex_match(kernelversion, (const char *)version))
continue;
nofail_asprintf(&pathname, "%s%s%s/%s/%s.ko", basedir,
diff --git a/doc/modprobe.sgml b/doc/modprobe.sgml
index 69b2d84..9e41dde 100644
--- a/doc/modprobe.sgml
+++ b/doc/modprobe.sgml
@@ -187,13 +187,13 @@
</term>
<listitem>
<para>
- Normally <command>modprobe</command> will report an error
- if you try to remove or insert a module it can't find (and
+ With this flag, <command>modprobe</command> won't print an error
+ message if you try to remove or insert a module it can't find (and
isn't an alias or
- <command>install</command>/<command>remove</command>
- command). With this flag, <command>modprobe</command>
- will simply ignore any bogus names (the kernel uses this
- to opportunistically probe for modules which might exist).
+ <command>install</command>/<command>remove</command> command).
+ However, it will still return with a non-zero exit status. The
+ kernel uses this to opportunistically probe for modules which might
+ exist.
</para>
</listitem>
</varlistentry>
diff --git a/elfops.c b/elfops.c
index da2740e..10e80ea 100644
--- a/elfops.c
+++ b/elfops.c
@@ -62,46 +62,21 @@ static int elf_ident(void *file, unsigned long fsize, int *conv)
*/
struct elf_file *grab_elf_file(const char *pathname)
{
- int fd;
- int err;
- struct elf_file *file;
-
- fd = open(pathname, O_RDONLY, 0);
- if (fd < 0)
- return NULL;
- file = grab_elf_file_fd(pathname, fd);
-
- err = errno;
- close(fd);
- errno = err;
- return file;
-}
-
-/*
- * grab_elf_file_fd - read ELF file from file descriptor into memory
- * @pathame: name of file to load
- * @fd: file descriptor of file to load
- *
- * Returns NULL, and errno set on error.
- */
-struct elf_file *grab_elf_file_fd(const char *pathname, int fd)
-{
struct elf_file *file;
file = malloc(sizeof(*file));
if (!file) {
errno = ENOMEM;
- return NULL;
+ goto fail;
}
file->pathname = strdup(pathname);
if (!file->pathname) {
- free(file);
errno = ENOMEM;
- return NULL;
+ goto fail_free_file;
}
- file->data = grab_fd(fd, &file->len);
+ file->data = grab_file(pathname, &file->len);
if (!file->data)
- goto fail;
+ goto fail_free_pathname;
switch (elf_ident(file->data, file->len, &file->conv)) {
case ELFCLASS32:
@@ -117,8 +92,12 @@ struct elf_file *grab_elf_file_fd(const char *pathname, int fd)
goto fail;
}
return file;
+
+fail_free_pathname:
+ free(file->pathname);
+fail_free_file:
+ free(file);
fail:
- release_elf_file(file);
return NULL;
}
diff --git a/elfops.h b/elfops.h
index ceee2c8..266c8cd 100644
--- a/elfops.h
+++ b/elfops.h
@@ -79,7 +79,6 @@ struct module_ops
extern struct module_ops mod_ops32, mod_ops64;
struct elf_file *grab_elf_file(const char *pathname);
-struct elf_file *grab_elf_file_fd(const char *pathname, int fd);
void release_elf_file(struct elf_file *file);
#endif /* MODINITTOOLS_MODULEOPS_H */
diff --git a/insmod.c b/insmod.c
index 3a2a910..de4f68b 100644
--- a/insmod.c
+++ b/insmod.c
@@ -60,9 +60,7 @@ static void *grab_file(const char *filename, unsigned long *size)
{
unsigned int max = 16384;
int ret, fd, err_save;
- void *buffer = malloc(max);
- if (!buffer)
- return NULL;
+ void *buffer;
if (streq(filename, "-"))
fd = dup(STDIN_FILENO);
@@ -72,6 +70,10 @@ static void *grab_file(const char *filename, unsigned long *size)
if (fd < 0)
return NULL;
+ buffer = malloc(max);
+ if (!buffer)
+ goto out_error;
+
*size = 0;
while ((ret = read(fd, buffer + *size, max - *size)) > 0) {
*size += ret;
@@ -158,7 +160,10 @@ int main(int argc, char *argv[])
if (ret != 0) {
fprintf(stderr, "insmod: error inserting '%s': %li %s\n",
filename, ret, moderror(errno));
- exit(1);
}
+ free(file);
+
+ if (ret != 0)
+ exit(1);
exit(0);
}
diff --git a/m4/ax_enable_builddir.m4 b/m4/ax_enable_builddir.m4
index 49b3eb9..4273a53 100644
--- a/m4/ax_enable_builddir.m4
+++ b/m4/ax_enable_builddir.m4
@@ -187,8 +187,9 @@ s/^srcdir *=.*/srcdir = ./
s/^top_srcdir *=.*/top_srcdir = ./
/[[:=]]/!d
/^\\./d
-dnl Now handle rules (i.e. lines containing /:/ but not /:=/).
-/:=/b
+dnl Now handle rules (i.e. lines containing ":" but not " = ").
+/ = /b
+/ .= /b
/:/!b
s/:.*/:/
s/ / /g
diff --git a/modprobe.c b/modprobe.c
index f45db9f..3ac0f65 100644
--- a/modprobe.c
+++ b/modprobe.c
@@ -75,9 +75,10 @@ typedef enum
mit_use_blacklist = 8,
mit_ignore_commands = 16,
mit_ignore_loaded = 32,
- mit_strip_vermagic = 64,
- mit_strip_modversion = 128,
- mit_resolve_alias = 256
+ mit_quiet_inuse = 64,
+ mit_strip_vermagic = 128,
+ mit_strip_modversion = 256,
+ mit_resolve_alias = 512
} modprobe_flags_t;
@@ -106,24 +107,6 @@ static struct module *find_module(const char *filename, struct list_head *list)
return NULL;
}
-/* We used to lock with a write flock but that allows regular users to block
- * module load by having a read lock on the module file (no way to bust the
- * existing locks without killing the offending process). Instead, we now
- * do the system call/init_module and allow the kernel to fail us instead.
- */
-static int open_file(const char *filename)
-{
- int fd = open(filename, O_RDONLY, 0);
-
- return fd;
-}
-
-static void close_file(int fd)
-{
- /* Valgrind is picky... */
- close(fd);
-}
-
static void add_module(char *filename, int namelen, struct list_head *list)
{
struct module *mod;
@@ -588,15 +571,70 @@ static char *prepend_option(char *options, const char *newoption)
/* Add to options */
static char *add_extra_options(const char *modname,
- char *optstring,
+ const char *optstring,
const struct module_options *options)
{
+ char *opts = NOFAIL(strdup(optstring));
+
while (options) {
if (streq(options->modulename, modname))
- optstring = prepend_option(optstring, options->options);
+ opts = prepend_option(opts, options->options);
options = options->next;
}
- return optstring;
+ return opts;
+}
+
+/* Is module in /proc/modules? If so, fill in usecount if not NULL.
+ 0 means no, 1 means yes, -1 means unknown.
+ */
+static int module_in_procfs(const char *modname, unsigned int *usecount)
+{
+ FILE *proc_modules;
+ char *line;
+
+again:
+ /* Might not be mounted yet. Don't fail. */
+ proc_modules = fopen("/proc/modules", "r");
+ if (!proc_modules)
+ return -1;
+
+ while ((line = getline_wrapped(proc_modules, NULL)) != NULL) {
+ char *entry = strtok(line, " \n");
+
+ if (entry && streq(entry, modname)) {
+ /* If it exists, usecount is the third entry. */
+ if (!strtok(NULL, " \n"))
+ goto out;
+
+ if (!(entry = strtok(NULL, " \n"))) /* usecount */
+ goto out;
+ else
+ if (usecount)
+ *usecount = atoi(entry);
+
+ /* Followed by - then status. */
+ if (strtok(NULL, " \n")
+ && (entry = strtok(NULL, " \n")) != NULL) {
+ /* No locking, we might hit cases
+ * where module is in flux. Spin. */
+ if (streq(entry, "Loading")
+ || streq(entry, "Unloading")) {
+ usleep(100000);
+ free(line);
+ fclose(proc_modules);
+ goto again;
+ }
+ }
+
+ out:
+ free(line);
+ fclose(proc_modules);
+ return 1;
+ }
+ free(line);
+ }
+ fclose(proc_modules);
+ return 0;
}
/* Read sysfs attribute into a buffer.
@@ -638,7 +676,7 @@ static int module_builtin(const char *dirname, const char *modname)
/* Is module in /sys/module? If so, fill in usecount if not NULL.
0 means no, 1 means yes, -1 means unknown.
*/
-static int module_in_kernel(const char *modname, unsigned int *usecount)
+static int module_in_sysfs(const char *modname, unsigned int *usecount)
{
int ret;
char *name;
@@ -658,14 +696,26 @@ static int module_in_kernel(const char *modname, unsigned int *usecount)
if (ret < 0)
return (errno == ENOENT) ? 0 : -1; /* Not found or unknown. */
- /* Wait for the existing module to either go live or disappear. */
nofail_asprintf(&name, "/sys/module/%s/initstate", modname);
- while (1) {
- ret = read_attribute(name, attr, ATTR_LEN);
- if (ret != 1 || streq(attr, "live\n"))
- break;
+ ret = read_attribute(name, attr, ATTR_LEN);
+ if (ret == 0) {
+ free(name);
+ nofail_asprintf(&name, "/sys/module/%s", modname);
+ if (stat(name, &finfo) < 0) {
+ /* module was removed before we could read initstate */
+ ret = 0;
+ } else {
+ /* initstate not available (2.6.19 or earlier) */
+ ret = -1;
+ }
+ free(name);
+ return ret;
+ }
+ /* Wait for the existing module to either go live or disappear. */
+ while (ret == 1 && !streq(attr, "live\n")) {
usleep(100000);
+ ret = read_attribute(name, attr, ATTR_LEN);
}
free(name);
@@ -684,6 +734,22 @@ static int module_in_kernel(const char *modname, unsigned int *usecount)
return 1;
}
+/* Is module loaded? If so, fill in usecount if not NULL.
+ 0 means no, 1 means yes, -1 means unknown.
+ */
+static int module_in_kernel(const char *modname, unsigned int *usecount)
+{
+ int result;
+
+ result = module_in_sysfs(modname, usecount);
+ if (result != -1)
+ return result;
+
+ /* /sys/module/%s/initstate is only available since 2.6.20,
+ fallback to /proc/modules to get module state on earlier kernels. */
+ return module_in_procfs(modname, usecount);
+}
+
void dump_modversions(const char *filename, errfn_t error)
{
struct elf_file *module;
@@ -1301,9 +1367,9 @@ static void do_softdep(const struct module_softdep *softdep,
}
}
-/* Actually do the insert. Frees second arg. */
+/* Actually do the insert. */
static int insmod(struct list_head *list,
- char *optstring,
+ const char *optstring,
const char *newname,
const char *cmdline_opts,
const struct modprobe_conf *conf,
@@ -1311,12 +1377,14 @@ static int insmod(struct list_head *list,
errfn_t error,
modprobe_flags_t flags)
{
- int ret, fd;
+ int ret;
struct elf_file *module;
const struct module_softdep *softdep;
const char *command;
struct module *mod = list_entry(list->next, struct module, list);
int rc = 0;
+ int already_loaded;
+ char *opts = NULL;
/* Take us off the list. */
list_del(&mod->list);
@@ -1326,54 +1394,54 @@ static int insmod(struct list_head *list,
modprobe_flags_t f = flags;
f &= ~mit_first_time;
f &= ~mit_ignore_commands;
- if ((rc = insmod(list, NOFAIL(strdup("")), NULL,
+ if ((rc = insmod(list, "", NULL,
"", conf, dirname, warn, f)) != 0)
{
error("Error inserting %s (%s): %s\n",
mod->modname, mod->filename,
insert_moderror(errno));
- goto out_optstring;
+ goto out;
}
}
- fd = open_file(mod->filename);
- if (fd < 0) {
- error("Could not open '%s': %s\n",
- mod->filename, strerror(errno));
- goto out_optstring;
- }
-
/* Don't do ANYTHING if already in kernel. */
- if (!(flags & mit_ignore_loaded)
- && module_in_kernel(newname ?: mod->modname, NULL) == 1) {
+ already_loaded = module_in_kernel(newname ?: mod->modname, NULL);
+
+ if (!(flags & mit_ignore_loaded) && already_loaded == 1) {
if (flags & mit_first_time)
error("Module %s already in kernel.\n",
newname ?: mod->modname);
- goto out_unlock;
+ goto out;
}
softdep = find_softdep(mod->modname, conf->softdeps);
if (softdep && !(flags & mit_ignore_commands)) {
- close_file(fd);
do_softdep(softdep, cmdline_opts, conf, dirname,
error, flags & (mit_remove | mit_dry_run));
- goto out_optstring;
+ goto out;
}
command = find_command(mod->modname, conf->commands);
if (command && !(flags & mit_ignore_commands)) {
- close_file(fd);
- do_command(mod->modname, command, flags & mit_dry_run, error,
- "install", cmdline_opts);
- goto out_optstring;
+ if (already_loaded == -1) {
+ warn("/sys/module/ not present or too old,"
+ " and /proc/modules does not exist.\n");
+ warn("Ignoring install commands for %s"
+ " in case it is already loaded.\n",
+ newname ?: mod->modname);
+ } else {
+ do_command(mod->modname, command, flags & mit_dry_run,
+ error, "install", cmdline_opts);
+ goto out;
+ }
}
- module = grab_elf_file_fd(mod->filename, fd);
+ module = grab_elf_file(mod->filename);
if (!module) {
error("Could not read '%s': %s\n", mod->filename,
(errno == ENOEXEC) ? "Invalid module format" :
strerror(errno));
- goto out_unlock;
+ goto out;
}
if (newname)
rename_module(module, mod->modname, newname);
@@ -1383,20 +1451,20 @@ static int insmod(struct list_head *list,
clear_magic(module);
/* Config file might have given more options */
- optstring = add_extra_options(mod->modname, optstring, conf->options);
+ opts = add_extra_options(mod->modname, optstring, conf->options);
- info("insmod %s %s\n", mod->filename, optstring);
+ info("insmod %s %s\n", mod->filename, opts);
if (flags & mit_dry_run)
- goto out;
+ goto out_elf_file;
- ret = init_module(module->data, module->len, optstring);
+ ret = init_module(module->data, module->len, opts);
if (ret != 0) {
if (errno == EEXIST) {
if (flags & mit_first_time)
error("Module %s already in kernel.\n",
newname ?: mod->modname);
- goto out_unlock;
+ goto out_elf_file;
}
/* don't warn noisely if we're loading multiple aliases. */
/* one of the aliases may try to use hardware we don't have. */
@@ -1406,12 +1474,10 @@ static int insmod(struct list_head *list,
insert_moderror(errno));
rc = 1;
}
- out:
+ out_elf_file:
release_elf_file(module);
- out_unlock:
- close_file(fd);
- out_optstring:
- free(optstring);
+ free(opts);
+ out:
free_module(mod);
return rc;
}
@@ -1429,6 +1495,7 @@ static void rmmod(struct list_head *list,
const char *command;
unsigned int usecount = 0;
struct module *mod = list_entry(list->next, struct module, list);
+ int exists;
/* Take first one off the list. */
list_del(&mod->list);
@@ -1436,6 +1503,11 @@ static void rmmod(struct list_head *list,
if (!name)
name = mod->modname;
+ /* Don't do ANYTHING if not loaded. */
+ exists = module_in_kernel(name, &usecount);
+ if (exists == 0)
+ goto nonexistent_module;
+
/* Even if renamed, find commands/softdeps to orig. name. */
softdep = find_softdep(mod->modname, conf->softdeps);
@@ -1447,16 +1519,21 @@ static void rmmod(struct list_head *list,
command = find_command(mod->modname, conf->commands);
if (command && !(flags & mit_ignore_commands)) {
- do_command(mod->modname, command, flags & mit_dry_run, error,
- "remove", cmdline_opts);
- goto remove_rest;
+ if (exists == -1) {
+ warn("/sys/module/ not present or too old,"
+ " and /proc/modules does not exist.\n");
+ warn("Ignoring remove commands for %s"
+ " in case it is not loaded.\n",
+ mod->modname);
+ } else {
+ do_command(mod->modname, command, flags & mit_dry_run,
+ error, "remove", cmdline_opts);
+ goto remove_rest;
+ }
}
- if (module_in_kernel(name, &usecount) == 0)
- goto nonexistent_module;
-
if (usecount != 0) {
- if (!(flags & mit_ignore_loaded))
+ if (!(flags & mit_quiet_inuse))
error("Module %s is in use.\n", name);
goto remove_rest;
}
@@ -1479,7 +1556,7 @@ static void rmmod(struct list_head *list,
if (!list_empty(list)) {
flags &= ~mit_first_time;
flags &= ~mit_ignore_commands;
- flags |= mit_ignore_loaded;
+ flags |= mit_quiet_inuse;
rmmod(list, NULL, "", conf, dirname, warn, flags);
}
@@ -1528,12 +1605,11 @@ static int handle_module(const char *modname,
return 1;
}
- if (flags & mit_remove) {
- flags &= ~mit_ignore_loaded;
+ if (flags & mit_remove)
rmmod(todo_list, newname, cmdline_opts,
conf, dirname, error, flags);
- } else
- insmod(todo_list, NOFAIL(strdup(options)), newname,
+ else
+ insmod(todo_list, options, newname,
cmdline_opts, conf, dirname, error, flags);
return 0;
@@ -1624,8 +1700,8 @@ int do_modprobe(const char *modulename,
err = warn;
while (aliases) {
/* Add the options for this alias. */
- char *opts = NOFAIL(strdup(cmdline_opts));
- opts = add_extra_options(modname, opts, conf->options);
+ char *opts;
+ opts = add_extra_options(modname, cmdline_opts, conf->options);
read_depends(dirname, aliases->module, &list);
failed |= handle_module(aliases->module,
@@ -1633,6 +1709,7 @@ int do_modprobe(const char *modulename,
conf, dirname, err, flags);
aliases = aliases->next;
+ free(opts);
INIT_LIST_HEAD(&list);
}
} else {
diff --git a/tests/test-modprobe/02proc.sh b/tests/test-modprobe/02proc.sh
new file mode 100755
index 0000000..d7db770
--- /dev/null
+++ b/tests/test-modprobe/02proc.sh
@@ -0,0 +1,103 @@
+#! /bin/sh
+
+# Test handling of /proc/modules.
+
+BITNESS=32
+
+rm -rf tests/tmp/*
+
+# Create inputs
+MODULE_DIR=tests/tmp/lib/modules/$MODTEST_UNAME
+mkdir -p $MODULE_DIR
+ln tests/data/$BITNESS/normal/export_nodep-$BITNESS.ko \
+ tests/data/$BITNESS/normal/noexport_nodep-$BITNESS.ko \
+ $MODULE_DIR
+
+mkdir tests/tmp/proc
+
+# Now create modules.dep
+cat > tests/tmp/lib/modules/$MODTEST_UNAME/modules.dep <<EOF
+noexport_nodep-$BITNESS.ko:
+export_nodep-$BITNESS.ko:
+EOF
+
+SIZE_NOEXPORT_NODEP=$(echo `wc -c < tests/data/$BITNESS/normal/noexport_nodep-$BITNESS.ko`)
+SIZE_EXPORT_NODEP=$(echo `wc -c < tests/data/$BITNESS/normal/export_nodep-$BITNESS.ko`)
+
+# If it can't open /proc/modules, it should try anyway.
+rm -f tests/tmp/proc/modules
+
+[ "`modprobe noexport_nodep-$BITNESS 2>&1`" = "INIT_MODULE: $SIZE_NOEXPORT_NODEP " ]
+[ "`modprobe export_nodep-$BITNESS 2>&1`" = "INIT_MODULE: $SIZE_EXPORT_NODEP " ]
+
+[ "`modprobe -r noexport_nodep-$BITNESS 2>&1`" = "DELETE_MODULE: noexport_nodep_$BITNESS EXCL " ]
+[ "`modprobe -r export_nodep-$BITNESS 2>&1`" = "DELETE_MODULE: export_nodep_$BITNESS EXCL " ]
+
+# If it doesn't exist in /proc/modules, remove should succeed.
+touch tests/tmp/proc/modules
+[ "`modprobe noexport_nodep-$BITNESS 2>&1`" = "INIT_MODULE: $SIZE_NOEXPORT_NODEP " ]
+[ "`modprobe export_nodep-$BITNESS 2>&1`" = "INIT_MODULE: $SIZE_EXPORT_NODEP " ]
+[ "`modprobe -r -v noexport_nodep-$BITNESS 2>&1; echo $?`" = "0" ]
+[ "`modprobe -r -v export_nodep-$BITNESS 2>&1; echo $?`" = "0" ]
+[ "`modprobe -r -v noexport-nodep-$BITNESS 2>&1; echo $?`" = "0" ]
+[ "`modprobe -r -v export-nodep-$BITNESS 2>&1; echo $?`" = "0" ]
+# ... unless --first-time is specified (won't print status due to set -e).
+[ "`modprobe --first-time -r noexport_nodep-$BITNESS 2>&1`" = "FATAL: Module noexport_nodep_$BITNESS is not in kernel." ]
+[ "`modprobe --first-time -r export_nodep-$BITNESS 2>&1`" = "FATAL: Module export_nodep_$BITNESS is not in kernel." ]
+[ "`modprobe --first-time -r noexport-nodep-$BITNESS 2>&1`" = "FATAL: Module noexport_nodep_$BITNESS is not in kernel." ]
+[ "`modprobe --first-time -r export-nodep-$BITNESS 2>&1`" = "FATAL: Module export_nodep_$BITNESS is not in kernel." ]
+
+# Old-style /proc (no unload support).
+echo "noexport_nodep_$BITNESS $SIZE_NOEXPORT_NODEP" > tests/tmp/proc/modules
+echo "export_nodep_$BITNESS $SIZE_EXPORT_NODEP" >> tests/tmp/proc/modules
+
+# If it does exist, insertion should "succeed".
+[ "`modprobe -v noexport_nodep-$BITNESS 2>&1; echo $?`" = "0" ]
+[ "`modprobe -v export_nodep-$BITNESS 2>&1; echo $?`" = "0" ]
+[ "`modprobe -v noexport-nodep-$BITNESS 2>&1; echo $?`" = "0" ]
+[ "`modprobe -v export-nodep-$BITNESS 2>&1; echo $?`" = "0" ]
+# .. unless --first-time is specified.
+[ "`modprobe --first-time noexport_nodep-$BITNESS 2>&1`" = "FATAL: Module noexport_nodep_$BITNESS already in kernel." ]
+[ "`modprobe --first-time export_nodep-$BITNESS 2>&1`" = "FATAL: Module export_nodep_$BITNESS already in kernel." ]
+[ "`modprobe --first-time noexport-nodep-$BITNESS 2>&1`" = "FATAL: Module noexport_nodep_$BITNESS already in kernel." ]
+[ "`modprobe --first-time export-nodep-$BITNESS 2>&1`" = "FATAL: Module export_nodep_$BITNESS already in kernel." ]
+
+# Removal should still try.
+[ "`modprobe -r noexport_nodep-$BITNESS 2>&1`" = "DELETE_MODULE: noexport_nodep_$BITNESS EXCL " ]
+[ "`modprobe -r export_nodep-$BITNESS 2>&1`" = "DELETE_MODULE: export_nodep_$BITNESS EXCL " ]
+
+# New-style /proc without unload support
+echo "noexport_nodep_$BITNESS $SIZE_NOEXPORT_NODEP - -" > tests/tmp/proc/modules
+echo "export_nodep_$BITNESS $SIZE_EXPORT_NODEP - -" >> tests/tmp/proc/modules
+
+[ "`modprobe --first-time noexport_nodep-$BITNESS 2>&1`" = "FATAL: Module noexport_nodep_$BITNESS already in kernel." ]
+[ "`modprobe --first-time export_nodep-$BITNESS 2>&1`" = "FATAL: Module export_nodep_$BITNESS already in kernel." ]
+[ "`modprobe --first-time noexport-nodep-$BITNESS 2>&1`" = "FATAL: Module noexport_nodep_$BITNESS already in kernel." ]
+[ "`modprobe --first-time export-nodep-$BITNESS 2>&1`" = "FATAL: Module export_nodep_$BITNESS already in kernel." ]
+# Removal should still try.
+[ "`modprobe -r noexport_nodep-$BITNESS 2>&1`" = "DELETE_MODULE: noexport_nodep_$BITNESS EXCL " ]
+[ "`modprobe -r export_nodep-$BITNESS 2>&1`" = "DELETE_MODULE: export_nodep_$BITNESS EXCL " ]
+
+# Should fail if refcounts non-zero. Old-style
+echo "noexport_nodep_$BITNESS $SIZE_NOEXPORT_NODEP 1" > tests/tmp/proc/modules
+echo "export_nodep_$BITNESS $SIZE_EXPORT_NODEP 1" >> tests/tmp/proc/modules
+
+[ "`modprobe -r noexport_nodep-$BITNESS 2>&1`" = "FATAL: Module noexport_nodep_$BITNESS is in use." ]
+[ "`modprobe -r export_nodep-$BITNESS 2>&1`" = "FATAL: Module export_nodep_$BITNESS is in use." ]
+[ "`modprobe -r noexport-nodep-$BITNESS 2>&1`" = "FATAL: Module noexport_nodep_$BITNESS is in use." ]
+[ "`modprobe -r export-nodep-$BITNESS 2>&1`" = "FATAL: Module export_nodep_$BITNESS is in use." ]
+
+# New-style /proc
+echo "noexport_nodep_$BITNESS $SIZE_NOEXPORT_NODEP 1 -" > tests/tmp/proc/modules
+echo "export_nodep_$BITNESS $SIZE_EXPORT_NODEP 1 something_else, extrafield" >> tests/tmp/proc/modules
+
+[ "`modprobe --first-time noexport_nodep-$BITNESS 2>&1`" = "FATAL: Module noexport_nodep_$BITNESS already in kernel." ]
+[ "`modprobe --first-time export_nodep-$BITNESS 2>&1`" = "FATAL: Module export_nodep_$BITNESS already in kernel." ]
+[ "`modprobe --first-time noexport-nodep-$BITNESS 2>&1`" = "FATAL: Module noexport_nodep_$BITNESS already in kernel." ]
+[ "`modprobe --first-time export-nodep-$BITNESS 2>&1`" = "FATAL: Module export_nodep_$BITNESS already in kernel." ]
+
+[ "`modprobe -r noexport_nodep-$BITNESS 2>&1`" = "FATAL: Module noexport_nodep_$BITNESS is in use." ]
+[ "`modprobe -r export_nodep-$BITNESS 2>&1`" = "FATAL: Module export_nodep_$BITNESS is in use." ]
+[ "`modprobe -r noexport-nodep-$BITNESS 2>&1`" = "FATAL: Module noexport_nodep_$BITNESS is in use." ]
+[ "`modprobe -r export-nodep-$BITNESS 2>&1`" = "FATAL: Module export_nodep_$BITNESS is in use." ]
+
diff --git a/tests/test-modprobe/04config.sh b/tests/test-modprobe/04config.sh
index cb85422..342cc18 100755
--- a/tests/test-modprobe/04config.sh
+++ b/tests/test-modprobe/04config.sh
@@ -88,38 +88,29 @@ SIZE_NOEXPORT_DEP=`wc -c < tests/data/$BITNESS/normal/noexport_dep-$BITNESS.ko`
SIZE_EXPORT_DEP=`wc -c < tests/data/$BITNESS/normal/export_dep-$BITNESS.ko`
SIZE_NOEXPORT_DOUBLEDEP=`wc -c < tests/data/$BITNESS/normal/noexport_doubledep-$BITNESS.ko`
-# Test ignoring install & remove.
+# Empty /sys/module/ for install commands
+mkdir -p tests/tmp/sys/module
+# Test ignoring install commands
[ "`modprobe --ignore-install export_nodep-$BITNESS 2>&1`" = "INIT_MODULE: $SIZE_EXPORT_NODEP " ]
[ "`modprobe -i export_nodep-$BITNESS 2>&1`" = "INIT_MODULE: $SIZE_EXPORT_NODEP " ]
[ "`modprobe -i foo 2>&1`" = "FATAL: Module foo not found." ]
-[ "`modprobe -r --ignore-remove export_nodep-$BITNESS 2>&1`" = "DELETE_MODULE: export_nodep_$BITNESS EXCL " ]
-[ "`modprobe -r -i export_nodep-$BITNESS 2>&1`" = "DELETE_MODULE: export_nodep_$BITNESS EXCL " ]
-[ "`modprobe -i -r foo 2>&1`" = "FATAL: Module foo not found." ]
-# Test install & remove (fake modules)
+# Test install commands (fake modules)
[ "`modprobe foo 2>&1`" = "SYSTEM: echo Installing foo" ]
[ "`modprobe bar 2>&1`" = "SYSTEM: echo Installing bar" ]
[ "`modprobe baz 2>&1`" = "SYSTEM: echo Installing baz" ]
-[ "`modprobe -r foo 2>&1`" = "SYSTEM: echo Removing foo" ]
-[ "`modprobe -r bar 2>&1`" = "SYSTEM: echo Removing bar" ]
-[ "`modprobe -r baz 2>&1`" = "SYSTEM: echo Removing baz" ]
-# Test install & remove of a what is also a real module.
+# Test install of a what is also a real module.
[ "`modprobe export_nodep-$BITNESS 2>&1`" = "SYSTEM: echo Installing export_nodep" ]
-[ "`modprobe -r export_nodep-$BITNESS 2>&1`" = "SYSTEM: echo Removing export_nodep" ]
-# Test install & remove of what is also a real module via dependency.
+# Test install of what is also a real module via dependency.
[ "`modprobe noexport_dep-$BITNESS 2>&1`" = "SYSTEM: echo Installing export_nodep
INIT_MODULE: $SIZE_NOEXPORT_DEP I am noexport_dep" ]
-[ "`modprobe -r noexport_dep-$BITNESS 2>&1`" = "DELETE_MODULE: noexport_dep_$BITNESS EXCL
-SYSTEM: echo Removing export_nodep" ]
-# Test ignoring install & remove: only effects commandline.
+# Test ignoring install commands: only effects commandline.
[ "`modprobe -i noexport_dep-$BITNESS 2>&1`" = "SYSTEM: echo Installing export_nodep
INIT_MODULE: $SIZE_NOEXPORT_DEP I am noexport_dep" ]
-[ "`modprobe -r -i noexport_dep-$BITNESS 2>&1`" = "DELETE_MODULE: noexport_dep_$BITNESS EXCL
-SYSTEM: echo Removing export_nodep" ]
# Test options
[ "`modprobe noexport_nodep-$BITNESS 2>&1`" = "INIT_MODULE: $SIZE_NOEXPORT_NODEP I am noexport_nodep" ]
@@ -173,6 +164,39 @@ INIT_MODULE: $SIZE_NOEXPORT_DOUBLEDEP I am noexport_doubledep I am alias to noex
# Test tab-to-spaces conversion, and \ wrapping.
[ "`modprobe alias_to_noexport_nodep-$BITNESS_with_tabbed_options 2>&1`" = "INIT_MODULE: $SIZE_NOEXPORT_NODEP I am noexport_nodep index=0 id=\"Thinkpad\" isapnp=0 port=0x530 cport=0x538 fm_port=0x388 mpu_port=-1 mpu_irq=-1 irq=9 dma1=1 dma2=3 enable=1 isapnp=0" ]
+# Populate /sys/module/ for remove commands
+mkdir -p tests/tmp/sys/module/noexport_nodep_$BITNESS
+mkdir -p tests/tmp/sys/module/noexport_dep_$BITNESS
+mkdir -p tests/tmp/sys/module/noexport_doubledep_$BITNESS
+mkdir -p tests/tmp/sys/module/export_nodep_$BITNESS
+mkdir -p tests/tmp/sys/module/export_dep_$BITNESS
+echo live > tests/tmp/sys/module/noexport_nodep_$BITNESS/initstate
+echo live > tests/tmp/sys/module/noexport_dep_$BITNESS/initstate
+echo live > tests/tmp/sys/module/noexport_doubledep_$BITNESS/initstate
+echo live > tests/tmp/sys/module/export_nodep_$BITNESS/initstate
+echo live > tests/tmp/sys/module/export_dep_$BITNESS/initstate
+
+# Test ignoring remove commands.
+[ "`modprobe -r --ignore-remove export_nodep-$BITNESS 2>&1`" = "DELETE_MODULE: export_nodep_$BITNESS EXCL " ]
+[ "`modprobe -r -i export_nodep-$BITNESS 2>&1`" = "DELETE_MODULE: export_nodep_$BITNESS EXCL " ]
+[ "`modprobe -i -r foo 2>&1`" = "FATAL: Module foo not found." ]
+
+# Test remove commands (fake modules)
+[ "`modprobe -r foo 2>&1`" = "SYSTEM: echo Removing foo" ]
+[ "`modprobe -r bar 2>&1`" = "SYSTEM: echo Removing bar" ]
+[ "`modprobe -r baz 2>&1`" = "SYSTEM: echo Removing baz" ]
+
+# Test remove of a what is also a real module.
+[ "`modprobe -r export_nodep-$BITNESS 2>&1`" = "SYSTEM: echo Removing export_nodep" ]
+
+# Test remove of what is also a real module via dependency.
+[ "`modprobe -r noexport_dep-$BITNESS 2>&1`" = "DELETE_MODULE: noexport_dep_$BITNESS EXCL
+SYSTEM: echo Removing export_nodep" ]
+
+# Test ignoring remove commands: only effects commandline.
+[ "`modprobe -r -i noexport_dep-$BITNESS 2>&1`" = "DELETE_MODULE: noexport_dep_$BITNESS EXCL
+SYSTEM: echo Removing export_nodep" ]
+
# Test aliases doing removal.
[ "`modprobe -r alias_to_noexport_nodep-$BITNESS 2>&1`" = "DELETE_MODULE: noexport_nodep_$BITNESS EXCL " ]
[ "`modprobe -r alias_to_noexport_dep-$BITNESS 2>&1`" = "DELETE_MODULE: noexport_dep_$BITNESS EXCL
@@ -186,3 +210,19 @@ SYSTEM: echo Removing export_nodep" ]
[ "`modprobe -r alias_to_foo 2>&1`" = "SYSTEM: echo Removing foo" ]
[ "`modprobe -r alias_to_bar 2>&1`" = "SYSTEM: echo Removing bar" ]
[ "`modprobe -r alias_to_baz 2>&1`" = "SYSTEM: echo Removing baz" ]
+
+# Now test install precaution in the absence of /sys/modules
+rm -r tests/tmp/sys/module
+
+# Test install and remove commands (fake modules)
+# No caution necessary here
+[ "`modprobe foo 2>&1`" = "SYSTEM: echo Installing foo" ]
+[ "`modprobe -r foo 2>&1`" = "SYSTEM: echo Removing foo" ]
+
+# Test install and remove of a what is also a real module.
+[ "`modprobe export_nodep-$BITNESS 2>&1`" = "WARNING: /sys/module/ not present or too old, and /proc/modules does not exist.
+WARNING: Ignoring install commands for export_nodep_$BITNESS in case it is already loaded.
+INIT_MODULE: $SIZE_EXPORT_NODEP " ]
+[ "`modprobe -r export_nodep-$BITNESS 2>&1`" = "WARNING: /sys/module/ not present or too old, and /proc/modules does not exist.
+WARNING: Ignoring remove commands for export_nodep_$BITNESS in case it is not loaded.
+DELETE_MODULE: export_nodep_32 EXCL " ]
diff --git a/tests/test-modprobe/12whitespace.sh b/tests/test-modprobe/12whitespace.sh
index 159c4c2..5a1d817 100755
--- a/tests/test-modprobe/12whitespace.sh
+++ b/tests/test-modprobe/12whitespace.sh
@@ -82,38 +82,29 @@ SIZE_NOEXPORT_DEP=`wc -c < tests/data/$BITNESS/normal/noexport_dep-$BITNESS.ko`
SIZE_EXPORT_DEP=`wc -c < tests/data/$BITNESS/normal/export_dep-$BITNESS.ko`
SIZE_NOEXPORT_DOUBLEDEP=`wc -c < tests/data/$BITNESS/normal/noexport_doubledep-$BITNESS.ko`
-# Test ignoring install & remove.
+# Empty /sys/module/ for install commands
+mkdir -p tests/tmp/sys/module
+# Test ignoring install commands.
[ "`modprobe --ignore-install export_nodep-$BITNESS 2>&1`" = "INIT_MODULE: $SIZE_EXPORT_NODEP " ]
[ "`modprobe -i export_nodep-$BITNESS 2>&1`" = "INIT_MODULE: $SIZE_EXPORT_NODEP " ]
[ "`modprobe -i foo 2>&1`" = "FATAL: Module foo not found." ]
-[ "`modprobe -r --ignore-remove export_nodep-$BITNESS 2>&1`" = "DELETE_MODULE: export_nodep_$BITNESS EXCL " ]
-[ "`modprobe -r -i export_nodep-$BITNESS 2>&1`" = "DELETE_MODULE: export_nodep_$BITNESS EXCL " ]
-[ "`modprobe -i -r foo 2>&1`" = "FATAL: Module foo not found." ]
-# Test install & remove (fake modules)
+# Test install commands (fake modules)
[ "`modprobe foo 2>&1`" = "SYSTEM: echo Installing foo" ]
[ "`modprobe bar 2>&1`" = "SYSTEM: echo Installing bar" ]
[ "`modprobe baz 2>&1`" = "SYSTEM: echo Installing baz" ]
-[ "`modprobe -r foo 2>&1`" = "SYSTEM: echo Removing foo" ]
-[ "`modprobe -r bar 2>&1`" = "SYSTEM: echo Removing bar" ]
-[ "`modprobe -r baz 2>&1`" = "SYSTEM: echo Removing baz" ]
-# Test install & remove of a what is also a real module.
+# Test install of a what is also a real module.
[ "`modprobe export_nodep-$BITNESS 2>&1`" = "SYSTEM: echo Installing export_nodep" ]
-[ "`modprobe -r export_nodep-$BITNESS 2>&1`" = "SYSTEM: echo Removing export_nodep" ]
-# Test install & remove of what is also a real module via dependency.
+# Test install of what is also a real module via dependency.
[ "`modprobe noexport_dep-$BITNESS 2>&1`" = "SYSTEM: echo Installing export_nodep
INIT_MODULE: $SIZE_NOEXPORT_DEP I am noexport_dep" ]
-[ "`modprobe -r noexport_dep-$BITNESS 2>&1`" = "DELETE_MODULE: noexport_dep_$BITNESS EXCL
-SYSTEM: echo Removing export_nodep" ]
-# Test ignoring install & remove: only effects commandline.
+# Test ignoring install commands: only effects commandline.
[ "`modprobe -i noexport_dep-$BITNESS 2>&1`" = "SYSTEM: echo Installing export_nodep
INIT_MODULE: $SIZE_NOEXPORT_DEP I am noexport_dep" ]
-[ "`modprobe -r -i noexport_dep-$BITNESS 2>&1`" = "DELETE_MODULE: noexport_dep_$BITNESS EXCL
-SYSTEM: echo Removing export_nodep" ]
# Test options
[ "`modprobe noexport_nodep-$BITNESS 2>&1`" = "INIT_MODULE: $SIZE_NOEXPORT_NODEP I am noexport_nodep" ]
@@ -164,6 +155,40 @@ INIT_MODULE: $SIZE_NOEXPORT_DOUBLEDEP I am noexport_doubledep I am alias to noex
[ "`modprobe alias_to_bar 2>&1`" = "SYSTEM: echo Installing bar" ]
[ "`modprobe alias_to_baz 2>&1`" = "SYSTEM: echo Installing baz" ]
+# Populate /sys/module/ for remove commands
+mkdir -p tests/tmp/sys/module/noexport_nodep_$BITNESS
+mkdir -p tests/tmp/sys/module/noexport_dep_$BITNESS
+mkdir -p tests/tmp/sys/module/noexport_doubledep_$BITNESS
+mkdir -p tests/tmp/sys/module/export_nodep_$BITNESS
+mkdir -p tests/tmp/sys/module/export_dep_$BITNESS
+echo live > tests/tmp/sys/module/noexport_nodep_$BITNESS/initstate
+echo live > tests/tmp/sys/module/noexport_dep_$BITNESS/initstate
+echo live > tests/tmp/sys/module/noexport_doubledep_$BITNESS/initstate
+echo live > tests/tmp/sys/module/export_nodep_$BITNESS/initstate
+echo live > tests/tmp/sys/module/export_dep_$BITNESS/initstate
+
+# Test ignoring remove commands.
+
+[ "`modprobe -r --ignore-remove export_nodep-$BITNESS 2>&1`" = "DELETE_MODULE: export_nodep_$BITNESS EXCL " ]
+[ "`modprobe -r -i export_nodep-$BITNESS 2>&1`" = "DELETE_MODULE: export_nodep_$BITNESS EXCL " ]
+[ "`modprobe -i -r foo 2>&1`" = "FATAL: Module foo not found." ]
+
+# Test remove commands (fake modules)
+[ "`modprobe -r foo 2>&1`" = "SYSTEM: echo Removing foo" ]
+[ "`modprobe -r bar 2>&1`" = "SYSTEM: echo Removing bar" ]
+[ "`modprobe -r baz 2>&1`" = "SYSTEM: echo Removing baz" ]
+
+# Test remove of a what is also a real module.
+[ "`modprobe -r export_nodep-$BITNESS 2>&1`" = "SYSTEM: echo Removing export_nodep" ]
+
+# Test remove of what is also a real module via dependency.
+[ "`modprobe -r noexport_dep-$BITNESS 2>&1`" = "DELETE_MODULE: noexport_dep_$BITNESS EXCL
+SYSTEM: echo Removing export_nodep" ]
+
+# Test ignoring remove commands: only effects commandline.
+[ "`modprobe -r -i noexport_dep-$BITNESS 2>&1`" = "DELETE_MODULE: noexport_dep_$BITNESS EXCL
+SYSTEM: echo Removing export_nodep" ]
+
# Test aliases doing removal.
[ "`modprobe -r alias_to_noexport_nodep-$BITNESS 2>&1`" = "DELETE_MODULE: noexport_nodep_$BITNESS EXCL " ]
[ "`modprobe -r alias_to_noexport_dep-$BITNESS 2>&1`" = "DELETE_MODULE: noexport_dep_$BITNESS EXCL
diff --git a/tests/test-modprobe/22recursiveinstall.sh b/tests/test-modprobe/22recursiveinstall.sh
index 0c98e1a..53b0c60 100755
--- a/tests/test-modprobe/22recursiveinstall.sh
+++ b/tests/test-modprobe/22recursiveinstall.sh
@@ -28,7 +28,7 @@ mkdir -p tests/tmp/sys/module
[ "`modprobe noexport_dep-$BITNESS 2>&1`" = "INIT_MODULE: $SIZE_EXPORT_NODEP
INIT_MODULE: $SIZE_NOEXPORT_DEP " ]
-# Check it's happy if we tell it dep is already instealled
+# Check it's happy if we tell it dep is already installed
mkdir -p tests/tmp/sys/module
mkdir -p tests/tmp/sys/module/export_nodep_$BITNESS
echo "live" >tests/tmp/sys/module/export_nodep_$BITNESS/initstate
@@ -37,7 +37,7 @@ echo "live" >tests/tmp/sys/module/export_nodep_$BITNESS/initstate
# If there's an install command, it will be done.
# Clean up sysfs (so we don't think it's loaded)
-rm -rf tests/tmp/sys
+rm -rf tests/tmp/sys/module/*
mkdir -p tests/tmp/etc/modprobe.d
echo "install export_nodep-$BITNESS COMMAND" > tests/tmp/etc/modprobe.d/modprobe.conf
@@ -53,7 +53,7 @@ echo "live" >tests/tmp/sys/module/export_nodep_$BITNESS/initstate
# Do dependencies even if install command.
# clean up sysfs (so we don't think it's loaded)
-rm -rf tests/tmp/sys
+rm -rf tests/tmp/sys/module/*
echo "install noexport_dep-$BITNESS COMMAND" > tests/tmp/etc/modprobe.d/modprobe.conf
diff --git a/tests/test-modprobe/27cmdline-install-remove.sh b/tests/test-modprobe/27cmdline-install-remove.sh
index fef02ff..9411222 100755
--- a/tests/test-modprobe/27cmdline-install-remove.sh
+++ b/tests/test-modprobe/27cmdline-install-remove.sh
@@ -19,6 +19,9 @@ echo "options noexport_nodep-$BITNESS file-options" > tests/tmp/etc/modprobe.d/m
echo "install noexport_nodep-$BITNESS modprobe --ignore-install noexport_nodep-$BITNESS \$CMDLINE_OPTS" >> tests/tmp/etc/modprobe.d/modprobe.conf
echo "install othertarget echo \$CMDLINE_OPTS otheropts" >> tests/tmp/etc/modprobe.d/modprobe.conf
+# Empty /sys/module/ for install commands
+mkdir -p tests/tmp/sys/module
+
# With quoted args
[ "`modprobe noexport_nodep-$BITNESS 'foo="bar baz"' 2>&1`" = "SYSTEM: modprobe --ignore-install noexport_nodep-$BITNESS foo=\"bar baz\"" ]
# With unquoted args
diff --git a/util.c b/util.c
index 4df11e0..59db9cb 100644
--- a/util.c
+++ b/util.c
@@ -4,6 +4,8 @@
#include <string.h>
#include <errno.h>
#include <elf.h>
+#include <sys/types.h>
+#include <regex.h>
#include "logging.h"
#include "util.h"
@@ -203,3 +205,30 @@ int __attribute__ ((pure)) native_endianness()
return (char) *((uint32_t*)("\1\0\0\2"));
}
+/*
+ * Compare "string" with extended regex "pattern". Include backward compatible
+ * matching of "*" as a wildcard by replacing it with ".*" automatically.
+ */
+int regex_match(const char *string, const char *pattern)
+{
+ int status;
+ regex_t re;
+ char *fix_pattern;
+
+ /* backward compatibility with old "match" code */
+ if (strncmp("*", pattern, 1) != 0)
+ fix_pattern = (char *)pattern;
+ else
+ fix_pattern = ".*"; /* match everything */
+
+ if (regcomp(&re, fix_pattern, REG_EXTENDED|REG_NOSUB) != 0)
+ return 0; /* alloc failure */
+
+ status = regexec(&re, string, (size_t) 0, NULL, 0);
+ regfree(&re);
+
+ if (status != 0)
+ return 0; /* no match */
+
+ return 1; /* match */
+}
diff --git a/util.h b/util.h
index d512072..2b50ca5 100644
--- a/util.h
+++ b/util.h
@@ -44,4 +44,6 @@ int native_endianness(void);
#define streq(a,b) (strcmp((a),(b)) == 0)
#define strstarts(a,start) (strncmp((a),(start), strlen(start)) == 0)
+int regex_match(const char *string, const char *pattern);
+
#endif
diff --git a/zlibsupport.c b/zlibsupport.c
index b159765..597820e 100644
--- a/zlibsupport.c
+++ b/zlibsupport.c
@@ -40,23 +40,6 @@ void *grab_contents(gzFile *gzfd, unsigned long *size)
return buffer;
}
-void *grab_fd(int fd, unsigned long *size)
-{
- gzFile gzfd;
-
- gzfd = gzdopen(fd, "rb");
- if (!gzfd) {
- if (errno == ENOMEM)
- fatal("Memory allocation failure in gzdopen\n");
- return NULL;
- }
-
- /* gzclose(gzfd) would close fd, which would drop locks.
- Don't blame zlib: POSIX locking semantics are so horribly
- broken that they should be ripped out. */
- return grab_contents(gzfd, size);
-}
-
/* gzopen handles uncompressed files transparently. */
void *grab_file(const char *filename, unsigned long *size)
{