Subject: Allow config extract embedded configuration files
To: None <tech-userlevel@netbsd.org>
From: Julio Merino <jmmv@menta.net>
List: tech-userlevel
Date: 04/14/2003 15:10:39
Hi,
as kernel files can contain embedded configuration files (with options
INCLUDE_CONFIG_FILE or INCLUDE_JUST_CONFIG), I think it could be good
if config(8) could automatically extract them and configure a new
kernel based on that information.
I've got a patch that does it (see below). I feel it's not very polished
and several things can be improved, but I don't know which ones are they.
Is it there any interest in this? Comments?
Index: config.8
===================================================================
RCS file: /cvsroot/src/usr.sbin/config/config.8,v
retrieving revision 1.22
diff -u -u -r1.22 config.8
--- config.8 2003/02/25 10:36:06 1.22
+++ config.8 2003/04/14 12:55:50
@@ -33,7 +33,7 @@
.\"
.\" from: @(#)config.8 8.2 (Berkeley) 4/19/94
.\"
-.Dd April 19, 1994
+.Dd April 14, 2003
.Dt CONFIG 8
.Os
.Sh NAME
@@ -106,6 +106,21 @@
directive at the beginning of the machine description file. You must
specify the location of the top-level kernel source directory if you
specify a build directory.
+.Pp
+If
+.Ar config-file
+is a binary kernel,
+.Nm
+will try to extract the configuration file embedded into it, which will
+be present if that kernel was built either with
+.Va INCLUDE_CONFIG_FILE
+or
+.Va INCLUDE_JUST_CONFIG
+options.
+This work mode requires you to manually specify a build directory with
+the
+.Fl b
+option, which implies the need to provide a source tree too.
.Pp
If the
.Fl p
Index: main.c
===================================================================
RCS file: /cvsroot/src/usr.sbin/config/main.c,v
retrieving revision 1.75
diff -u -u -r1.75 main.c
--- main.c 2003/01/27 05:00:54 1.75
+++ main.c 2003/04/14 12:55:56
@@ -62,6 +62,7 @@
#include <ctype.h>
#include <err.h>
#include <errno.h>
+#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -110,6 +111,9 @@
static FILE *cfg;
static time_t cfgtime;
+static int is_elf(const char *);
+static int extract_config(const char *, char *, int);
+
int badfilename(const char *fname);
const char *progname;
@@ -242,14 +246,44 @@
}
defbuilddir = (argc == 0) ? "." : p;
- /*
- * Parse config file (including machine definitions).
- */
- logconfig_start();
- if (yyparse())
- stop();
- logconfig_end();
+ if (is_elf(conffile)) {
+ char cname[20];
+
+ if (builddir == NULL) {
+ (void)fprintf(stderr,
+ "config: build directory must be specified with "
+ "binary kernels\n");
+ exit(1);
+ }
+
+ if (!extract_config(conffile, cname, sizeof(cname))) {
+ (void)fprintf(stderr,
+ "config: %s does not contain configuration "
+ "information\n", conffile);
+ exit(2);
+ }
+
+ firstfile(cname);
+
+ /*
+ * Parse config file (including machine definitions).
+ */
+ logconfig_start();
+ if (yyparse())
+ stop();
+ logconfig_end();
+ unlink(cname);
+ } else {
+ /*
+ * Parse config file (including machine definitions).
+ */
+ logconfig_start();
+ if (yyparse())
+ stop();
+ logconfig_end();
+ }
+
/*
* Select devices and pseudo devices and their attributes
*/
@@ -1297,3 +1331,107 @@
return (intern(low));
}
+static int
+is_elf(const char *file)
+{
+ int kernel;
+ char hdr[4];
+
+ kernel = open(file, O_RDONLY);
+ read(kernel, hdr, 4);
+ close(kernel);
+ return memcmp("\177ELF", hdr, 4) == 0 ? 1 : 0;
+}
+
+static int
+extract_config(const char *kname, char *cname, int cnamelen)
+{
+ char ibuf[LINE_MAX + 1], obuf[LINE_MAX + 1], *tmpdir;
+ int found, kfd, cfd;
+
+ found = 0;
+
+ /* Open binary kernel */
+ kfd = open(conffile, O_RDONLY);
+ if (kfd == -1) {
+ fprintf(stderr, "config: cannot open %s: %s", kname,
+ strerror(errno));
+ exit(2);
+ }
+
+ /* Open temporary configuration file */
+ tmpdir = getenv("TMPDIR");
+ if (tmpdir == NULL)
+ tmpdir = "/tmp";
+ snprintf(cname, cnamelen, "%s/config.tmp.XXXXXX", tmpdir);
+ cfd = mkstemp(cname);
+ if (cfd == -1) {
+ fprintf(stderr, "config: cannot create %s: %s", cname,
+ strerror(errno));
+ exit(2);
+ }
+
+ /* Extract configuration from kfd into cfd */
+ for (;;) {
+ int count;
+ char *ptr;
+
+ count = read(kfd, ibuf, LINE_MAX);
+ if (count == -1) {
+ (void)fprintf(stderr,
+ "config: cannot read from %s: %s", kname,
+ strerror(errno));
+ exit(2);
+ } else if (count == 0)
+ break;
+ ibuf[count] = '\0';
+
+ /* Convert \0's into anything else, so strstr(3) works */
+ for (ptr = ibuf; ptr < ibuf + count; ptr++)
+ if (*ptr == '\0')
+ *ptr = 1;
+
+ ptr = strstr(ibuf, "_CFG_");
+ if (ptr != NULL) {
+ int len;
+
+ if (!found) {
+ printf("Using configuration embedded in %s\n",
+ kname);
+ found = 1;
+ }
+
+ lseek(kfd, -(count - (ptr - ibuf)), SEEK_CUR);
+ count = read(kfd, ibuf, LINE_MAX);
+ if (count == -1) {
+ (void)fprintf(stderr,
+ "config: cannot read from %s: %s", kname,
+ strerror(errno));
+ exit(2);
+ }
+ ibuf[count] = '\0';
+
+ ptr = ibuf;
+ while (*ptr != '\n' && *ptr != '\0') ptr++;
+ *ptr = '\0';
+
+ strunvis(obuf, ibuf + 5);
+ len = strlen(obuf);
+ obuf[len] = '\n';
+ if (write(cfd, obuf, len + 1) == -1) {
+ (void)fprintf(stderr,
+ "config: cannot write to %s: %s", cname,
+ strerror(errno));
+ exit(2);
+ }
+
+ lseek(kfd, -(count - (ptr - ibuf)), SEEK_CUR);
+ } else if (count > 5)
+ lseek(kfd, -5, SEEK_CUR);
+ }
+
+ close(kfd);
+ close(cfd);
+
+ return found;
+}
Thanks.
--
Julio M. Merino Vidal <jmmv@menta.net>
The NetBSD Project - http://www.NetBSD.org/