sysupgrade.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. /*
  2. * Copyright (C) 2013 Felix Fietkau <nbd@openwrt.org>
  3. * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
  4. * Copyright (C) 2017 Matthias Schiffer <mschiffer@universe-factory.net>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU Lesser General Public License version 2.1
  8. * as published by the Free Software Foundation
  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
  13. * GNU General Public License for more details.
  14. */
  15. #define _GNU_SOURCE
  16. #include "watchdog.h"
  17. #include "sysupgrade.h"
  18. #include <ctype.h>
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <unistd.h>
  22. #include <libubox/blobmsg.h>
  23. void sysupgrade_exec_upgraded(const char *prefix, char *path,
  24. const char *backup, char *command,
  25. struct blob_attr *options)
  26. {
  27. char *wdt_fd = watchdog_fd();
  28. char *argv[] = { "/sbin/upgraded", NULL, NULL, NULL};
  29. struct blob_attr *option;
  30. int rem;
  31. int ret;
  32. ret = chroot(prefix);
  33. if (ret < 0) {
  34. fprintf(stderr, "Failed to chroot for upgraded exec.\n");
  35. return;
  36. }
  37. argv[1] = path;
  38. argv[2] = command;
  39. if (wdt_fd) {
  40. watchdog_set_cloexec(false);
  41. setenv("WDTFD", wdt_fd, 1);
  42. }
  43. if (backup)
  44. setenv("UPGRADE_BACKUP", backup, 1);
  45. blobmsg_for_each_attr(option, options, rem) {
  46. const char *prefix = "UPGRADE_OPT_";
  47. char value[11];
  48. char *name;
  49. char *c;
  50. int tmp;
  51. if (asprintf(&name, "%s%s", prefix, blobmsg_name(option)) <= 0)
  52. continue;
  53. for (c = name + strlen(prefix); *c; c++) {
  54. if (isalnum(*c) || *c == '_') {
  55. *c = toupper(*c);
  56. } else {
  57. c = NULL;
  58. break;
  59. }
  60. }
  61. if (!c) {
  62. fprintf(stderr, "Option \"%s\" contains invalid characters\n",
  63. blobmsg_name(option));
  64. free(name);
  65. continue;
  66. }
  67. switch (blobmsg_type(option)) {
  68. case BLOBMSG_TYPE_INT32:
  69. tmp = blobmsg_get_u32(option);
  70. break;
  71. case BLOBMSG_TYPE_INT16:
  72. tmp = blobmsg_get_u16(option);
  73. break;
  74. case BLOBMSG_TYPE_INT8:
  75. tmp = blobmsg_get_u8(option);
  76. break;
  77. default:
  78. fprintf(stderr, "Option \"%s\" has unsupported type: %d\n",
  79. blobmsg_name(option), blobmsg_type(option));
  80. free(name);
  81. continue;
  82. }
  83. snprintf(value, sizeof(value), "%u", tmp);
  84. setenv(name, value, 1);
  85. free(name);
  86. }
  87. execvp(argv[0], argv);
  88. /* Cleanup on failure */
  89. fprintf(stderr, "Failed to exec upgraded.\n");
  90. unsetenv("WDTFD");
  91. watchdog_set_cloexec(true);
  92. ret = chroot(".");
  93. if (ret < 0) {
  94. fprintf(stderr, "Failed to reset chroot, exiting.\n");
  95. exit(EXIT_FAILURE);
  96. }
  97. }