~registry/kmod/master

« back to all changes in this revision

Viewing changes to tools/kmod-rmmod.c

  • Committer: Lucas De Marchi
  • Date: 2011-12-12 12:30:01 UTC
  • mfrom: (161.1.30)
  • Revision ID: git-v1:2fee2f13ce5f6b17dd672389de422217c56105e2
Merge branch 'use-mmap'

Conflicts:
        libkmod/libkmod.c

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * kmod-rmmod - remove modules from linux kernel using libkmod.
 
3
 *
 
4
 * Copyright (C) 2011  ProFUSION embedded systems
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or
 
7
 * modify it under the terms of the GNU Lesser General Public
 
8
 * License as published by the Free Software Foundation version 2.1.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
 * Lesser General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU Lesser General Public
 
16
 * License along with this program; if not, write to the Free Software
 
17
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
18
 */
 
19
#include <stdio.h>
 
20
#include <stdlib.h>
 
21
#include <getopt.h>
 
22
#include <errno.h>
 
23
#include <string.h>
 
24
#include <sys/types.h>
 
25
#include <sys/stat.h>
 
26
#include <unistd.h>
 
27
#include <syslog.h>
 
28
#include "libkmod.h"
 
29
 
 
30
 
 
31
static const char cmdopts_s[] = "fsvVwh";
 
32
static const struct option cmdopts[] = {
 
33
        {"force", no_argument, 0, 'f'},
 
34
        {"syslog", no_argument, 0, 's'},
 
35
        {"verbose", no_argument, 0, 'v'},
 
36
        {"version", no_argument, 0, 'V'},
 
37
        {"wait", no_argument, 0, 'w'},
 
38
        {"help", no_argument, 0, 'h'},
 
39
        {NULL, 0, 0, 0}
 
40
};
 
41
 
 
42
static void help(const char *progname)
 
43
{
 
44
        fprintf(stderr,
 
45
                "Usage:\n"
 
46
                "\t%s [options] modulename ...\n"
 
47
                "Options:\n"
 
48
                "\t-f, --force       forces a module unload and may crash your\n"
 
49
                "\t                  machine. This requires Forced Module Removal\n"
 
50
                "\t                  option in your kernel. DANGEROUS\n"
 
51
                "\t-s, --syslog      print to syslog, not stderr\n"
 
52
                "\t-v, --verbose     enables more messages\n"
 
53
                "\t-V, --version     show version\n"
 
54
                "\t-w, --wait        begins module removal even if it is used and\n"
 
55
                "\t                  will stop new users from accessing it.\n"
 
56
                "\t-h, --help        show this help\n",
 
57
                progname);
 
58
}
 
59
 
 
60
static void log_syslog(void *data, int priority, const char *file, int line,
 
61
                                const char *fn, const char *format,
 
62
                                va_list args)
 
63
{
 
64
        char *str, buf[32];
 
65
        const char *prioname;
 
66
 
 
67
        switch (priority) {
 
68
        case LOG_CRIT:
 
69
                prioname = "FATAL";
 
70
                break;
 
71
        case LOG_ERR:
 
72
                prioname = "ERROR";
 
73
                break;
 
74
        case LOG_WARNING:
 
75
                prioname = "WARNING";
 
76
                break;
 
77
        case LOG_NOTICE:
 
78
                prioname = "NOTICE";
 
79
                break;
 
80
        case LOG_INFO:
 
81
                prioname = "INFO";
 
82
                break;
 
83
        case LOG_DEBUG:
 
84
                prioname = "DEBUG";
 
85
                break;
 
86
        default:
 
87
                snprintf(buf, sizeof(buf), "LOG-%03d", priority);
 
88
                prioname = buf;
 
89
        }
 
90
 
 
91
        if (vasprintf(&str, format, args) < 0)
 
92
                return;
 
93
#ifdef ENABLE_DEBUG
 
94
        syslog(LOG_NOTICE, "%s: %s:%d %s() %s", prioname, file, line, fn, str);
 
95
#else
 
96
        syslog(LOG_NOTICE, "%s: %s", prioname, str);
 
97
#endif
 
98
        free(str);
 
99
        (void)data;
 
100
}
 
101
 
 
102
int main(int argc, char *argv[])
 
103
{
 
104
        struct kmod_ctx *ctx;
 
105
        int flags = KMOD_REMOVE_NOWAIT;
 
106
        int use_syslog = 0;
 
107
        int verbose = 0;
 
108
        int i, err;
 
109
 
 
110
        for (;;) {
 
111
                int c, idx = 0;
 
112
                c = getopt_long(argc, argv, cmdopts_s, cmdopts, &idx);
 
113
                if (c == -1)
 
114
                        break;
 
115
                switch (c) {
 
116
                case 'f':
 
117
                        flags |= KMOD_REMOVE_FORCE;
 
118
                        break;
 
119
                case 's':
 
120
                        use_syslog = 1;
 
121
                        break;
 
122
                case 'v':
 
123
                        verbose++;
 
124
                        break;
 
125
                case 'w':
 
126
                        flags &= ~KMOD_REMOVE_NOWAIT;
 
127
                        break;
 
128
                case 'h':
 
129
                        help(argv[0]);
 
130
                        return EXIT_SUCCESS;
 
131
                case 'V':
 
132
                        puts(PACKAGE " version " VERSION);
 
133
                        return EXIT_SUCCESS;
 
134
                case '?':
 
135
                        return EXIT_FAILURE;
 
136
                default:
 
137
                        fprintf(stderr,
 
138
                                "Error: unexpected getopt_long() value '%c'.\n",
 
139
                                c);
 
140
                        return EXIT_FAILURE;
 
141
                }
 
142
        }
 
143
 
 
144
        if (optind >= argc) {
 
145
                fprintf(stderr, "Error: missing module name.\n");
 
146
                return EXIT_FAILURE;
 
147
        }
 
148
 
 
149
        ctx = kmod_new(NULL, NULL);
 
150
        if (!ctx) {
 
151
                fputs("Error: kmod_new() failed!\n", stderr);
 
152
                return EXIT_FAILURE;
 
153
        }
 
154
 
 
155
        kmod_set_log_priority(ctx, kmod_get_log_priority(ctx) + verbose);
 
156
        if (use_syslog) {
 
157
                openlog("rmmod", LOG_CONS, LOG_DAEMON);
 
158
                kmod_set_log_fn(ctx, log_syslog, NULL);
 
159
        }
 
160
 
 
161
        for (i = optind; i < argc; i++) {
 
162
                struct kmod_module *mod;
 
163
                const char *arg = argv[i];
 
164
                struct stat st;
 
165
                if (stat(arg, &st) == 0)
 
166
                        err = kmod_module_new_from_path(ctx, arg, &mod);
 
167
                else
 
168
                        err = kmod_module_new_from_name(ctx, arg, &mod);
 
169
 
 
170
                if (err < 0) {
 
171
                        fprintf(stderr, "Error: could not use module %s: %s\n",
 
172
                                arg, strerror(-err));
 
173
                        break;
 
174
                }
 
175
 
 
176
                err = kmod_module_remove_module(mod, flags);
 
177
                if (err < 0) {
 
178
                        fprintf(stderr,
 
179
                                "Error: could not remove module %s: %s\n",
 
180
                                arg, strerror(-err));
 
181
                }
 
182
                kmod_module_unref(mod);
 
183
                if (err < 0)
 
184
                        break;
 
185
        }
 
186
 
 
187
        kmod_unref(ctx);
 
188
 
 
189
        if (use_syslog)
 
190
                closelog();
 
191
 
 
192
        return err >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
 
193
}