File module-init-tools-suse.diff of Package module-init-tools
This patch contains suse-specific changes against upstream commit 9a1c905651a38d1f2c6d4d836f81b5e06a503521
diff --git a/depmod.c b/depmod.c
index 4c8caa0..b4e52b4 100644
--- a/depmod.c
+++ b/depmod.c
@@ -193,7 +193,7 @@ static void load_module_symvers(const char *filename)
/* eg. "0xb352177e\tfind_first_bit\tvmlinux\tEXPORT_SYMBOL" */
while (fgets(line, sizeof(line)-1, module_symvers)) {
- const char *ver, *sym, *where;
+ const char *ver, *sym, *where, *slash;
ver = strtok(line, " \t");
sym = strtok(NULL, " \t");
@@ -201,7 +201,9 @@ static void load_module_symvers(const char *filename)
if (!ver || !sym || !where)
continue;
- if (streq(where, "vmlinux"))
+ if (streq(where, "vmlinux") ||
+ (((slash = strrchr(where, '/'))) &&
+ streq(slash, "/built-in")))
add_symbol(sym, strtoull(ver, NULL, 16), NULL);
}
@@ -434,7 +436,7 @@ static const char *compress_path(const char *path, const char *basedir)
return path;
}
-static void output_deps(struct module *modules,
+static int output_deps(struct module *modules,
FILE *out, char *dirname)
{
struct module *i;
@@ -453,12 +455,13 @@ static void output_deps(struct module *modules,
}
fprintf(out, "\n");
}
+ return 1;
}
/* warn whenever duplicate module aliases, deps, or symbols are found. */
int warn_dups = 0;
-static void output_deps_bin(struct module *modules,
+static int output_deps_bin(struct module *modules,
FILE *out, char *dirname)
{
struct module *i;
@@ -495,6 +498,8 @@ static void output_deps_bin(struct module *modules,
index_write(index, out);
index_destroy(index);
+
+ return 1;
}
@@ -769,7 +774,7 @@ static struct module *parse_modules(struct module *list)
}
/* Simply dump hash table. */
-static void output_symbols(struct module *unused, FILE *out, char *dirname)
+static int output_symbols(struct module *unused, FILE *out, char *dirname)
{
unsigned int i;
@@ -786,9 +791,10 @@ static void output_symbols(struct module *unused, FILE *out, char *dirname)
}
}
}
+ return 1;
}
-static void output_symbols_bin(struct module *unused, FILE *out, char *dirname)
+static int output_symbols_bin(struct module *unused, FILE *out, char *dirname)
{
struct index_node *index;
unsigned int i;
@@ -817,9 +823,54 @@ static void output_symbols_bin(struct module *unused, FILE *out, char *dirname)
index_write(index, out);
index_destroy(index);
+
+ return 1;
}
-static void output_aliases(struct module *modules, FILE *out, char *dirname)
+static int output_builtin_bin(struct module *unused, FILE *out, char *dirname)
+{
+ struct index_node *index;
+ char *textfile, *line;
+ unsigned int linenum;
+ FILE *f;
+
+ nofail_asprintf(&textfile, "%s/modules.builtin", dirname);
+ if (!(f = fopen(textfile, "r"))) {
+ if (errno != ENOENT)
+ fatal("Could not open '%s': %s\n",
+ textfile, strerror(errno));
+ free(textfile);
+ return 0;
+ }
+ free(textfile);
+ index = index_create();
+
+ while ((line = getline_wrapped(f, &linenum)) != NULL) {
+ char *module = strrchr(line, '/');
+
+ if (!*line || *line == '#') {
+ free(line);
+ continue;
+ }
+ module = strrchr(line, '/');
+ if (module)
+ module++;
+ else
+ module = line;
+ if (ends_in(module, ".ko"))
+ module[strlen(module) - 3] = '\0';
+ underscores(module);
+ index_insert(index, module, "", 0);
+ free(line);
+ }
+ fclose(f);
+ index_write(index, out);
+ index_destroy(index);
+
+ return 1;
+}
+
+static int output_aliases(struct module *modules, FILE *out, char *dirname)
{
struct module *i;
struct elf_file *file;
@@ -849,9 +900,10 @@ static void output_aliases(struct module *modules, FILE *out, char *dirname)
}
strtbl_free(tbl);
}
+ return 1;
}
-static void output_aliases_bin(struct module *modules, FILE *out, char *dirname)
+static int output_aliases_bin(struct module *modules, FILE *out, char *dirname)
{
struct module *i;
struct elf_file *file;
@@ -901,11 +953,13 @@ static void output_aliases_bin(struct module *modules, FILE *out, char *dirname)
index_write(index, out);
index_destroy(index);
+
+ return 1;
}
struct depfile {
char *name;
- void (*func)(struct module *, FILE *, char *dirname);
+ int (*func)(struct module *, FILE *, char *dirname);
int map_file;
};
@@ -923,7 +977,8 @@ static struct depfile depfiles[] = {
{ "modules.alias", output_aliases, 0 },
{ "modules.alias.bin", output_aliases_bin, 0 },
{ "modules.symbols", output_symbols, 0 },
- { "modules.symbols.bin", output_symbols_bin, 0 }
+ { "modules.symbols.bin", output_symbols_bin, 0 },
+ { "modules.builtin.bin", output_builtin_bin, 0 },
};
/* If we can't figure it out, it's safe to say "true". */
@@ -1368,6 +1423,7 @@ int main(int argc, char *argv[])
for (i = 0; i < sizeof(depfiles)/sizeof(depfiles[0]); i++) {
FILE *out;
+ int res;
struct depfile *d = &depfiles[i];
char depname[strlen(dirname) + 1 + strlen(d->name) + 1];
char tmpname[strlen(dirname) + 1 + strlen(d->name) +
@@ -1388,12 +1444,18 @@ int main(int argc, char *argv[])
if (ends_in(depname, ".bin"))
continue;
}
- d->func(list, out, dirname);
- if (!doing_stdout) {
- fclose(out);
+ res = d->func(list, out, dirname);
+ if (doing_stdout)
+ continue;
+ fclose(out);
+ if (res) {
if (rename(tmpname, depname) < 0)
fatal("Could not rename %s into %s: %s\n",
tmpname, depname, strerror(errno));
+ } else {
+ if (unlink(tmpname) < 0)
+ warn("Could not delete %s: %s\n",
+ tmpname, strerror(errno));
}
}
diff --git a/doc/modprobe.conf.sgml b/doc/modprobe.conf.sgml
index cacc006..cd94511 100644
--- a/doc/modprobe.conf.sgml
+++ b/doc/modprobe.conf.sgml
@@ -176,6 +176,19 @@
</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term>allow_unsupported_modules <replaceable>[0|1]</replaceable>
+ </term>
+ <listitem>
+ <para>
+ In SUSE kernels, every kernel module has a flag 'supported'. If
+ this flag is not set loading this module will taint your kernel.
+ Setting this option to 0 disables loading of unsupported modules
+ and avoids tainting the kernel. This is typically set in
+ <filename>/etc/modprobe.d/unsupported-modules</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
</variablelist>
</refsect1>
<refsect1>
diff --git a/doc/modprobe.sgml b/doc/modprobe.sgml
index fde8ca7..01ee9e1 100644
--- a/doc/modprobe.sgml
+++ b/doc/modprobe.sgml
@@ -430,9 +430,28 @@
</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>--allow-unsupported-modules</option>
+ </term>
+ <listitem>
+ <para>
+ Load unsupported modules even if disabled in configuration.
+ </para>
+ </listitem>
+ </varlistentry>
</variablelist>
</refsect1>
<refsect1>
+ <title>RETURN VALUE</title>
+
+ <para>
+ <command>modprobe</command> returns 0 on success, 1 on an unspecified
+ error and 2 if the module is not supported. Use the
+ <option>--allow-unsupported-modules</option> option to force
+ using an unsupported module.
+ </para>
+ </refsect1>
+ <refsect1>
<title>ENVIRONMENT</title>
<para>
The MODPROBE_OPTIONS environment variable can also be used to
diff --git a/logging.c b/logging.c
index 4330269..46257ff 100644
--- a/logging.c
+++ b/logging.c
@@ -57,13 +57,15 @@ void error(const char *fmt, ...)
va_end(arglist);
}
+/* can be overriden for different kinds of errors */
+int fatal_exit_code = 1;
void fatal(const char *fmt, ...)
{
va_list arglist;
va_start(arglist, fmt);
message("FATAL: ", fmt, &arglist);
va_end(arglist);
- exit(1);
+ exit(fatal_exit_code);
}
/* If we don't flush, then child processes print before we do */
diff --git a/logging.h b/logging.h
index c01187b..7445ab4 100644
--- a/logging.h
+++ b/logging.h
@@ -10,6 +10,9 @@ extern int quiet;
/* Do we want informative messages as well as errors? */
extern int verbose;
+/* Exit code returned by fatal() */
+extern int fatal_exit_code;
+
extern void fatal(const char *fmt, ...);
extern void error(const char *fmt, ...);
extern void warn(const char *fmt, ...);
diff --git a/modprobe.c b/modprobe.c
index 21a3111..72d9c10 100644
--- a/modprobe.c
+++ b/modprobe.c
@@ -51,6 +51,9 @@
int use_binary_indexes = 1; /* default to enabled. */
+/* Allow loading of unsupported modules? */
+static int allow_unsupported = 1;
+
extern long init_module(void *, unsigned long, const char *);
extern long delete_module(const char *, unsigned int);
@@ -69,8 +72,9 @@ typedef enum
mit_ignore_commands = 16,
mit_ignore_loaded = 32,
mit_strip_vermagic = 64,
- mit_strip_modversion = 128
+ mit_strip_modversion = 128,
+ mit_force_allow_unsupported = 1<<20,
} modprobe_flags_t;
#ifndef MODULE_DIR
@@ -354,6 +358,23 @@ static void clear_magic(struct elf_file *module)
}
}
+static int module_supported(struct elf_file *module)
+{
+ struct string_table *tbl;
+ int j;
+
+ /* Grab from new-style .modinfo section. */
+ tbl = module->ops->load_strings(module, ".modinfo", NULL, fatal);
+ for (j = 0; tbl && j < tbl->cnt; j++) {
+ const char *p = tbl->str[j];
+ if (streq(p, "supported=yes") ||
+ streq(p, "supported=external")) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
struct module_options
{
struct module_options *next;
@@ -537,6 +558,24 @@ static int read_attribute(const char *filename, char *buf, size_t buflen)
return (s == NULL) ? -1 : 1;
}
+/* is this a built-in module?
+ * 0: no, 1: yes, -1: don't know
+ */
+static int module_builtin(const char *dirname, const char *modname)
+{
+ struct index_file *index;
+ char *filename, *value;
+
+ nofail_asprintf(&filename, "%s/modules.builtin.bin", dirname);
+ index = index_file_open(filename);
+ free(filename);
+ if (!index)
+ return -1;
+ value = index_search(index, modname);
+ free(value);
+ return value ? 1 : 0;
+}
+
/* Is module in /sys/module? If so, fill in usecount if not NULL.
0 means no, 1 means yes, -1 means unknown.
*/
@@ -787,6 +826,16 @@ static int parse_config_file(const char *filename,
if (streq(tmp, "no"))
use_binary_indexes = 0;
}
+ } else if (strcmp(cmd, "allow_unsupported_modules") == 0) {
+ const char *option = strsep_skipspace(&ptr, "\t ");
+ if (!option)
+ grammar(cmd, filename, linenum);
+ else if (streq(option, "yes") || streq(option, "1"))
+ allow_unsupported = 1;
+ else if (streq(option, "no") || streq(option, "0"))
+ allow_unsupported = 0;
+ else
+ grammar(cmd, filename, linenum);
} else
grammar(cmd, filename, linenum);
@@ -1144,6 +1193,17 @@ static int insmod(struct list_head *list,
strerror(errno));
goto out_unlock;
}
+ /* Supported? */
+ if (!allow_unsupported && !module_supported(module)) {
+ if (error == fatal)
+ fatal_exit_code = 2;
+ error("module '%s' is unsupported\n"
+ "Use --allow-unsupported or set allow_unsupported_modules to 1 in\n"
+ "/etc/modprobe.d/10-unsupported-modules.conf\n",
+ mod->filename);
+ goto out;
+ }
+
if (newname)
rename_module(module, mod->modname, newname);
if (flags & mit_strip_modversion)
@@ -1309,6 +1369,16 @@ int do_modprobe(char *modname,
/* Returns the resolved alias, options */
parse_toplevel_config(configname, modname, 0,
flags & mit_remove, &modoptions, &commands, &aliases, &blacklist);
+ if (flags & mit_force_allow_unsupported)
+ allow_unsupported = 1;
+ /* Be nice to people running non-suse kernels and allow
+ * unsupported modules */
+ if (!allow_unsupported) {
+ if (access("/proc/sys/kernel/", F_OK) == 0 &&
+ access("/proc/sys/kernel/unsupported", F_OK) == -1 &&
+ errno == ENOENT)
+ allow_unsupported = 1;
+ }
/* Read module options from kernel command line */
parse_kcmdline(0, &modoptions);
@@ -1331,6 +1401,11 @@ int do_modprobe(char *modname,
modname, 0, flags & mit_remove,
&modoptions, &commands,
&aliases, &blacklist);
+ /* builtin module? */
+ if (!aliases && module_builtin(dirname, modname) == 1) {
+ info("builtin %s\n", modname);
+ return 0;
+ }
}
}
@@ -1390,6 +1465,8 @@ static struct option options[] = { { "version", 0, NULL, 'V' },
{ "force-modversion", 0, NULL, 2 },
{ "first-time", 0, NULL, 3 },
{ "dump-modversions", 0, NULL, 4 },
+ { "allow-unsupported-modules", 0, NULL, 128 },
+ { "use-blacklist", 0, NULL, 'b' },
{ NULL, 0, NULL, 0 } };
int main(int argc, char *argv[])
@@ -1494,6 +1571,9 @@ int main(int argc, char *argv[])
case 4:
dump_modver = 1;
break;
+ case 128:
+ flags |= mit_force_allow_unsupported;
+ break;
default:
print_usage(argv[0]);
}
diff --git a/tables.c b/tables.c
index 2f44450..c862920 100644
--- a/tables.c
+++ b/tables.c
@@ -34,7 +34,7 @@ static void output_pci_entry(struct pci_device_id *pci, char *name, FILE *out,
END(pci->class_mask, conv));
}
-void output_pci_table(struct module *modules, FILE *out, char *dirname)
+int output_pci_table(struct module *modules, FILE *out, char *dirname)
{
struct module *i;
@@ -53,6 +53,7 @@ void output_pci_table(struct module *modules, FILE *out, char *dirname)
for (e = t->pci_table; e->vendor; e = (void *)e + t->pci_size)
output_pci_entry(e, shortname, out, i->file->conv);
}
+ return 1;
}
/* We set driver_info to zero */
@@ -78,7 +79,7 @@ static void output_usb_entry(struct usb_device_id *usb, char *name, FILE *out,
END(usb->bInterfaceProtocol, conv));
}
-void output_usb_table(struct module *modules, FILE *out, char *dirname)
+int output_usb_table(struct module *modules, FILE *out, char *dirname)
{
struct module *i;
@@ -104,6 +105,7 @@ void output_usb_table(struct module *modules, FILE *out, char *dirname)
e = (void *)e + t->usb_size)
output_usb_entry(e, shortname, out, i->file->conv);
}
+ return 1;
}
static void output_ieee1394_entry(struct ieee1394_device_id *fw, char *name,
@@ -118,7 +120,7 @@ static void output_ieee1394_entry(struct ieee1394_device_id *fw, char *name,
END(fw->version, conv));
}
-void output_ieee1394_table(struct module *modules, FILE *out, char *dirname)
+int output_ieee1394_table(struct module *modules, FILE *out, char *dirname)
{
struct module *i;
@@ -138,6 +140,7 @@ void output_ieee1394_table(struct module *modules, FILE *out, char *dirname)
fw = (void *) fw + t->ieee1394_size)
output_ieee1394_entry(fw, shortname, out, i->file->conv);
}
+ return 1;
}
@@ -151,7 +154,7 @@ static void output_ccw_entry(struct ccw_device_id *ccw, char *name, FILE *out,
END(ccw->dev_type, conv), END(ccw->dev_model, conv));
}
-void output_ccw_table(struct module *modules, FILE *out, char *dirname)
+int output_ccw_table(struct module *modules, FILE *out, char *dirname)
{
struct module *i;
@@ -172,6 +175,7 @@ void output_ccw_table(struct module *modules, FILE *out, char *dirname)
e = (void *) e + t->ccw_size)
output_ccw_entry(e, shortname, out, i->file->conv);
}
+ return 1;
}
#define ISAPNP_VENDOR(a,b,c) (((((a)-'A'+1)&0x3f)<<2)|\
@@ -192,7 +196,7 @@ static void put_isapnp_id(FILE *out, const char *id)
fprintf(out, " 0x%04x 0x%04x ", vendor, device);
}
-void output_isapnp_table(struct module *modules, FILE *out, char *dirname)
+int output_isapnp_table(struct module *modules, FILE *out, char *dirname)
{
struct module *i;
@@ -238,6 +242,7 @@ void output_isapnp_table(struct module *modules, FILE *out, char *dirname)
}
}
}
+ return 1;
}
#define MATCH_bustype 1
@@ -412,7 +417,7 @@ static int output_input_entry_64_old(struct input_device_id_old_64 *input,
return 0;
}
-void output_input_table(struct module *modules, FILE *out, char *dirname)
+int output_input_table(struct module *modules, FILE *out, char *dirname)
{
struct module *i;
@@ -468,6 +473,7 @@ void output_input_table(struct module *modules, FILE *out, char *dirname)
}
}
}
+ return 1;
}
static void output_serio_entry(struct serio_device_id *serio, char *name, FILE *out)
@@ -482,7 +488,7 @@ static void output_serio_entry(struct serio_device_id *serio, char *name, FILE *
}
-void output_serio_table(struct module *modules, FILE *out, char *dirname)
+int output_serio_table(struct module *modules, FILE *out, char *dirname)
{
struct module *i;
@@ -500,6 +506,7 @@ void output_serio_table(struct module *modules, FILE *out, char *dirname)
for (e = t->serio_table; e->type || e->proto; e = (void *)e + t->serio_size)
output_serio_entry(e, shortname, out);
}
+ return 1;
}
@@ -542,7 +549,7 @@ static void output_of_entry(struct of_device_id *dev, char *name, FILE *out)
free(compatible);
}
-void output_of_table(struct module *modules, FILE *out, char *dirname)
+int output_of_table(struct module *modules, FILE *out, char *dirname)
{
struct module *i;
@@ -560,4 +567,5 @@ void output_of_table(struct module *modules, FILE *out, char *dirname)
e = (void *)e + t->of_size)
output_of_entry(e, shortname, out);
}
+ return 1;
}
diff --git a/tables.h b/tables.h
index 8a1420f..920e8df 100644
--- a/tables.h
+++ b/tables.h
@@ -175,13 +175,13 @@ struct of_device_id {
/* Functions provided by tables.c */
struct module;
-void output_usb_table(struct module *modules, FILE *out, char *dirname);
-void output_ieee1394_table(struct module *modules, FILE *out, char *dirname);
-void output_pci_table(struct module *modules, FILE *out, char *dirname);
-void output_ccw_table(struct module *modules, FILE *out, char *dirname);
-void output_isapnp_table(struct module *modules, FILE *out, char *dirname);
-void output_input_table(struct module *modules, FILE *out, char *dirname);
-void output_serio_table(struct module *modules, FILE *out, char *dirname);
-void output_of_table(struct module *modules, FILE *out, char *dirname);
+int output_usb_table(struct module *modules, FILE *out, char *dirname);
+int output_ieee1394_table(struct module *modules, FILE *out, char *dirname);
+int output_pci_table(struct module *modules, FILE *out, char *dirname);
+int output_ccw_table(struct module *modules, FILE *out, char *dirname);
+int output_isapnp_table(struct module *modules, FILE *out, char *dirname);
+int output_input_table(struct module *modules, FILE *out, char *dirname);
+int output_serio_table(struct module *modules, FILE *out, char *dirname);
+int output_of_table(struct module *modules, FILE *out, char *dirname);
#endif /* MODINITTOOLS_TABLES_H */
diff --git a/zlibsupport.c b/zlibsupport.c
index b159765..0f78524 100644
--- a/zlibsupport.c
+++ b/zlibsupport.c
@@ -12,6 +12,8 @@
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
+#include <stdio.h>
+#include <string.h>
#include "zlibsupport.h"
#include "logging.h"
@@ -19,69 +21,35 @@
#ifdef CONFIG_USE_ZLIB
#include <zlib.h>
+#endif
-void *grab_contents(gzFile *gzfd, unsigned long *size)
+#ifdef CONFIG_USE_ZLIB
+static int check_gz_magic(int fd)
{
- unsigned int max = 16384;
- void *buffer = NOFAIL(malloc(max));
- int ret;
-
- *size = 0;
- while ((ret = gzread(gzfd, buffer + *size, max - *size)) > 0) {
- *size += ret;
- if (*size == max)
- buffer = NOFAIL(realloc(buffer, max *= 2));
- }
- if (ret < 0) {
- free(buffer);
- buffer = NULL;
- }
-
- return buffer;
+ unsigned char magic[2];
+
+ if (read(fd, magic, 2) != 2)
+ return -1;
+ lseek(fd, 0, SEEK_SET);
+ if (magic[0] == 0x1f && magic[1] == 0x8b)
+ return 1;
+ return 0;
}
-void *grab_fd(int fd, unsigned long *size)
+static char *tmpdir(void)
{
- 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);
+ static char *TMPDIR;
+
+ if (TMPDIR)
+ return TMPDIR;
+ TMPDIR = getenv("TMPDIR");
+ if (!TMPDIR)
+ TMPDIR = "/tmp";
+ return TMPDIR;
}
+#endif
-/* gzopen handles uncompressed files transparently. */
-void *grab_file(const char *filename, unsigned long *size)
-{
- gzFile gzfd;
- void *buffer;
-
- errno = 0;
- gzfd = gzopen(filename, "rb");
- if (!gzfd) {
- if (errno == ENOMEM)
- fatal("Memory allocation failure in gzopen\n");
- return NULL;
- }
- buffer = grab_contents(gzfd, size);
- gzclose(gzfd);
- return buffer;
-}
-
-void release_file(void *data, unsigned long size)
-{
- free(data);
-}
-#else /* ... !CONFIG_USE_ZLIB */
-
-void *grab_fd(int fd, unsigned long *size)
+void *do_grab_fd(int fd, unsigned long *size)
{
struct stat st;
void *map;
@@ -97,6 +65,60 @@ void *grab_fd(int fd, unsigned long *size)
return map;
}
+void *grab_fd(int fd, unsigned long *size)
+{
+#ifdef CONFIG_USE_ZLIB
+ int magic = check_gz_magic(fd);
+ if (magic == -1)
+ return NULL;
+ if (magic) {
+ gzFile gzfd;
+ int tmp;
+ char buffer[4096];
+ char *template;
+ int r, w;
+ void *ret = NULL;
+
+ template = NOFAIL(malloc(strlen(tmpdir()) + sizeof("/m-i-t.XXXXXX")));
+ sprintf(template, "%s/m-i-t.XXXXXX", tmpdir());
+ gzfd = gzdopen(dup(fd), "rb");
+ if (!gzfd) {
+ if (errno == ENOMEM)
+ fatal("Memory allocation failure in gzdopen\n");
+ goto out_template;
+ }
+ tmp = mkstemp(template);
+ if (tmp == -1)
+ goto out_template;
+
+ while ((r = gzread(gzfd, buffer, sizeof(buffer))) > 0) {
+ char *p = buffer;
+ do {
+ w = write(tmp, p, r);
+ if (w > 0) {
+ r -= w;
+ p += w;
+ }
+ } while (w > 0 || (w == -1 && errno == EINTR));
+ if (w == -1)
+ goto out;
+ }
+ if (r < 0)
+ goto out;
+ gzclose(gzfd);
+ ret = do_grab_fd(tmp, size);
+out:
+ close(tmp);
+ unlink(template);
+out_template:
+ free(template);
+ return ret;
+ } else
+#endif
+ return do_grab_fd(fd, size);
+}
+
+
void *grab_file(const char *filename, unsigned long *size)
{
int fd;
@@ -114,4 +136,4 @@ void release_file(void *data, unsigned long size)
{
munmap(data, size);
}
-#endif
+