~ubuntu-branches/ubuntu/trusty/kmod/trusty

« back to all changes in this revision

Viewing changes to tools/static-nodes.c

  • Committer: Package Import Robot
  • Author(s): Martin Pitt
  • Date: 2013-10-24 06:16:30 UTC
  • mfrom: (1.1.5)
  • Revision ID: package-import@ubuntu.com-20131024061630-o87ipf2zxqtpigls
Tags: 15-0ubuntu1
* New upstream release. (See Debian #716739)
* Drop patches included upstream: dot_kcmdline, bad_alias_assertion,
  blacklist_aliased.
* Drop check_builtin_kver, this would only apply to lucid and is otherwise
  unnecessary.
* Drop --disable-shared/--enable-static, this got dropped in this version
  and isn't necessary any more. /bin/kmod does not dynamically link to
  libkmod by default now.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * kmod-static-nodes - manage modules.devname
 
3
 *
 
4
 * Copyright (C) 2004-2012 Kay Sievers <kay@vrfy.org>
 
5
 * Copyright (C) 2011-2013  ProFUSION embedded systems
 
6
 * Copyright (C) 2013 Tom Gundersen <teg@jklm.no>
 
7
 *
 
8
 * This program is free software: you can redistribute it and/or modify
 
9
 * it under the terms of the GNU General Public License as published by
 
10
 * the Free Software Foundation, either version 2 of the License, or
 
11
 * (at your option) any later version.
 
12
 *
 
13
 * This program is distributed in the hope that it will be useful,
 
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
 * GNU General Public License for more details.
 
17
 *
 
18
 * You should have received a copy of the GNU General Public License
 
19
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
20
 */
 
21
 
 
22
#include <stdio.h>
 
23
#include <stdlib.h>
 
24
#include <stddef.h>
 
25
#include <getopt.h>
 
26
#include <errno.h>
 
27
#include <unistd.h>
 
28
#include <string.h>
 
29
#include <limits.h>
 
30
#include <sys/utsname.h>
 
31
#include <sys/stat.h>
 
32
#include <sys/types.h>
 
33
#include "libkmod-util.h"
 
34
 
 
35
#include "kmod.h"
 
36
 
 
37
struct static_nodes_format {
 
38
        const char *name;
 
39
        int (*write)(FILE *, char[], char[], char, unsigned int, unsigned int);
 
40
        const char *description;
 
41
};
 
42
 
 
43
static const struct static_nodes_format static_nodes_format_human;
 
44
static const struct static_nodes_format static_nodes_format_tmpfiles;
 
45
static const struct static_nodes_format static_nodes_format_devname;
 
46
 
 
47
static const struct static_nodes_format *static_nodes_formats[] = {
 
48
        &static_nodes_format_human,
 
49
        &static_nodes_format_tmpfiles,
 
50
        &static_nodes_format_devname,
 
51
};
 
52
 
 
53
static const char cmdopts_s[] = "o:f:h";
 
54
static const struct option cmdopts[] = {
 
55
        { "output", required_argument, 0, 'o'},
 
56
        { "format", required_argument, 0, 'f'},
 
57
        { "help", no_argument, 0, 'h'},
 
58
        { },
 
59
};
 
60
 
 
61
static int write_human(FILE *out, char modname[], char devname[], char type, unsigned int maj, unsigned int min)
 
62
{
 
63
        int ret;
 
64
 
 
65
        ret = fprintf(out,
 
66
                        "Module: %s\n"
 
67
                        "\tDevice node: /dev/%s\n"
 
68
                        "\t\tType: %s device\n"
 
69
                        "\t\tMajor: %u\n"
 
70
                        "\t\tMinor: %u\n",
 
71
                        modname, devname,
 
72
                        (type == 'c') ? "character" : "block", maj, min);
 
73
        if (ret >= 0)
 
74
                return EXIT_SUCCESS;
 
75
        else
 
76
                return EXIT_FAILURE;
 
77
}
 
78
 
 
79
static const struct static_nodes_format static_nodes_format_human = {
 
80
        .name = "human",
 
81
        .write = write_human,
 
82
        .description = "(default) a human readable format. Do not parse.",
 
83
};
 
84
 
 
85
static int write_tmpfiles(FILE *out, char modname[], char devname[], char type, unsigned int maj, unsigned int min)
 
86
{
 
87
        const char *dir;
 
88
        int ret;
 
89
 
 
90
        dir = strrchr(devname, '/');
 
91
        if (dir) {
 
92
                ret = fprintf(out, "d /dev/%.*s 0755 - - -\n",
 
93
                              (int)(dir - devname), devname);
 
94
                if (ret < 0)
 
95
                        return EXIT_FAILURE;
 
96
        }
 
97
 
 
98
        ret = fprintf(out, "%c /dev/%s 0600 - - - %u:%u\n",
 
99
                      type, devname, maj, min);
 
100
        if (ret < 0)
 
101
                return EXIT_FAILURE;
 
102
 
 
103
        return EXIT_SUCCESS;
 
104
}
 
105
 
 
106
static const struct static_nodes_format static_nodes_format_tmpfiles = {
 
107
        .name = "tmpfiles",
 
108
        .write = write_tmpfiles,
 
109
        .description = "the tmpfiles.d(5) format used by systemd-tmpfiles.",
 
110
};
 
111
 
 
112
static int write_devname(FILE *out, char modname[], char devname[], char type, unsigned int maj, unsigned int min)
 
113
{
 
114
        int ret;
 
115
 
 
116
        ret = fprintf(out, "%s %s %c%u:%u\n", modname, devname, type, maj, min);
 
117
        if (ret >= 0)
 
118
                return EXIT_SUCCESS;
 
119
        else
 
120
                return EXIT_FAILURE;
 
121
}
 
122
 
 
123
static const struct static_nodes_format static_nodes_format_devname = {
 
124
        .name = "devname",
 
125
        .write = write_devname,
 
126
        .description = "the modules.devname format.",
 
127
};
 
128
 
 
129
static void help(void)
 
130
{
 
131
        size_t i;
 
132
 
 
133
        printf("Usage:\n"
 
134
               "\t%s static-nodes [options]\n"
 
135
               "\n"
 
136
               "kmod static-nodes outputs the static-node information of the currently running kernel.\n"
 
137
               "\n"
 
138
               "Options:\n"
 
139
               "\t-f, --format=FORMAT  choose format to use: see \"Formats\"\n"
 
140
               "\t-o, --output=FILE    write output to file\n"
 
141
               "\t-h, --help           show this help\n"
 
142
               "\n"
 
143
               "Formats:\n",
 
144
         program_invocation_short_name);
 
145
 
 
146
        for (i = 0; i < ARRAY_SIZE(static_nodes_formats); i++) {
 
147
                if (static_nodes_formats[i]->description != NULL) {
 
148
                        printf("\t%-12s %s\n", static_nodes_formats[i]->name,
 
149
                               static_nodes_formats[i]->description);
 
150
                }
 
151
        }
 
152
}
 
153
 
 
154
static int do_static_nodes(int argc, char *argv[])
 
155
{
 
156
        struct utsname kernel;
 
157
        char modules[PATH_MAX], buf[4096];
 
158
        const char *output = "/dev/stdout";
 
159
        FILE *in = NULL, *out = NULL;
 
160
        const struct static_nodes_format *format = &static_nodes_format_human;
 
161
        int r, ret = EXIT_SUCCESS;
 
162
 
 
163
        for (;;) {
 
164
                int c, idx = 0, valid;
 
165
                size_t i;
 
166
 
 
167
                c = getopt_long(argc, argv, cmdopts_s, cmdopts, &idx);
 
168
                if (c == -1) {
 
169
                        break;
 
170
                }
 
171
                switch (c) {
 
172
                case 'o':
 
173
                        output = optarg;
 
174
                        break;
 
175
                case 'f':
 
176
                        valid = 0;
 
177
 
 
178
                        for (i = 0; i < ARRAY_SIZE(static_nodes_formats); i++) {
 
179
                                if (streq(static_nodes_formats[i]->name, optarg)) {
 
180
                                        format = static_nodes_formats[i];
 
181
                                        valid = 1;
 
182
                                }
 
183
                        }
 
184
 
 
185
                        if (!valid) {
 
186
                                fprintf(stderr, "Unknown format: '%s'.\n",
 
187
                                        optarg);
 
188
                                help();
 
189
                                ret = EXIT_FAILURE;
 
190
                                goto finish;
 
191
                        }
 
192
                        break;
 
193
                case 'h':
 
194
                        help();
 
195
                        goto finish;
 
196
                case '?':
 
197
                        ret = EXIT_FAILURE;
 
198
                        goto finish;
 
199
                default:
 
200
                        fprintf(stderr, "Unexpected commandline option '%c'.\n",
 
201
                                c);
 
202
                        help();
 
203
                        ret = EXIT_FAILURE;
 
204
                        goto finish;
 
205
                }
 
206
        }
 
207
 
 
208
        if (uname(&kernel) < 0) {
 
209
                fputs("Error: uname failed!\n", stderr);
 
210
                ret = EXIT_FAILURE;
 
211
                goto finish;
 
212
        }
 
213
 
 
214
        snprintf(modules, sizeof(modules), "/lib/modules/%s/modules.devname", kernel.release);
 
215
        in = fopen(modules, "re");
 
216
        if (in == NULL) {
 
217
                if (errno == ENOENT) {
 
218
                        fprintf(stderr, "Warning: /lib/modules/%s/modules.devname not found - ignoring\n",
 
219
                                kernel.release);
 
220
                        ret = EXIT_SUCCESS;
 
221
                } else {
 
222
                        fprintf(stderr, "Error: could not open /lib/modules/%s/modules.devname - %m\n",
 
223
                                kernel.release);
 
224
                        ret = EXIT_FAILURE;
 
225
                }
 
226
                goto finish;
 
227
        }
 
228
 
 
229
        r = mkdir_parents(output, 0755);
 
230
        if (r < 0) {
 
231
                fprintf(stderr, "Error: could not create parent directory for %s - %m.\n", output);
 
232
                ret = EXIT_FAILURE;
 
233
                goto finish;
 
234
        }
 
235
 
 
236
        out = fopen(output, "we");
 
237
        if (out == NULL) {
 
238
                fprintf(stderr, "Error: could not create %s - %m\n", output);
 
239
                ret = EXIT_FAILURE;
 
240
                goto finish;
 
241
        }
 
242
 
 
243
        while (fgets(buf, sizeof(buf), in) != NULL) {
 
244
                char modname[PATH_MAX];
 
245
                char devname[PATH_MAX];
 
246
                char type;
 
247
                unsigned int maj, min;
 
248
                int matches;
 
249
 
 
250
                if (buf[0] == '#')
 
251
                        continue;
 
252
 
 
253
                matches = sscanf(buf, "%s %s %c%u:%u", modname, devname,
 
254
                                 &type, &maj, &min);
 
255
                if (matches != 5 || (type != 'c' && type != 'b')) {
 
256
                        fprintf(stderr, "Error: invalid devname entry: %s", buf);
 
257
                        ret = EXIT_FAILURE;
 
258
                        continue;
 
259
                }
 
260
 
 
261
                format->write(out, modname, devname, type, maj, min);
 
262
        }
 
263
 
 
264
finish:
 
265
        if (in)
 
266
                fclose(in);
 
267
        if (out)
 
268
                fclose(out);
 
269
        return ret;
 
270
}
 
271
 
 
272
const struct kmod_cmd kmod_cmd_static_nodes = {
 
273
        .name = "static-nodes",
 
274
        .cmd = do_static_nodes,
 
275
        .help = "outputs the static-node information installed with the currently running kernel",
 
276
};