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