swaponoff.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * Mini swapon/swapoff implementation for busybox
  4. *
  5. * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
  6. *
  7. * Licensed under GPLv2, see file LICENSE in this source tree.
  8. */
  9. //usage:#define swapon_trivial_usage
  10. //usage: "[-a]" IF_FEATURE_SWAPON_PRI(" [-p PRI]") " [DEVICE]"
  11. //usage:#define swapon_full_usage "\n\n"
  12. //usage: "Start swapping on DEVICE\n"
  13. //usage: "\n -a Start swapping on all swap devices"
  14. //usage: IF_FEATURE_SWAPON_PRI(
  15. //usage: "\n -p PRI Set swap device priority"
  16. //usage: )
  17. //usage:
  18. //usage:#define swapoff_trivial_usage
  19. //usage: "[-a] [DEVICE]"
  20. //usage:#define swapoff_full_usage "\n\n"
  21. //usage: "Stop swapping on DEVICE\n"
  22. //usage: "\n -a Stop swapping on all swap devices"
  23. #include "libbb.h"
  24. #include <mntent.h>
  25. #ifndef __BIONIC__
  26. # include <sys/swap.h>
  27. #endif
  28. #if ENABLE_FEATURE_MOUNT_LABEL
  29. # include "volume_id.h"
  30. #else
  31. # define resolve_mount_spec(fsname) ((void)0)
  32. #endif
  33. #ifndef MNTTYPE_SWAP
  34. # define MNTTYPE_SWAP "swap"
  35. #endif
  36. #if ENABLE_FEATURE_SWAPON_PRI
  37. struct globals {
  38. int flags;
  39. } FIX_ALIASING;
  40. #define G (*(struct globals*)&bb_common_bufsiz1)
  41. #define g_flags (G.flags)
  42. #else
  43. #define g_flags 0
  44. #endif
  45. #define INIT_G() do { } while (0)
  46. static int swap_enable_disable(char *device)
  47. {
  48. int status;
  49. struct stat st;
  50. resolve_mount_spec(&device);
  51. xstat(device, &st);
  52. #if ENABLE_DESKTOP
  53. /* test for holes */
  54. if (S_ISREG(st.st_mode))
  55. if (st.st_blocks * (off_t)512 < st.st_size)
  56. bb_error_msg("warning: swap file has holes");
  57. #endif
  58. if (applet_name[5] == 'n')
  59. status = swapon(device, g_flags);
  60. else
  61. status = swapoff(device);
  62. if (status != 0) {
  63. bb_simple_perror_msg(device);
  64. return 1;
  65. }
  66. return 0;
  67. }
  68. static int do_em_all(void)
  69. {
  70. struct mntent *m;
  71. FILE *f;
  72. int err;
  73. f = setmntent("/etc/fstab", "r");
  74. if (f == NULL)
  75. bb_perror_msg_and_die("/etc/fstab");
  76. err = 0;
  77. while ((m = getmntent(f)) != NULL) {
  78. if (strcmp(m->mnt_type, MNTTYPE_SWAP) == 0) {
  79. /* swapon -a should ignore entries with noauto,
  80. * but swapoff -a should process them */
  81. if (applet_name[5] != 'n'
  82. || hasmntopt(m, MNTOPT_NOAUTO) == NULL
  83. ) {
  84. #if ENABLE_FEATURE_SWAPON_PRI
  85. char *p;
  86. g_flags = 0; /* each swap space might have different flags */
  87. p = hasmntopt(m, "pri");
  88. if (p) {
  89. /* Max allowed 32767 (==SWAP_FLAG_PRIO_MASK) */
  90. unsigned int swap_prio = MIN(bb_strtou(p + 4 , NULL, 10), SWAP_FLAG_PRIO_MASK);
  91. /* We want to allow "NNNN,foo", thus errno == EINVAL is allowed too */
  92. if (errno != ERANGE) {
  93. g_flags = SWAP_FLAG_PREFER |
  94. (swap_prio << SWAP_FLAG_PRIO_SHIFT);
  95. }
  96. }
  97. #endif
  98. err += swap_enable_disable(m->mnt_fsname);
  99. }
  100. }
  101. }
  102. if (ENABLE_FEATURE_CLEAN_UP)
  103. endmntent(f);
  104. return err;
  105. }
  106. int swap_on_off_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  107. int swap_on_off_main(int argc UNUSED_PARAM, char **argv)
  108. {
  109. int ret;
  110. INIT_G();
  111. #if !ENABLE_FEATURE_SWAPON_PRI
  112. ret = getopt32(argv, "a");
  113. #else
  114. if (applet_name[5] == 'n')
  115. opt_complementary = "p+";
  116. ret = getopt32(argv, (applet_name[5] == 'n') ? "ap:" : "a", &g_flags);
  117. if (ret & 2) { // -p
  118. g_flags = SWAP_FLAG_PREFER |
  119. ((g_flags & SWAP_FLAG_PRIO_MASK) << SWAP_FLAG_PRIO_SHIFT);
  120. ret &= 1;
  121. }
  122. #endif
  123. if (ret /* & 1: not needed */) // -a
  124. return do_em_all();
  125. argv += optind;
  126. if (!*argv)
  127. bb_show_usage();
  128. /* ret = 0; redundant */
  129. do {
  130. ret += swap_enable_disable(*argv);
  131. } while (*++argv);
  132. return ret;
  133. }