Refactor cpio code into separate file.
[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 enum { HELP_OPTION = CHAR_MAX + 1 };
40
41 static const char *options = "k:vV";
42 static const struct option long_options[] = {
43   { "help", 0, 0, HELP_OPTION },
44   { "kmods", required_argument, 0, 'k' },
45   { "verbose", 0, 0, 'v' },
46   { "version", 0, 0, 'V' },
47   { 0, 0, 0, 0 }
48 };
49
50 static void
51 usage (const char *progname)
52 {
53   printf ("%s: build the supermin appliance on the fly\n"
54           "\n"
55           "Usage:\n"
56           "  %s [-options] inputs [...] whitelist host_cpu kernel initrd\n"
57           "  %s --help\n"
58           "  %s --version\n"
59           "\n"
60           "This script is used by febootstrap to build the supermin appliance\n"
61           "(kernel and initrd output files).  You should NOT need to run this\n"
62           "program directly except if you are debugging tricky supermin\n"
63           "appliance problems.\n"
64           "\n"
65           "NB: The kernel and initrd parameters are OUTPUT parameters.  If\n"
66           "those files exist, they are overwritten by the output.\n"
67           "\n"
68           "Options:\n"
69           "  --help\n"
70           "       Display this help text and exit.\n"
71           "  -k file | --kmods file\n"
72           "       Specify kernel module whitelist.\n"
73           "  --verbose | -v\n"
74           "       Enable verbose messages (give multiple times for more verbosity).\n"
75           "  --version | -V\n"
76           "       Display version number and exit.\n",
77           progname, progname, progname, progname);
78 }
79
80 int
81 main (int argc, char *argv[])
82 {
83   /* First thing: start the clock. */
84   gettimeofday (&start_t, NULL);
85
86   const char *whitelist = NULL;
87
88   /* Command line arguments. */
89   for (;;) {
90     int c = getopt_long (argc, argv, options, long_options, NULL);
91     if (c == -1) break;
92
93     switch (c) {
94     case HELP_OPTION:
95       usage (argv[0]);
96       exit (EXIT_SUCCESS);
97
98     case 'k':
99       whitelist = optarg;
100       break;
101
102     case 'v':
103       verbose++;
104       break;
105
106     case 'V':
107       printf (PACKAGE_NAME " " PACKAGE_VERSION "\n");
108       exit (EXIT_SUCCESS);
109
110     default:
111       usage (argv[0]);
112       exit (EXIT_FAILURE);
113     }
114   }
115
116   char **inputs = &argv[optind];
117   int nr_inputs = argc - optind - 3;
118
119   if (nr_inputs < 1) {
120     usage (argv[0]);
121     exit (EXIT_FAILURE);
122   }
123
124   /* See: https://bugzilla.redhat.com/show_bug.cgi?id=558593 */
125   const char *hostcpu = argv[argc-3];
126
127   /* Output files. */
128   const char *kernel = argv[argc-2];
129   const char *appliance = argv[argc-1];
130
131   if (verbose) {
132     print_timestamped_message ("whitelist = %s, "
133                                "host_cpu = %s, "
134                                "kernel = %s, "
135                                "appliance = %s",
136                                whitelist ? : "(not specified)",
137                                hostcpu, kernel, appliance);
138     int i;
139     for (i = 0; i < nr_inputs; ++i)
140       print_timestamped_message ("inputs[%d] = %s", i, inputs[i]);
141   }
142
143   /* Remove the output files if they exist. */
144   unlink (kernel);
145   unlink (appliance);
146
147   /* Create kernel output file. */
148   const char *modpath;
149   modpath = create_kernel (hostcpu, kernel);
150
151   if (verbose)
152     print_timestamped_message ("finished creating kernel");
153
154   /* Create the appliance. */
155   create_appliance (inputs, nr_inputs, whitelist, modpath, appliance,
156                     &cpio_writer);
157
158   if (verbose)
159     print_timestamped_message ("finished creating appliance");
160
161   exit (EXIT_SUCCESS);
162 }