f5a06cce52e72217764dbd769e6982f7602d4766
[febootstrap.git] / helper / main.c
1 /* febootstrap-supermin-helper reimplementation in C.
2  * Copyright (C) 2009-2010 Red Hat Inc.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18
19 #include <config.h>
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <unistd.h>
26 #include <getopt.h>
27 #include <limits.h>
28 #include <sys/types.h>
29 #include <sys/time.h>
30 #include <assert.h>
31
32 #include "error.h"
33
34 #include "helper.h"
35
36 struct timeval start_t;
37 int verbose = 0;
38
39 static const char *format = "cpio";
40
41 enum { HELP_OPTION = CHAR_MAX + 1 };
42
43 static const char *options = "f:k:vV";
44 static const struct option long_options[] = {
45   { "help", 0, 0, HELP_OPTION },
46   { "format", required_argument, 0, 'f' },
47   { "kmods", required_argument, 0, 'k' },
48   { "verbose", 0, 0, 'v' },
49   { "version", 0, 0, 'V' },
50   { 0, 0, 0, 0 }
51 };
52
53 static void
54 usage (const char *progname)
55 {
56   printf ("%s: build the supermin appliance on the fly\n"
57           "\n"
58           "Usage:\n"
59           "  %s [-options] inputs [...] whitelist host_cpu kernel initrd\n"
60           "  %s --help\n"
61           "  %s --version\n"
62           "\n"
63           "This script is used by febootstrap to build the supermin appliance\n"
64           "(kernel and initrd output files).  You should NOT need to run this\n"
65           "program directly except if you are debugging tricky supermin\n"
66           "appliance problems.\n"
67           "\n"
68           "NB: The kernel and initrd parameters are OUTPUT parameters.  If\n"
69           "those files exist, they are overwritten by the output.\n"
70           "\n"
71           "Options:\n"
72           "  --help\n"
73           "       Display this help text and exit.\n"
74           "  -f cpio | --format cpio\n"
75           "       Specify output format (default: cpio).\n"
76           "  -k file | --kmods file\n"
77           "       Specify kernel module whitelist.\n"
78           "  --verbose | -v\n"
79           "       Enable verbose messages (give multiple times for more verbosity).\n"
80           "  --version | -V\n"
81           "       Display version number and exit.\n",
82           progname, progname, progname, progname);
83 }
84
85 int
86 main (int argc, char *argv[])
87 {
88   /* First thing: start the clock. */
89   gettimeofday (&start_t, NULL);
90
91   const char *whitelist = NULL;
92
93   /* Command line arguments. */
94   for (;;) {
95     int c = getopt_long (argc, argv, options, long_options, NULL);
96     if (c == -1) break;
97
98     switch (c) {
99     case HELP_OPTION:
100       usage (argv[0]);
101       exit (EXIT_SUCCESS);
102
103     case 'f':
104       format = optarg;
105       break;
106
107     case 'k':
108       whitelist = optarg;
109       break;
110
111     case 'v':
112       verbose++;
113       break;
114
115     case 'V':
116       printf (PACKAGE_NAME " " PACKAGE_VERSION "\n");
117       exit (EXIT_SUCCESS);
118
119     default:
120       usage (argv[0]);
121       exit (EXIT_FAILURE);
122     }
123   }
124
125   /* Select the correct writer module. */
126   struct writer *writer;
127
128   if (strcmp (format, "cpio") == 0)
129     writer = &cpio_writer;
130   else {
131     fprintf (stderr, "%s: incorrect output format (-f): must be cpio\n",
132              argv[0]);
133     exit (EXIT_FAILURE);
134   }
135
136   char **inputs = &argv[optind];
137   int nr_inputs = argc - optind - 3;
138
139   if (nr_inputs < 1) {
140     usage (argv[0]);
141     exit (EXIT_FAILURE);
142   }
143
144   /* See: https://bugzilla.redhat.com/show_bug.cgi?id=558593 */
145   const char *hostcpu = argv[argc-3];
146
147   /* Output files. */
148   const char *kernel = argv[argc-2];
149   const char *appliance = argv[argc-1];
150
151   if (verbose) {
152     print_timestamped_message ("whitelist = %s, "
153                                "host_cpu = %s, "
154                                "kernel = %s, "
155                                "appliance = %s",
156                                whitelist ? : "(not specified)",
157                                hostcpu, kernel, appliance);
158     int i;
159     for (i = 0; i < nr_inputs; ++i)
160       print_timestamped_message ("inputs[%d] = %s", i, inputs[i]);
161   }
162
163   /* Remove the output files if they exist. */
164   unlink (kernel);
165   unlink (appliance);
166
167   /* Create kernel output file. */
168   const char *modpath;
169   modpath = create_kernel (hostcpu, kernel);
170
171   if (verbose)
172     print_timestamped_message ("finished creating kernel");
173
174   /* Create the appliance. */
175   create_appliance (inputs, nr_inputs, whitelist, modpath, appliance, writer);
176
177   if (verbose)
178     print_timestamped_message ("finished creating appliance");
179
180   exit (EXIT_SUCCESS);
181 }