Denis Vlasenko | 9299305 | 2008-10-15 09:44:37 +0000 | [diff] [blame^] | 1 | /* vi: set sw=4 ts=4: */ |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 2 | /* |
| 3 | * Sysctl 1.01 - A utility to read and manipulate the sysctl parameters |
| 4 | * |
Rob Landley | 8b1f11d | 2006-04-17 21:49:34 +0000 | [diff] [blame] | 5 | * Copyright 1999 George Staikos |
Bernhard Reutner-Fischer | cb44816 | 2006-04-12 07:35:12 +0000 | [diff] [blame] | 6 | * |
| 7 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 8 | * |
| 9 | * Changelog: |
| 10 | * v1.01: |
| 11 | * - added -p <preload> to preload values from a file |
| 12 | * v1.01.1 |
| 13 | * - busybox applet aware by <solar@gentoo.org> |
Eric Andersen | c7bda1c | 2004-03-15 08:29:22 +0000 | [diff] [blame] | 14 | * |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 15 | */ |
| 16 | |
Denis Vlasenko | b6adbf1 | 2007-05-26 19:00:18 +0000 | [diff] [blame] | 17 | #include "libbb.h" |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 18 | |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 19 | static int sysctl_read_setting(const char *setting); |
| 20 | static int sysctl_write_setting(const char *setting); |
| 21 | static int sysctl_display_all(const char *path); |
| 22 | static int sysctl_preload_file_and_exit(const char *filename); |
Denis Vlasenko | 58cc52a | 2008-10-15 08:22:55 +0000 | [diff] [blame] | 23 | static void sysctl_dots_to_slashes(char *name); |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 24 | |
Denis Vlasenko | 5a28a25 | 2007-10-29 19:22:13 +0000 | [diff] [blame] | 25 | static const char ETC_SYSCTL_CONF[] ALIGN1 = "/etc/sysctl.conf"; |
| 26 | static const char PROC_SYS[] ALIGN1 = "/proc/sys/"; |
| 27 | enum { strlen_PROC_SYS = sizeof(PROC_SYS) - 1 }; |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 28 | |
Denis Vlasenko | cfdb711 | 2008-10-15 08:29:17 +0000 | [diff] [blame] | 29 | static const char msg_unknown_key[] ALIGN1 = |
Denis Vlasenko | 5a28a25 | 2007-10-29 19:22:13 +0000 | [diff] [blame] | 30 | "error: '%s' is an unknown key"; |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 31 | |
Glenn L McGrath | ab82154 | 2003-12-26 02:19:34 +0000 | [diff] [blame] | 32 | static void dwrite_str(int fd, const char *buf) |
| 33 | { |
| 34 | write(fd, buf, strlen(buf)); |
| 35 | } |
| 36 | |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 37 | enum { |
| 38 | FLAG_SHOW_KEYS = 1 << 0, |
| 39 | FLAG_SHOW_KEY_ERRORS = 1 << 1, |
| 40 | FLAG_TABLE_FORMAT = 1 << 2, /* not implemented */ |
| 41 | FLAG_SHOW_ALL = 1 << 3, |
| 42 | FLAG_PRELOAD_FILE = 1 << 4, |
| 43 | FLAG_WRITE = 1 << 5, |
| 44 | }; |
| 45 | |
Denis Vlasenko | 9b49a5e | 2007-10-11 10:05:36 +0000 | [diff] [blame] | 46 | int sysctl_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
Denis Vlasenko | a60f84e | 2008-07-05 09:18:54 +0000 | [diff] [blame] | 47 | int sysctl_main(int argc UNUSED_PARAM, char **argv) |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 48 | { |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 49 | int retval; |
| 50 | int opt; |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 51 | |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 52 | opt = getopt32(argv, "+neAapw"); /* '+' - stop on first non-option */ |
| 53 | argv += optind; |
| 54 | opt ^= (FLAG_SHOW_KEYS | FLAG_SHOW_KEY_ERRORS); |
| 55 | option_mask32 ^= (FLAG_SHOW_KEYS | FLAG_SHOW_KEY_ERRORS); |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 56 | |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 57 | if (opt & (FLAG_TABLE_FORMAT | FLAG_SHOW_ALL)) |
| 58 | return sysctl_display_all(PROC_SYS); |
| 59 | if (opt & FLAG_PRELOAD_FILE) |
| 60 | return sysctl_preload_file_and_exit(*argv ? *argv : ETC_SYSCTL_CONF); |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 61 | |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 62 | retval = 0; |
| 63 | while (*argv) { |
| 64 | if (opt & FLAG_WRITE) |
| 65 | retval |= sysctl_write_setting(*argv); |
| 66 | else |
| 67 | retval |= sysctl_read_setting(*argv); |
| 68 | argv++; |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 69 | } |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 70 | |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 71 | return retval; |
Denis Vlasenko | 5a28a25 | 2007-10-29 19:22:13 +0000 | [diff] [blame] | 72 | } /* end sysctl_main() */ |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 73 | |
Denis Vlasenko | 81944c9 | 2008-10-15 08:45:54 +0000 | [diff] [blame] | 74 | /* Set sysctl's from a conf file. Format example: |
| 75 | * # Controls IP packet forwarding |
| 76 | * net.ipv4.ip_forward = 0 |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 77 | */ |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 78 | static int sysctl_preload_file_and_exit(const char *filename) |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 79 | { |
Denis Vlasenko | 4a717e0 | 2008-07-20 13:01:56 +0000 | [diff] [blame] | 80 | char *token[2]; |
| 81 | parser_t *parser; |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 82 | |
Denis Vlasenko | 4a717e0 | 2008-07-20 13:01:56 +0000 | [diff] [blame] | 83 | parser = config_open(filename); |
Denis Vlasenko | 81944c9 | 2008-10-15 08:45:54 +0000 | [diff] [blame] | 84 | // TODO: ';' is comment char too |
| 85 | while (config_read(parser, token, 2, 2, "# \t=", PARSE_NORMAL)) { |
Denis Vlasenko | 4a717e0 | 2008-07-20 13:01:56 +0000 | [diff] [blame] | 86 | #if 0 |
Denis Vlasenko | 81944c9 | 2008-10-15 08:45:54 +0000 | [diff] [blame] | 87 | char *s = xasprintf("%s=%s", token[0], token[1]); |
| 88 | sysctl_write_setting(s); |
| 89 | free(s); |
| 90 | #else /* Save ~4 bytes by using parser internals */ |
| 91 | sprintf(parser->line, "%s=%s", token[0], token[1]); // must have room by definition |
| 92 | sysctl_write_setting(parser->line); |
Denis Vlasenko | 4a717e0 | 2008-07-20 13:01:56 +0000 | [diff] [blame] | 93 | #endif |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 94 | } |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 95 | if (ENABLE_FEATURE_CLEAN_UP) |
Denis Vlasenko | 4a717e0 | 2008-07-20 13:01:56 +0000 | [diff] [blame] | 96 | config_close(parser); |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 97 | return 0; |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 98 | } /* end sysctl_preload_file_and_exit() */ |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 99 | |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 100 | static int sysctl_write_setting(const char *setting) |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 101 | { |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 102 | int retval; |
Denis Vlasenko | 5a28a25 | 2007-10-29 19:22:13 +0000 | [diff] [blame] | 103 | const char *name; |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 104 | const char *value; |
| 105 | const char *equals; |
| 106 | char *tmpname, *outname, *cptr; |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 107 | int fd; |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 108 | |
Denis Vlasenko | 5a28a25 | 2007-10-29 19:22:13 +0000 | [diff] [blame] | 109 | name = setting; |
| 110 | equals = strchr(setting, '='); |
| 111 | if (!equals) { |
Denis Vlasenko | cfdb711 | 2008-10-15 08:29:17 +0000 | [diff] [blame] | 112 | bb_error_msg("error: '%s' must be of the form name=value", setting); |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 113 | return EXIT_FAILURE; |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 114 | } |
| 115 | |
Denis Vlasenko | 5a28a25 | 2007-10-29 19:22:13 +0000 | [diff] [blame] | 116 | value = equals + 1; /* point to the value in name=value */ |
| 117 | if (name == equals || !*value) { |
Denis Vlasenko | cfdb711 | 2008-10-15 08:29:17 +0000 | [diff] [blame] | 118 | bb_error_msg("error: malformed setting '%s'", setting); |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 119 | return EXIT_FAILURE; |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 120 | } |
| 121 | |
Denis Vlasenko | 5a28a25 | 2007-10-29 19:22:13 +0000 | [diff] [blame] | 122 | tmpname = xasprintf("%s%.*s", PROC_SYS, (int)(equals - name), name); |
| 123 | outname = xstrdup(tmpname + strlen_PROC_SYS); |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 124 | |
Denis Vlasenko | 58cc52a | 2008-10-15 08:22:55 +0000 | [diff] [blame] | 125 | sysctl_dots_to_slashes(tmpname); |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 126 | |
| 127 | while ((cptr = strchr(outname, '/')) != NULL) |
| 128 | *cptr = '.'; |
| 129 | |
Denis Vlasenko | 50f7f44 | 2007-04-11 23:20:53 +0000 | [diff] [blame] | 130 | fd = open(tmpname, O_WRONLY | O_CREAT | O_TRUNC, 0666); |
| 131 | if (fd < 0) { |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 132 | switch (errno) { |
| 133 | case ENOENT: |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 134 | if (option_mask32 & FLAG_SHOW_KEY_ERRORS) |
Denis Vlasenko | cfdb711 | 2008-10-15 08:29:17 +0000 | [diff] [blame] | 135 | bb_error_msg(msg_unknown_key, outname); |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 136 | break; |
| 137 | default: |
Denis Vlasenko | cfdb711 | 2008-10-15 08:29:17 +0000 | [diff] [blame] | 138 | bb_perror_msg("error setting key '%s'", outname); |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 139 | break; |
| 140 | } |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 141 | retval = EXIT_FAILURE; |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 142 | } else { |
Glenn L McGrath | ab82154 | 2003-12-26 02:19:34 +0000 | [diff] [blame] | 143 | dwrite_str(fd, value); |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 144 | close(fd); |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 145 | if (option_mask32 & FLAG_SHOW_KEYS) { |
| 146 | printf("%s = ", outname); |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 147 | } |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 148 | puts(value); |
| 149 | retval = EXIT_SUCCESS; |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 150 | } |
| 151 | |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 152 | free(tmpname); |
| 153 | free(outname); |
| 154 | return retval; |
Denis Vlasenko | 5a28a25 | 2007-10-29 19:22:13 +0000 | [diff] [blame] | 155 | } /* end sysctl_write_setting() */ |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 156 | |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 157 | static int sysctl_read_setting(const char *name) |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 158 | { |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 159 | int retval; |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 160 | char *tmpname, *outname, *cptr; |
| 161 | char inbuf[1025]; |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 162 | FILE *fp; |
| 163 | |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 164 | if (!*name) { |
| 165 | if (option_mask32 & FLAG_SHOW_KEY_ERRORS) |
Denis Vlasenko | cfdb711 | 2008-10-15 08:29:17 +0000 | [diff] [blame] | 166 | bb_error_msg(msg_unknown_key, name); |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 167 | return -1; |
| 168 | } |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 169 | |
Denis Vlasenko | 5a28a25 | 2007-10-29 19:22:13 +0000 | [diff] [blame] | 170 | tmpname = concat_path_file(PROC_SYS, name); |
| 171 | outname = xstrdup(tmpname + strlen_PROC_SYS); |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 172 | |
Denis Vlasenko | 58cc52a | 2008-10-15 08:22:55 +0000 | [diff] [blame] | 173 | sysctl_dots_to_slashes(tmpname); |
| 174 | |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 175 | while ((cptr = strchr(outname, '/')) != NULL) |
| 176 | *cptr = '.'; |
| 177 | |
Denis Vlasenko | 5415c85 | 2008-07-21 23:05:26 +0000 | [diff] [blame] | 178 | fp = fopen_for_read(tmpname); |
Denis Vlasenko | 5a28a25 | 2007-10-29 19:22:13 +0000 | [diff] [blame] | 179 | if (fp == NULL) { |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 180 | switch (errno) { |
| 181 | case ENOENT: |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 182 | if (option_mask32 & FLAG_SHOW_KEY_ERRORS) |
Denis Vlasenko | cfdb711 | 2008-10-15 08:29:17 +0000 | [diff] [blame] | 183 | bb_error_msg(msg_unknown_key, outname); |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 184 | break; |
| 185 | default: |
Denis Vlasenko | cfdb711 | 2008-10-15 08:29:17 +0000 | [diff] [blame] | 186 | bb_perror_msg("error reading key '%s'", outname); |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 187 | break; |
| 188 | } |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 189 | retval = EXIT_FAILURE; |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 190 | } else { |
| 191 | while (fgets(inbuf, sizeof(inbuf) - 1, fp)) { |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 192 | if (option_mask32 & FLAG_SHOW_KEYS) { |
| 193 | printf("%s = ", outname); |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 194 | } |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 195 | fputs(inbuf, stdout); |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 196 | } |
| 197 | fclose(fp); |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 198 | retval = EXIT_SUCCESS; |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 199 | } |
| 200 | |
| 201 | free(tmpname); |
| 202 | free(outname); |
| 203 | return retval; |
Denis Vlasenko | 5a28a25 | 2007-10-29 19:22:13 +0000 | [diff] [blame] | 204 | } /* end sysctl_read_setting() */ |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 205 | |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 206 | static int sysctl_display_all(const char *path) |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 207 | { |
Denis Vlasenko | 81944c9 | 2008-10-15 08:45:54 +0000 | [diff] [blame] | 208 | int retval = EXIT_SUCCESS; |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 209 | DIR *dp; |
| 210 | struct dirent *de; |
| 211 | char *tmpdir; |
| 212 | struct stat ts; |
| 213 | |
Denis Vlasenko | 51742f4 | 2007-04-12 00:32:05 +0000 | [diff] [blame] | 214 | dp = opendir(path); |
| 215 | if (!dp) { |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 216 | return EXIT_FAILURE; |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 217 | } |
Denis Vlasenko | 5a28a25 | 2007-10-29 19:22:13 +0000 | [diff] [blame] | 218 | while ((de = readdir(dp)) != NULL) { |
| 219 | tmpdir = concat_subpath_file(path, de->d_name); |
| 220 | if (tmpdir == NULL) |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 221 | continue; /* . or .. */ |
Denis Vlasenko | 5a28a25 | 2007-10-29 19:22:13 +0000 | [diff] [blame] | 222 | if (stat(tmpdir, &ts) != 0) { |
| 223 | bb_perror_msg(tmpdir); |
| 224 | } else if (S_ISDIR(ts.st_mode)) { |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 225 | retval |= sysctl_display_all(tmpdir); |
Denis Vlasenko | 5a28a25 | 2007-10-29 19:22:13 +0000 | [diff] [blame] | 226 | } else { |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 227 | retval |= sysctl_read_setting(tmpdir + strlen_PROC_SYS); |
Denis Vlasenko | 5a28a25 | 2007-10-29 19:22:13 +0000 | [diff] [blame] | 228 | } |
| 229 | free(tmpdir); |
| 230 | } /* end while */ |
| 231 | closedir(dp); |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 232 | |
| 233 | return retval; |
Denis Vlasenko | 5a28a25 | 2007-10-29 19:22:13 +0000 | [diff] [blame] | 234 | } /* end sysctl_display_all() */ |
Denis Vlasenko | 58cc52a | 2008-10-15 08:22:55 +0000 | [diff] [blame] | 235 | |
| 236 | static void sysctl_dots_to_slashes(char *name) |
| 237 | { |
Denis Vlasenko | e915a1a | 2008-10-15 09:43:35 +0000 | [diff] [blame] | 238 | char *cptr, *last_good; |
| 239 | char *end = name + strlen(name) - 1; |
Denis Vlasenko | 58cc52a | 2008-10-15 08:22:55 +0000 | [diff] [blame] | 240 | |
| 241 | /* Example from bug 3894: |
| 242 | * net.ipv4.conf.eth0.100.mc_forwarding -> |
Denis Vlasenko | e915a1a | 2008-10-15 09:43:35 +0000 | [diff] [blame] | 243 | * net/ipv4/conf/eth0.100/mc_forwarding. NB: |
| 244 | * net/ipv4/conf/eth0/mc_forwarding *also exists*, |
| 245 | * therefore we must start from the end, and if |
| 246 | * we replaced even one . -> /, start over again, |
| 247 | * but never replace dots before the position |
| 248 | * where replacement occurred. */ |
| 249 | last_good = name - 1; |
| 250 | again: |
| 251 | cptr = end; |
| 252 | while (cptr > last_good) { |
Denis Vlasenko | 58cc52a | 2008-10-15 08:22:55 +0000 | [diff] [blame] | 253 | if (*cptr == '.') { |
| 254 | *cptr = '\0'; |
Denis Vlasenko | e915a1a | 2008-10-15 09:43:35 +0000 | [diff] [blame] | 255 | if (access(name, F_OK) == 0) { |
Denis Vlasenko | 58cc52a | 2008-10-15 08:22:55 +0000 | [diff] [blame] | 256 | *cptr = '/'; |
Denis Vlasenko | e915a1a | 2008-10-15 09:43:35 +0000 | [diff] [blame] | 257 | last_good = cptr; |
| 258 | goto again; |
| 259 | } |
| 260 | *cptr = '.'; |
Denis Vlasenko | 58cc52a | 2008-10-15 08:22:55 +0000 | [diff] [blame] | 261 | } |
Denis Vlasenko | e915a1a | 2008-10-15 09:43:35 +0000 | [diff] [blame] | 262 | cptr--; |
Denis Vlasenko | 58cc52a | 2008-10-15 08:22:55 +0000 | [diff] [blame] | 263 | } |
| 264 | } /* end sysctl_dots_to_slashes() */ |