10cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri/*
20cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri * kmod-modinfo - query kernel module information using libkmod.
30cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri *
4e6b0e49b4ea7937a98b16f23d621244ee1a3e588Lucas De Marchi * Copyright (C) 2011-2013  ProFUSION embedded systems
50cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri *
60cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri * This program is free software: you can redistribute it and/or modify
70cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri * it under the terms of the GNU General Public License as published by
80cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri * the Free Software Foundation, either version 2 of the License, or
90cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri * (at your option) any later version.
100cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri *
110cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri * This program is distributed in the hope that it will be useful,
120cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri * but WITHOUT ANY WARRANTY; without even the implied warranty of
130cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
140cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri * GNU General Public License for more details.
150cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri *
160cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri * You should have received a copy of the GNU General Public License
170cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri * along with this program.  If not, see <http://www.gnu.org/licenses/>.
180cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri */
190cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri
20c2e4286bb98c6bec77575ac0c6f862e7ddf6394fLucas De Marchi#include <errno.h>
21c2e4286bb98c6bec77575ac0c6f862e7ddf6394fLucas De Marchi#include <getopt.h>
22c2e4286bb98c6bec77575ac0c6f862e7ddf6394fLucas De Marchi#include <limits.h>
23c2e4286bb98c6bec77575ac0c6f862e7ddf6394fLucas De Marchi#include <stdbool.h>
240cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri#include <stdio.h>
250cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri#include <stdlib.h>
260cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri#include <string.h>
270cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri#include <sys/stat.h>
28c2e4286bb98c6bec77575ac0c6f862e7ddf6394fLucas De Marchi#include <sys/utsname.h>
29c2e4286bb98c6bec77575ac0c6f862e7ddf6394fLucas De Marchi
30f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi#include <shared/util.h>
31f4e8c16291c58b71dfc622c11f3e00c818dcaebbLucas De Marchi
32f357866d97995e30c0ad623880d28dc527ff6890Lucas De Marchi#include <libkmod/libkmod.h>
330cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri
344a2e20dfb3f94b0c5f0b8269b0dd84974a5dac56Lucas De Marchi#include "kmod.h"
354a2e20dfb3f94b0c5f0b8269b0dd84974a5dac56Lucas De Marchi
360cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieristatic char separator = '\n';
370cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieristatic const char *field = NULL;
380cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri
390cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieristruct param {
400cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	struct param *next;
410cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	const char *name;
420cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	const char *param;
430cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	const char *type;
440cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	int namelen;
450cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	int paramlen;
460cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	int typelen;
470cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri};
480cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri
490cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieristatic struct param *add_param(const char *name, int namelen, const char *param, int paramlen, const char *type, int typelen, struct param **list)
500cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri{
510cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	struct param *it;
520cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri
530cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	for (it = *list; it != NULL; it = it->next) {
540cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		if (it->namelen == namelen &&
550cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			memcmp(it->name, name, namelen) == 0)
560cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			break;
570cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	}
580cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri
590cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	if (it == NULL) {
600cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		it = malloc(sizeof(struct param));
610cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		if (it == NULL)
620cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			return NULL;
630cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		it->next = *list;
640cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		*list = it;
650cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		it->name = name;
660cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		it->namelen = namelen;
670cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		it->param = NULL;
680cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		it->type = NULL;
690cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		it->paramlen = 0;
700cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		it->typelen = 0;
710cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	}
720cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri
730cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	if (param != NULL) {
740cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		it->param = param;
750cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		it->paramlen = paramlen;
760cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	}
770cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri
780cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	if (type != NULL) {
790cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		it->type = type;
800cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		it->typelen = typelen;
810cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	}
820cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri
830cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	return it;
840cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri}
850cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri
86b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieristatic int process_parm(const char *key, const char *value, struct param **params)
87b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri{
88b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri	const char *name, *param, *type;
89b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri	int namelen, paramlen, typelen;
90b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri	struct param *it;
91b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri	const char *colon = strchr(value, ':');
92b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri	if (colon == NULL) {
939382dbf7aa8e65b3e080f154b7b986da0e1fbfceLucas De Marchi		ERR("Found invalid \"%s=%s\": missing ':'\n",
94b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri		    key, value);
95b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri		return 0;
96b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri	}
97b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri
98b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri	name = value;
99b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri	namelen = colon - value;
1005b0436a759f8561d35834a0458a2df70a60f9107Lucas De Marchi	if (streq(key, "parm")) {
101b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri		param = colon + 1;
102b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri		paramlen = strlen(param);
103b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri		type = NULL;
104b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri		typelen = 0;
105b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri	} else {
106b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri		param = NULL;
107b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri		paramlen = 0;
108b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri		type = colon + 1;
109b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri		typelen = strlen(type);
110b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri	}
111b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri
112b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri	it = add_param(name, namelen, param, paramlen, type, typelen, params);
113b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri	if (it == NULL) {
1149382dbf7aa8e65b3e080f154b7b986da0e1fbfceLucas De Marchi		ERR("Out of memory!\n");
115b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri		return -ENOMEM;
116b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri	}
117b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri
118b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri	return 0;
119b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri}
120b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri
121b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieristatic int modinfo_params_do(const struct kmod_list *list)
122b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri{
123b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri	const struct kmod_list *l;
124b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri	struct param *params = NULL;
125b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri	int err = 0;
126b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri
127b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri	kmod_list_foreach(l, list) {
128b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri		const char *key = kmod_module_info_get_key(l);
129b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri		const char *value = kmod_module_info_get_value(l);
1305b0436a759f8561d35834a0458a2df70a60f9107Lucas De Marchi		if (!streq(key, "parm") && !streq(key, "parmtype"))
131b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri			continue;
132b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri
133b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri		err = process_parm(key, value, &params);
134b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri		if (err < 0)
135b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri			goto end;
136b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri	}
137b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri
138b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri	while (params != NULL) {
139b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri		struct param *p = params;
140b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri		params = p->next;
141b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri
142b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri		if (p->param == NULL)
143b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri			printf("%.*s: (%.*s)%c",
144b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri			       p->namelen, p->name, p->typelen, p->type,
145b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri			       separator);
146b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri		else if (p->type != NULL)
147b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri			printf("%.*s:%.*s (%.*s)%c",
148b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri			       p->namelen, p->name,
149b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri			       p->paramlen, p->param,
150b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri			       p->typelen, p->type,
151b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri			       separator);
152b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri		else
153b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri			printf("%.*s:%.*s%c",
154b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri			       p->namelen, p->name,
155b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri			       p->paramlen, p->param,
156b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri			       separator);
157b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri
158b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri		free(p);
159b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri	}
160b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri
161b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieriend:
162b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri	while (params != NULL) {
163b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri		void *tmp = params;
164b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri		params = params->next;
165b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri		free(tmp);
166b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri	}
167b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri
168b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri	return err;
169b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri}
170b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri
1710cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieristatic int modinfo_do(struct kmod_module *mod)
1720cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri{
1730cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	struct kmod_list *l, *list = NULL;
1740cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	struct param *params = NULL;
1750cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	int err;
1760cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri
1775b0436a759f8561d35834a0458a2df70a60f9107Lucas De Marchi	if (field != NULL && streq(field, "filename")) {
1780cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		printf("%s%c", kmod_module_get_path(mod), separator);
1790cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		return 0;
1800cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	} else if (field == NULL) {
1810cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		printf("%-16s%s%c", "filename:",
1820cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		       kmod_module_get_path(mod), separator);
1830cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	}
1840cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri
1850cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	err = kmod_module_get_info(mod, &list);
1860cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	if (err < 0) {
1879382dbf7aa8e65b3e080f154b7b986da0e1fbfceLucas De Marchi		ERR("could not get modinfo from '%s': %s\n",
1880cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			kmod_module_get_name(mod), strerror(-err));
1890cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		return err;
1900cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	}
1910cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri
1925b0436a759f8561d35834a0458a2df70a60f9107Lucas De Marchi	if (field != NULL && streq(field, "parm")) {
193b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri		err = modinfo_params_do(list);
194b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri		goto end;
195b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri	}
196b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri
1970cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	kmod_list_foreach(l, list) {
1980cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		const char *key = kmod_module_info_get_key(l);
1990cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		const char *value = kmod_module_info_get_value(l);
2000cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		int keylen;
2010cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri
2020cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		if (field != NULL) {
2035b0436a759f8561d35834a0458a2df70a60f9107Lucas De Marchi			if (!streq(field, key))
2040cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri				continue;
2050cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			/* filtered output contains no key, just value */
2060cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			printf("%s%c", value, separator);
2070cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			continue;
2080cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		}
2090cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri
2105b0436a759f8561d35834a0458a2df70a60f9107Lucas De Marchi		if (streq(key, "parm") || streq(key, "parmtype")) {
211b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri			err = process_parm(key, value, &params);
212b014c490cb7dc1dd064393537c69ed5fd7b81ccfGustavo Sverzut Barbieri			if (err < 0)
2130cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri				goto end;
2140cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			continue;
2150cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		}
2160cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri
2170cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		if (separator == '\0') {
2180cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			printf("%s=%s%c", key, value, separator);
2190cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			continue;
2200cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		}
2210cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri
2220cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		keylen = strlen(key);
2230cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		printf("%s:%-*s%s%c", key, 15 - keylen, "", value, separator);
2240cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	}
2250cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri
2260cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	if (field != NULL)
2270cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		goto end;
2280cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri
2290cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	while (params != NULL) {
2300cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		struct param *p = params;
2310cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		params = p->next;
2320cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri
2330cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		if (p->param == NULL)
2340cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			printf("%-16s%.*s:%.*s%c", "parm:",
2350cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			       p->namelen, p->name, p->typelen, p->type,
2360cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			       separator);
2370cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		else if (p->type != NULL)
238515ec7960bf22c52e9e5d27c23a5dadad785a9daGustavo Sverzut Barbieri			printf("%-16s%.*s:%.*s (%.*s)%c", "parm:",
2390cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			       p->namelen, p->name,
2400cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			       p->paramlen, p->param,
2410cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			       p->typelen, p->type,
2420cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			       separator);
2430cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		else
244515ec7960bf22c52e9e5d27c23a5dadad785a9daGustavo Sverzut Barbieri			printf("%-16s%.*s:%.*s%c",
2450cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			       "parm:",
2460cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			       p->namelen, p->name,
2470cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			       p->paramlen, p->param,
2480cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			       separator);
2490cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri
2500cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		free(p);
2510cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	}
2520cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri
2530cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieriend:
2540cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	while (params != NULL) {
2550cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		void *tmp = params;
2560cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		params = params->next;
2570cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		free(tmp);
2580cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	}
2590cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	kmod_module_info_free_list(list);
2600cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri
2610cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	return err;
2620cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri}
2630cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri
2640cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieristatic int modinfo_path_do(struct kmod_ctx *ctx, const char *path)
2650cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri{
2660cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	struct kmod_module *mod;
2670cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	int err = kmod_module_new_from_path(ctx, path, &mod);
2680cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	if (err < 0) {
2699382dbf7aa8e65b3e080f154b7b986da0e1fbfceLucas De Marchi		ERR("Module file %s not found.\n", path);
2700cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		return err;
2710cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	}
2720cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	err = modinfo_do(mod);
2730cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	kmod_module_unref(mod);
2740cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	return err;
2750cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri}
2760cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri
2770cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieristatic int modinfo_alias_do(struct kmod_ctx *ctx, const char *alias)
2780cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri{
2793e4c6af6ad41182ab3efc5ebe796005648ba4733Dave Reisner	struct kmod_list *l, *filtered, *list = NULL;
2800cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	int err = kmod_module_new_from_lookup(ctx, alias, &list);
2810cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	if (err < 0) {
2829382dbf7aa8e65b3e080f154b7b986da0e1fbfceLucas De Marchi		ERR("Module alias %s not found.\n", alias);
2830cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		return err;
2840cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	}
2855f85a133f8e4c2c97f90062e4055dbe2efd76325Dave Reisner
2865f85a133f8e4c2c97f90062e4055dbe2efd76325Dave Reisner	if (list == NULL) {
2879382dbf7aa8e65b3e080f154b7b986da0e1fbfceLucas De Marchi		ERR("Module %s not found.\n", alias);
2885f85a133f8e4c2c97f90062e4055dbe2efd76325Dave Reisner		return -ENOENT;
2895f85a133f8e4c2c97f90062e4055dbe2efd76325Dave Reisner	}
2905f85a133f8e4c2c97f90062e4055dbe2efd76325Dave Reisner
2913e4c6af6ad41182ab3efc5ebe796005648ba4733Dave Reisner	err = kmod_module_apply_filter(ctx, KMOD_FILTER_BUILTIN, list, &filtered);
2923e4c6af6ad41182ab3efc5ebe796005648ba4733Dave Reisner	kmod_module_unref_list(list);
2933e4c6af6ad41182ab3efc5ebe796005648ba4733Dave Reisner	if (err < 0) {
2949382dbf7aa8e65b3e080f154b7b986da0e1fbfceLucas De Marchi		ERR("Failed to filter list: %m\n");
2953e4c6af6ad41182ab3efc5ebe796005648ba4733Dave Reisner		return err;
2963e4c6af6ad41182ab3efc5ebe796005648ba4733Dave Reisner	}
2973e4c6af6ad41182ab3efc5ebe796005648ba4733Dave Reisner
2983e4c6af6ad41182ab3efc5ebe796005648ba4733Dave Reisner	if (filtered == NULL) {
2999382dbf7aa8e65b3e080f154b7b986da0e1fbfceLucas De Marchi		ERR("Module %s not found.\n", alias);
3003e4c6af6ad41182ab3efc5ebe796005648ba4733Dave Reisner		return -ENOENT;
3013e4c6af6ad41182ab3efc5ebe796005648ba4733Dave Reisner	}
3023e4c6af6ad41182ab3efc5ebe796005648ba4733Dave Reisner
3033e4c6af6ad41182ab3efc5ebe796005648ba4733Dave Reisner	kmod_list_foreach(l, filtered) {
3040cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		struct kmod_module *mod = kmod_module_get_module(l);
3050cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		int r = modinfo_do(mod);
3060cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		kmod_module_unref(mod);
3070cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		if (r < 0)
3080cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			err = r;
3090cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	}
3103e4c6af6ad41182ab3efc5ebe796005648ba4733Dave Reisner	kmod_module_unref_list(filtered);
3110cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	return err;
3120cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri}
3130cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri
314022e1f0e0dae85772fc56604d3c009c23391bc10Gustavo Sverzut Barbieristatic const char cmdopts_s[] = "adlpn0F:k:b:Vh";
3150cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieristatic const struct option cmdopts[] = {
3160cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	{"author", no_argument, 0, 'a'},
3170cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	{"description", no_argument, 0, 'd'},
3180cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	{"license", no_argument, 0, 'l'},
3190cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	{"parameters", no_argument, 0, 'p'},
3200cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	{"filename", no_argument, 0, 'n'},
3210cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	{"null", no_argument, 0, '0'},
3220cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	{"field", required_argument, 0, 'F'},
3230cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	{"set-version", required_argument, 0, 'k'},
3240cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	{"basedir", required_argument, 0, 'b'},
3250cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	{"version", no_argument, 0, 'V'},
3260cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	{"help", no_argument, 0, 'h'},
3270cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	{NULL, 0, 0, 0}
3280cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri};
3290cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri
3304a2e20dfb3f94b0c5f0b8269b0dd84974a5dac56Lucas De Marchistatic void help(void)
3310cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri{
33234e06bfb545f7a4cce6773b96b602db8329d4009Lucas De Marchi	printf("Usage:\n"
3330cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		"\t%s [options] filename [args]\n"
3340cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		"Options:\n"
3350cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		"\t-a, --author                Print only 'author'\n"
3360cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		"\t-d, --description           Print only 'description'\n"
3370cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		"\t-l, --license               Print only 'license'\n"
3380cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		"\t-p, --parameters            Print only 'parm'\n"
3390cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		"\t-n, --filename              Print only 'filename'\n"
3400cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		"\t-0, --null                  Use \\0 instead of \\n\n"
3410cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		"\t-F, --field=FIELD           Print only provided FIELD\n"
3420cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		"\t-k, --set-version=VERSION   Use VERSION instead of `uname -r`\n"
343c5b37dba8956dd8f82c54b9f97dc5dca07940db5Dave Reisner		"\t-b, --basedir=DIR           Use DIR as filesystem root for /lib/modules\n"
3440cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		"\t-V, --version               Show version\n"
3450cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		"\t-h, --help                  Show this help\n",
3467c04aeee40e9cced2656e286b2dc4bfbe8008a9fLucas De Marchi		program_invocation_short_name);
3470cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri}
3480cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri
349a23f0c9c55f46635cb58e5269b19b9e4471b5150Dan McGeestatic bool is_module_filename(const char *name)
350a23f0c9c55f46635cb58e5269b19b9e4471b5150Dan McGee{
351a23f0c9c55f46635cb58e5269b19b9e4471b5150Dan McGee	struct stat st;
352a23f0c9c55f46635cb58e5269b19b9e4471b5150Dan McGee
353a23f0c9c55f46635cb58e5269b19b9e4471b5150Dan McGee	if (stat(name, &st) == 0 && S_ISREG(st.st_mode) &&
3546f02b6fa7ac435017b8f63dc9a1c8ce62bba008bAleksey Makarov		path_ends_with_kmod_ext(name, strlen(name)))
355a23f0c9c55f46635cb58e5269b19b9e4471b5150Dan McGee			return true;
356a23f0c9c55f46635cb58e5269b19b9e4471b5150Dan McGee
357a23f0c9c55f46635cb58e5269b19b9e4471b5150Dan McGee	return false;
358a23f0c9c55f46635cb58e5269b19b9e4471b5150Dan McGee}
359a23f0c9c55f46635cb58e5269b19b9e4471b5150Dan McGee
360769becb5dbfb673900c6813d02ae3737d87035efLucas De Marchistatic int do_modinfo(int argc, char *argv[])
3610cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri{
3620cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	struct kmod_ctx *ctx;
3630cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	char dirname_buf[PATH_MAX];
3640cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	const char *dirname = NULL;
3650cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	const char *kversion = NULL;
3660cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	const char *root = NULL;
3670cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	const char *null_config = NULL;
3680cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	int i, err;
3690cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri
3700cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	for (;;) {
3710cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		int c, idx = 0;
3720cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		c = getopt_long(argc, argv, cmdopts_s, cmdopts, &idx);
3730cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		if (c == -1)
3740cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			break;
3750cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		switch (c) {
3760cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		case 'a':
3770cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			field = "author";
3780cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			break;
3790cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		case 'd':
3800cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			field = "description";
3810cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			break;
3820cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		case 'l':
3830cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			field = "license";
3840cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			break;
3850cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		case 'p':
3860cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			field = "parm";
3870cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			break;
3880cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		case 'n':
3890cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			field = "filename";
3900cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			break;
3910cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		case '0':
3920cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			separator = '\0';
3930cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			break;
3940cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		case 'F':
3950cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			field = optarg;
3960cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			break;
3970cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		case 'k':
3980cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			kversion = optarg;
3990cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			break;
4000cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		case 'b':
4010cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			root = optarg;
4020cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			break;
4030cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		case 'h':
4044a2e20dfb3f94b0c5f0b8269b0dd84974a5dac56Lucas De Marchi			help();
4050cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			return EXIT_SUCCESS;
4060cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		case 'V':
4070cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			puts(PACKAGE " version " VERSION);
408655de2751dec5594807cb0a613e80fb48b06bc59Lucas De Marchi			puts(KMOD_FEATURES);
4090cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			return EXIT_SUCCESS;
4100cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		case '?':
4110cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			return EXIT_FAILURE;
4120cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		default:
4139382dbf7aa8e65b3e080f154b7b986da0e1fbfceLucas De Marchi			ERR("unexpected getopt_long() value '%c'.\n", c);
4140cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			return EXIT_FAILURE;
4150cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		}
4160cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	}
4170cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri
4180cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	if (optind >= argc) {
4199382dbf7aa8e65b3e080f154b7b986da0e1fbfceLucas De Marchi		ERR("missing module or filename.\n");
4200cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		return EXIT_FAILURE;
4210cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	}
4220cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri
4230cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	if (root != NULL || kversion != NULL) {
4240cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		struct utsname u;
4250cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		if (root == NULL)
4260cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			root = "";
4270cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		if (kversion == NULL) {
4280cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			if (uname(&u) < 0) {
4299382dbf7aa8e65b3e080f154b7b986da0e1fbfceLucas De Marchi				ERR("uname() failed: %m\n");
4300cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri				return EXIT_FAILURE;
4310cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			}
4320cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			kversion = u.release;
4330cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		}
434c5b37dba8956dd8f82c54b9f97dc5dca07940db5Dave Reisner		snprintf(dirname_buf, sizeof(dirname_buf), "%s/lib/modules/%s",
4350cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			 root, kversion);
4360cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		dirname = dirname_buf;
4370cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	}
4380cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri
4390cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	ctx = kmod_new(dirname, &null_config);
4400cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	if (!ctx) {
4419382dbf7aa8e65b3e080f154b7b986da0e1fbfceLucas De Marchi		ERR("kmod_new() failed!\n");
4420cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		return EXIT_FAILURE;
4430cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	}
4440cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri
4450cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	err = 0;
4460cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	for (i = optind; i < argc; i++) {
4470cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		const char *name = argv[i];
4480cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		int r;
4490cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri
450a23f0c9c55f46635cb58e5269b19b9e4471b5150Dan McGee		if (is_module_filename(name))
4510cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			r = modinfo_path_do(ctx, name);
4520cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		else
4530cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			r = modinfo_alias_do(ctx, name);
4540cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri
4550cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri		if (r < 0)
4560cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri			err = r;
4570cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	}
4580cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri
4590cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	kmod_unref(ctx);
4600cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri	return err >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
4610cc3ccfd5233e03506b41022e4a31a37e8a208acGustavo Sverzut Barbieri}
462769becb5dbfb673900c6813d02ae3737d87035efLucas De Marchi
463769becb5dbfb673900c6813d02ae3737d87035efLucas De Marchiconst struct kmod_cmd kmod_cmd_compat_modinfo = {
464769becb5dbfb673900c6813d02ae3737d87035efLucas De Marchi	.name = "modinfo",
465769becb5dbfb673900c6813d02ae3737d87035efLucas De Marchi	.cmd = do_modinfo,
466769becb5dbfb673900c6813d02ae3737d87035efLucas De Marchi	.help = "compat modinfo command",
467769becb5dbfb673900c6813d02ae3737d87035efLucas De Marchi};
468