]> git.ipfire.org Git - thirdparty/util-linux.git/blobdiff - sys-utils/chcpu.c
misc: consolidate version printing and close_stdout()
[thirdparty/util-linux.git] / sys-utils / chcpu.c
index 523e9c566079f5ac5ba3ff5c722cf5f574020d4a..c4e5bc7e297d98152b62c4216c41035ccb12a4b1 100644 (file)
 
 #define EXCL_ERROR "--{configure,deconfigure,disable,dispatch,enable}"
 
+/* partial success, otherwise we return regular EXIT_{SUCCESS,FAILURE} */
+#define CHCPU_EXIT_SOMEOK      64
+
 #define _PATH_SYS_CPU          "/sys/devices/system/cpu"
-#define _PATH_SYS_CPU_ONLINE   _PATH_SYS_CPU "/online"
-#define _PATH_SYS_CPU_RESCAN   _PATH_SYS_CPU "/rescan"
-#define _PATH_SYS_CPU_DISPATCH _PATH_SYS_CPU "/dispatching"
 
 static cpu_set_t *onlinecpus;
 static int maxcpus;
@@ -66,135 +66,160 @@ enum {
        CMD_CPU_DISPATCH_VERTICAL,
 };
 
-static int cpu_enable(cpu_set_t *cpu_set, size_t setsize, int enable)
+/* returns:   0 = success
+ *          < 0 = failure
+ *          > 0 = partial success
+ */
+static int cpu_enable(struct path_cxt *sys, cpu_set_t *cpu_set, size_t setsize, int enable)
 {
-       unsigned int cpu;
+       int cpu;
        int online, rc;
        int configured = -1;
+       int fails = 0;
 
-       for (cpu = 0; cpu < setsize; cpu++) {
-               if (!CPU_ISSET(cpu, cpu_set))
+       for (cpu = 0; cpu < maxcpus; cpu++) {
+               if (!CPU_ISSET_S(cpu, setsize, cpu_set))
                        continue;
-               if (!path_exist(_PATH_SYS_CPU "/cpu%d", cpu)) {
-                       printf(_("CPU %d does not exist\n"), cpu);
+               if (ul_path_accessf(sys, F_OK, "cpu%d", cpu) != 0) {
+                       warnx(_("CPU %u does not exist"), cpu);
+                       fails++;
                        continue;
                }
-               if (!path_exist(_PATH_SYS_CPU "/cpu%d/online", cpu)) {
-                       printf(_("CPU %d is not hot pluggable\n"), cpu);
+               if (ul_path_accessf(sys, F_OK, "cpu%d/online", cpu) != 0) {
+                       warnx(_("CPU %u is not hot pluggable"), cpu);
+                       fails++;
                        continue;
                }
-               online = path_getnum(_PATH_SYS_CPU "/cpu%d/online", cpu);
-               if ((online == 1) && (enable == 1)) {
-                       printf(_("CPU %d is already enabled\n"), cpu);
+               if (ul_path_readf_s32(sys, &online, "cpu%d/online", cpu) == 0
+                   && online == 1
+                   && enable == 1) {
+                       printf(_("CPU %u is already enabled\n"), cpu);
                        continue;
                }
-               if ((online == 0) && (enable == 0)) {
-                       printf(_("CPU %d is already disabled\n"), cpu);
+               if (online == 0 && enable == 0) {
+                       printf(_("CPU %u is already disabled\n"), cpu);
                        continue;
                }
-               if (path_exist(_PATH_SYS_CPU "/cpu%d/configure", cpu))
-                       configured = path_getnum(_PATH_SYS_CPU "/cpu%d/configure", cpu);
+               if (ul_path_accessf(sys, F_OK, "cpu%d/configure", cpu) == 0)
+                       ul_path_readf_s32(sys, &configured, "cpu%d/configure", cpu);
                if (enable) {
-                       rc = path_writestr("1", _PATH_SYS_CPU "/cpu%d/online", cpu);
-                       if ((rc == -1) && (configured == 0))
-                               printf(_("CPU %d enable failed "
-                                        "(CPU is deconfigured)\n"), cpu);
-                       else if (rc == -1)
-                               printf(_("CPU %d enable failed (%m)\n"), cpu);
-                       else
-                               printf(_("CPU %d enabled\n"), cpu);
+                       rc = ul_path_writef_string(sys, "1", "cpu%d/online", cpu);
+                       if (rc != 0 && configured == 0) {
+                               warn(_("CPU %u enable failed (CPU is deconfigured)"), cpu);
+                               fails++;
+                       } else if (rc != 0) {
+                               warn(_("CPU %u enable failed"), cpu);
+                               fails++;
+                       } else
+                               printf(_("CPU %u enabled\n"), cpu);
                } else {
                        if (onlinecpus && num_online_cpus() == 1) {
-                               printf(_("CPU %d disable failed "
-                                        "(last enabled CPU)\n"), cpu);
+                               warnx(_("CPU %u disable failed (last enabled CPU)"), cpu);
+                               fails++;
                                continue;
                        }
-                       rc = path_writestr("0", _PATH_SYS_CPU "/cpu%d/online", cpu);
-                       if (rc == -1)
-                               printf(_("CPU %d disable failed (%m)\n"), cpu);
-                       else {
-                               printf(_("CPU %d disabled\n"), cpu);
+                       rc = ul_path_writef_string(sys, "0", "cpu%d/online", cpu);
+                       if (rc != 0) {
+                               warn(_("CPU %u disable failed"), cpu);
+                               fails++;
+                       } else {
+                               printf(_("CPU %u disabled\n"), cpu);
                                if (onlinecpus)
-                                       CPU_CLR(cpu, onlinecpus);
+                                       CPU_CLR_S(cpu, setsize, onlinecpus);
                        }
                }
        }
-       return EXIT_SUCCESS;
+
+       return fails == 0 ? 0 : fails == maxcpus ? -1 : 1;
 }
 
-static int cpu_rescan(void)
+static int cpu_rescan(struct path_cxt *sys)
 {
-       if (!path_exist(_PATH_SYS_CPU_RESCAN))
+       if (ul_path_access(sys, F_OK, "rescan") != 0)
                errx(EXIT_FAILURE, _("This system does not support rescanning of CPUs"));
-       if (path_writestr("1", _PATH_SYS_CPU_RESCAN) == -1)
+
+       if (ul_path_write_string(sys, "1", "rescan") != 0)
                err(EXIT_FAILURE, _("Failed to trigger rescan of CPUs"));
+
        printf(_("Triggered rescan of CPUs\n"));
-       return EXIT_SUCCESS;
+       return 0;
 }
 
-static int cpu_set_dispatch(int mode)
+static int cpu_set_dispatch(struct path_cxt *sys, int mode)
 {
-       if (!path_exist(_PATH_SYS_CPU_DISPATCH))
+       if (ul_path_access(sys, F_OK, "dispatching") != 0)
                errx(EXIT_FAILURE, _("This system does not support setting "
                                     "the dispatching mode of CPUs"));
        if (mode == 0) {
-               if (path_writestr("0", _PATH_SYS_CPU_DISPATCH) == -1)
+               if (ul_path_write_string(sys, "0", "dispatching") != 0)
                        err(EXIT_FAILURE, _("Failed to set horizontal dispatch mode"));
+
                printf(_("Successfully set horizontal dispatching mode\n"));
        } else {
-               if (path_writestr("1", _PATH_SYS_CPU_DISPATCH) == -1)
+               if (ul_path_write_string(sys, "1", "dispatching") != 0)
                        err(EXIT_FAILURE, _("Failed to set vertical dispatch mode"));
+
                printf(_("Successfully set vertical dispatching mode\n"));
        }
-       return EXIT_SUCCESS;
+       return 0;
 }
 
-static int cpu_configure(cpu_set_t *cpu_set, size_t setsize, int configure)
+/* returns:   0 = success
+ *          < 0 = failure
+ *          > 0 = partial success
+ */
+static int cpu_configure(struct path_cxt *sys, cpu_set_t *cpu_set, size_t setsize, int configure)
 {
-       unsigned int cpu;
+       int cpu;
        int rc, current;
+       int fails = 0;
 
-       for (cpu = 0; cpu < setsize; cpu++) {
-               if (!CPU_ISSET(cpu, cpu_set))
+       for (cpu = 0; cpu < maxcpus; cpu++) {
+               if (!CPU_ISSET_S(cpu, setsize, cpu_set))
                        continue;
-               if (!path_exist(_PATH_SYS_CPU "/cpu%d", cpu)) {
-                       printf(_("CPU %d does not exist\n"), cpu);
+               if (ul_path_accessf(sys, F_OK, "cpu%d", cpu) != 0) {
+                       warnx(_("CPU %u does not exist"), cpu);
+                       fails++;
                        continue;
                }
-               if (!path_exist(_PATH_SYS_CPU "/cpu%d/configure", cpu)) {
-                       printf(_("CPU %d is not configurable\n"), cpu);
+               if (ul_path_accessf(sys, F_OK, "cpu%d/configure", cpu) != 0) {
+                       warnx(_("CPU %u is not configurable"), cpu);
+                       fails++;
                        continue;
                }
-               current = path_getnum(_PATH_SYS_CPU "/cpu%d/configure", cpu);
-               if ((current == 1) && (configure == 1)) {
-                       printf(_("CPU %d is already configured\n"), cpu);
+               ul_path_readf_s32(sys, &current, "cpu%d/configure", cpu);
+               if (current == 1 && configure == 1) {
+                       printf(_("CPU %u is already configured\n"), cpu);
                        continue;
                }
-               if ((current == 0) && (configure == 0)) {
-                       printf(_("CPU %d is already deconfigured\n"), cpu);
+               if (current == 0 && configure == 0) {
+                       printf(_("CPU %u is already deconfigured\n"), cpu);
                        continue;
                }
-               if ((current == 1) && (configure == 0) && onlinecpus &&
+               if (current == 1 && configure == 0 && onlinecpus &&
                    is_cpu_online(cpu)) {
-                       printf(_("CPU %d deconfigure failed "
-                                "(CPU is enabled)\n"), cpu);
+                       warnx(_("CPU %u deconfigure failed (CPU is enabled)"), cpu);
+                       fails++;
                        continue;
                }
                if (configure) {
-                       rc = path_writestr("1", _PATH_SYS_CPU "/cpu%d/configure", cpu);
-                       if (rc == -1)
-                               printf(_("CPU %d configure failed (%m)\n"), cpu);
-                       else
-                               printf(_("CPU %d configured\n"), cpu);
+                       rc = ul_path_writef_string(sys, "1", "cpu%d/configure", cpu);
+                       if (rc != 0) {
+                               warn(_("CPU %u configure failed"), cpu);
+                               fails++;
+                       } else
+                               printf(_("CPU %u configured\n"), cpu);
                } else {
-                       rc = path_writestr("0", _PATH_SYS_CPU "/cpu%d/configure", cpu);
-                       if (rc == -1)
-                               printf(_("CPU %d deconfigure failed (%m)\n"), cpu);
-                       else
-                               printf(_("CPU %d deconfigured\n"), cpu);
+                       rc = ul_path_writef_string(sys, "0", "cpu%d/configure", cpu);
+                       if (rc != 0) {
+                               warn(_("CPU %u deconfigure failed"), cpu);
+                               fails++;
+                       } else
+                               printf(_("CPU %u deconfigured\n"), cpu);
                }
        }
-       return EXIT_SUCCESS;
+
+       return fails == 0 ? 0 : fails == maxcpus ? -1 : 1;
 }
 
 static void cpu_parse(char *cpu_string, cpu_set_t *cpu_set, size_t setsize)
@@ -209,95 +234,102 @@ static void cpu_parse(char *cpu_string, cpu_set_t *cpu_set, size_t setsize)
        errx(EXIT_FAILURE, _("failed to parse CPU list: %s"), cpu_string);
 }
 
-static void __attribute__((__noreturn__)) usage(FILE *out)
+static void __attribute__((__noreturn__)) usage(void)
 {
+       FILE *out = stdout;
        fprintf(out, _(
                "\nUsage:\n"
                " %s [options]\n"), program_invocation_short_name);
 
-       puts(_( "\nOptions:\n"
-               "  -h, --help                    print this help\n"
-               "  -e, --enable <cpu-list>       enable cpus\n"
-               "  -d, --disable <cpu-list>      disable cpus\n"
-               "  -c, --configure <cpu-list>    configure cpus\n"
-               "  -g, --deconfigure <cpu-list>  deconfigure cpus\n"
-               "  -p, --dispatch <mode>         set dispatching mode\n"
-               "  -r, --rescan                  trigger rescan of cpus\n"
-               "  -V, --version                 output version information and exit\n"));
-
-       exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
+       fputs(USAGE_SEPARATOR, out);
+       fputs(_("Configure CPUs in a multi-processor system.\n"), out);
+
+       fputs(USAGE_OPTIONS, stdout);
+       fputs(_(
+               " -e, --enable <cpu-list>       enable cpus\n"
+               " -d, --disable <cpu-list>      disable cpus\n"
+               " -c, --configure <cpu-list>    configure cpus\n"
+               " -g, --deconfigure <cpu-list>  deconfigure cpus\n"
+               " -p, --dispatch <mode>         set dispatching mode\n"
+               " -r, --rescan                  trigger rescan of cpus\n"
+               ), stdout);
+       printf(USAGE_HELP_OPTIONS(31));
+
+       printf(USAGE_MAN_TAIL("chcpu(8)"));
+       exit(EXIT_SUCCESS);
 }
 
 int main(int argc, char *argv[])
 {
-       cpu_set_t *cpu_set;
+       struct path_cxt *sys = NULL;    /* _PATH_SYS_CPU handler */
+       cpu_set_t *cpu_set = NULL;
        size_t setsize;
        int cmd = -1;
-       int c;
-
-       enum {
-               EXCL_NONE,
-               EXCL_CONFIGURE,
-               EXCL_DECONFIGURE,
-               EXCL_DISABLE,
-               EXCL_DISPATCH,
-               EXCL_ENABLE
-       };
-       int excl_any = EXCL_NONE;
+       int c, rc;
 
        static const struct option longopts[] = {
-               { "configure",  required_argument, 0, 'c' },
-               { "deconfigure",required_argument, 0, 'g' },
-               { "disable",    required_argument, 0, 'd' },
-               { "dispatch",   required_argument, 0, 'p' },
-               { "enable",     required_argument, 0, 'e' },
-               { "help",       no_argument,       0, 'h' },
-               { "rescan",     no_argument,       0, 'r' },
-               { "version",    no_argument,       0, 'V' },
-               { NULL,         0, 0, 0 }
+               { "configure",  required_argument, NULL, 'c' },
+               { "deconfigure",required_argument, NULL, 'g' },
+               { "disable",    required_argument, NULL, 'd' },
+               { "dispatch",   required_argument, NULL, 'p' },
+               { "enable",     required_argument, NULL, 'e' },
+               { "help",       no_argument,       NULL, 'h' },
+               { "rescan",     no_argument,       NULL, 'r' },
+               { "version",    no_argument,       NULL, 'V' },
+               { NULL,         0, NULL, 0 }
        };
 
+       static const ul_excl_t excl[] = {       /* rows and cols in ASCII order */
+               { 'c','d','e','g','p' },
+               { 0 }
+       };
+       int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT;
+
        setlocale(LC_ALL, "");
        bindtextdomain(PACKAGE, LOCALEDIR);
        textdomain(PACKAGE);
-       atexit(close_stdout);
+       close_stdout_atexit();
+
+       ul_path_init_debug();
+       sys = ul_new_path(_PATH_SYS_CPU);
+       if (!sys)
+               err(EXIT_FAILURE, _("failed to initialize sysfs handler"));
 
        maxcpus = get_max_number_of_cpus();
        if (maxcpus < 1)
                errx(EXIT_FAILURE, _("cannot determine NR_CPUS; aborting"));
-       if (path_exist(_PATH_SYS_CPU_ONLINE))
-               onlinecpus = path_cpulist(maxcpus, _PATH_SYS_CPU_ONLINE);
-       setsize = CPU_ALLOC_SIZE(maxcpus);
-       cpu_set = CPU_ALLOC(maxcpus);
+
+       if (ul_path_access(sys, F_OK, "online") == 0)
+               ul_path_readf_cpulist(sys, &cpu_set, maxcpus, "online");
+       else
+               cpu_set = CPU_ALLOC(maxcpus);
        if (!cpu_set)
                err(EXIT_FAILURE, _("cpuset_alloc failed"));
 
+       setsize = CPU_ALLOC_SIZE(maxcpus);
+
        while ((c = getopt_long(argc, argv, "c:d:e:g:hp:rV", longopts, NULL)) != -1) {
+
+               err_exclusive_options(c, longopts, excl, excl_st);
+
                switch (c) {
                case 'c':
-                       exclusive_option(&excl_any, EXCL_CONFIGURE, EXCL_ERROR);
                        cmd = CMD_CPU_CONFIGURE;
                        cpu_parse(argv[optind - 1], cpu_set, setsize);
                        break;
                case 'd':
-                       exclusive_option(&excl_any, EXCL_DISABLE, EXCL_ERROR);
                        cmd = CMD_CPU_DISABLE;
                        cpu_parse(argv[optind - 1], cpu_set, setsize);
                        break;
                case 'e':
-                       exclusive_option(&excl_any, EXCL_ENABLE, EXCL_ERROR);
                        cmd = CMD_CPU_ENABLE;
                        cpu_parse(argv[optind - 1], cpu_set, setsize);
                        break;
                case 'g':
-                       exclusive_option(&excl_any, EXCL_DECONFIGURE, EXCL_ERROR);
                        cmd = CMD_CPU_DECONFIGURE;
                        cpu_parse(argv[optind - 1], cpu_set, setsize);
                        break;
-               case 'h':
-                       usage(stdout);
                case 'p':
-                       exclusive_option(&excl_any, EXCL_DISPATCH, EXCL_ERROR);
                        if (strcmp("horizontal", argv[optind - 1]) == 0)
                                cmd = CMD_CPU_DISPATCH_HORIZONTAL;
                        else if (strcmp("vertical", argv[optind - 1]) == 0)
@@ -309,33 +341,50 @@ int main(int argc, char *argv[])
                case 'r':
                        cmd = CMD_CPU_RESCAN;
                        break;
+
+               case 'h':
+                       usage();
                case 'V':
-                       printf(_("%s from %s\n"), program_invocation_short_name,
-                              PACKAGE_STRING);
-                       return EXIT_SUCCESS;
+                       print_version(EXIT_SUCCESS);
                default:
-                       usage(stderr);
+                       errtryhelp(EXIT_FAILURE);
                }
        }
 
-       if ((argc == 1) || (argc != optind))
-               usage(stderr);
+       if ((argc == 1) || (argc != optind)) {
+               warnx(_("bad usage"));
+               errtryhelp(EXIT_FAILURE);
+       }
 
        switch (cmd) {
        case CMD_CPU_ENABLE:
-               return cpu_enable(cpu_set, maxcpus, 1);
+               rc = cpu_enable(sys, cpu_set, maxcpus, 1);
+               break;
        case CMD_CPU_DISABLE:
-               return cpu_enable(cpu_set, maxcpus, 0);
+               rc = cpu_enable(sys, cpu_set, maxcpus, 0);
+               break;
        case CMD_CPU_CONFIGURE:
-               return cpu_configure(cpu_set, maxcpus, 1);
+               rc = cpu_configure(sys, cpu_set, maxcpus, 1);
+               break;
        case CMD_CPU_DECONFIGURE:
-               return cpu_configure(cpu_set, maxcpus, 0);
+               rc = cpu_configure(sys, cpu_set, maxcpus, 0);
+               break;
        case CMD_CPU_RESCAN:
-               return cpu_rescan();
+               rc = cpu_rescan(sys);
+               break;
        case CMD_CPU_DISPATCH_HORIZONTAL:
-               return cpu_set_dispatch(0);
+               rc = cpu_set_dispatch(sys, 0);
+               break;
        case CMD_CPU_DISPATCH_VERTICAL:
-               return cpu_set_dispatch(1);
+               rc = cpu_set_dispatch(sys, 1);
+               break;
+       default:
+               rc = -EINVAL;
+               break;
        }
-       return EXIT_SUCCESS;
+
+       ul_unref_path(sys);
+
+       return rc == 0 ? EXIT_SUCCESS :
+               rc < 0 ? EXIT_FAILURE : CHCPU_EXIT_SOMEOK;
 }