LCOV - code coverage report
Current view: top level - core - emergency-action.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 15 77 19.5 %
Date: 2019-08-22 15:41:25 Functions: 4 5 80.0 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : 
       3             : #include <sys/reboot.h>
       4             : 
       5             : #include "bus-error.h"
       6             : #include "bus-util.h"
       7             : #include "emergency-action.h"
       8             : #include "raw-reboot.h"
       9             : #include "reboot-util.h"
      10             : #include "special.h"
      11             : #include "string-table.h"
      12             : #include "terminal-util.h"
      13             : #include "virt.h"
      14             : 
      15           0 : static void log_and_status(Manager *m, bool warn, const char *message, const char *reason) {
      16           0 :         log_full(warn ? LOG_WARNING : LOG_DEBUG, "%s: %s", message, reason);
      17           0 :         if (warn)
      18           0 :                 manager_status_printf(m, STATUS_TYPE_EMERGENCY,
      19             :                                       ANSI_HIGHLIGHT_RED "  !!  " ANSI_NORMAL,
      20             :                                       "%s: %s", message, reason);
      21           0 : }
      22             : 
      23           7 : void emergency_action(
      24             :                 Manager *m,
      25             :                 EmergencyAction action,
      26             :                 EmergencyActionFlags options,
      27             :                 const char *reboot_arg,
      28             :                 int exit_status,
      29             :                 const char *reason) {
      30             : 
      31           7 :         assert(m);
      32           7 :         assert(action >= 0);
      33           7 :         assert(action < _EMERGENCY_ACTION_MAX);
      34             : 
      35           7 :         if (action == EMERGENCY_ACTION_NONE)
      36           7 :                 return;
      37             : 
      38           0 :         if (FLAGS_SET(options, EMERGENCY_ACTION_IS_WATCHDOG) && !m->service_watchdogs) {
      39           0 :                 log_warning("Watchdog disabled! Not acting on: %s", reason);
      40           0 :                 return;
      41             :         }
      42             : 
      43           0 :         bool warn = FLAGS_SET(options, EMERGENCY_ACTION_WARN);
      44             : 
      45           0 :         switch (action) {
      46             : 
      47           0 :         case EMERGENCY_ACTION_REBOOT:
      48           0 :                 log_and_status(m, warn, "Rebooting", reason);
      49             : 
      50           0 :                 (void) update_reboot_parameter_and_warn(reboot_arg, true);
      51           0 :                 (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_REBOOT_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL, NULL);
      52           0 :                 break;
      53             : 
      54           0 :         case EMERGENCY_ACTION_REBOOT_FORCE:
      55           0 :                 log_and_status(m, warn, "Forcibly rebooting", reason);
      56             : 
      57           0 :                 (void) update_reboot_parameter_and_warn(reboot_arg, true);
      58           0 :                 m->objective = MANAGER_REBOOT;
      59             : 
      60           0 :                 break;
      61             : 
      62           0 :         case EMERGENCY_ACTION_REBOOT_IMMEDIATE:
      63           0 :                 log_and_status(m, warn, "Rebooting immediately", reason);
      64             : 
      65           0 :                 sync();
      66             : 
      67           0 :                 if (!isempty(reboot_arg)) {
      68           0 :                         log_info("Rebooting with argument '%s'.", reboot_arg);
      69           0 :                         (void) raw_reboot(LINUX_REBOOT_CMD_RESTART2, reboot_arg);
      70           0 :                         log_warning_errno(errno, "Failed to reboot with parameter, retrying without: %m");
      71             :                 }
      72             : 
      73           0 :                 log_info("Rebooting.");
      74           0 :                 (void) reboot(RB_AUTOBOOT);
      75           0 :                 break;
      76             : 
      77           0 :         case EMERGENCY_ACTION_EXIT:
      78             : 
      79           0 :                 if (exit_status >= 0)
      80           0 :                         m->return_value = exit_status;
      81             : 
      82           0 :                 if (MANAGER_IS_USER(m) || detect_container() > 0) {
      83           0 :                         log_and_status(m, warn, "Exiting", reason);
      84           0 :                         (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_EXIT_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL, NULL);
      85           0 :                         break;
      86             :                 }
      87             : 
      88           0 :                 log_notice("Doing \"poweroff\" action instead of an \"exit\" emergency action.");
      89             :                 _fallthrough_;
      90             : 
      91           0 :         case EMERGENCY_ACTION_POWEROFF:
      92           0 :                 log_and_status(m, warn, "Powering off", reason);
      93           0 :                 (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_POWEROFF_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL, NULL);
      94           0 :                 break;
      95             : 
      96           0 :         case EMERGENCY_ACTION_EXIT_FORCE:
      97             : 
      98           0 :                 if (exit_status >= 0)
      99           0 :                         m->return_value = exit_status;
     100             : 
     101           0 :                 if (MANAGER_IS_USER(m) || detect_container() > 0) {
     102           0 :                         log_and_status(m, warn, "Exiting immediately", reason);
     103           0 :                         m->objective = MANAGER_EXIT;
     104           0 :                         break;
     105             :                 }
     106             : 
     107           0 :                 log_notice("Doing \"poweroff-force\" action instead of an \"exit-force\" emergency action.");
     108             :                 _fallthrough_;
     109             : 
     110           0 :         case EMERGENCY_ACTION_POWEROFF_FORCE:
     111           0 :                 log_and_status(m, warn, "Forcibly powering off", reason);
     112           0 :                 m->objective = MANAGER_POWEROFF;
     113           0 :                 break;
     114             : 
     115           0 :         case EMERGENCY_ACTION_POWEROFF_IMMEDIATE:
     116           0 :                 log_and_status(m, warn, "Powering off immediately", reason);
     117             : 
     118           0 :                 sync();
     119             : 
     120           0 :                 log_info("Powering off.");
     121           0 :                 (void) reboot(RB_POWER_OFF);
     122           0 :                 break;
     123             : 
     124           0 :         default:
     125           0 :                 assert_not_reached("Unknown emergency action");
     126             :         }
     127             : }
     128             : 
     129             : static const char* const emergency_action_table[_EMERGENCY_ACTION_MAX] = {
     130             :         [EMERGENCY_ACTION_NONE] = "none",
     131             :         [EMERGENCY_ACTION_REBOOT] = "reboot",
     132             :         [EMERGENCY_ACTION_REBOOT_FORCE] = "reboot-force",
     133             :         [EMERGENCY_ACTION_REBOOT_IMMEDIATE] = "reboot-immediate",
     134             :         [EMERGENCY_ACTION_POWEROFF] = "poweroff",
     135             :         [EMERGENCY_ACTION_POWEROFF_FORCE] = "poweroff-force",
     136             :         [EMERGENCY_ACTION_POWEROFF_IMMEDIATE] = "poweroff-immediate",
     137             :         [EMERGENCY_ACTION_EXIT] = "exit",
     138             :         [EMERGENCY_ACTION_EXIT_FORCE] = "exit-force",
     139             : };
     140          42 : DEFINE_STRING_TABLE_LOOKUP(emergency_action, EmergencyAction);
     141             : 
     142          20 : int parse_emergency_action(
     143             :                 const char *value,
     144             :                 bool system,
     145             :                 EmergencyAction *ret) {
     146             : 
     147             :         EmergencyAction x;
     148             : 
     149          20 :         x = emergency_action_from_string(value);
     150          20 :         if (x < 0)
     151           2 :                 return -EINVAL;
     152             : 
     153          18 :         if (!system && x != EMERGENCY_ACTION_NONE && x < _EMERGENCY_ACTION_FIRST_USER_ACTION)
     154           6 :                 return -EOPNOTSUPP;
     155             : 
     156          12 :         *ret = x;
     157          12 :         return 0;
     158             : }

Generated by: LCOV version 1.14