blob: e2c060f303a6b8dc40ad7eef46176c60178280e0 [file] [log] [blame]
Erik Andersene49d5ec2000-02-08 19:58:47 +00001/* vi: set sw=4 ts=4: */
Eric Andersen87590061999-10-18 21:22:59 +00002/*
3 * Mini swapon/swapoff implementation for busybox
4 *
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
Eric Andersen87590061999-10-18 21:22:59 +00006 *
Denys Vlasenko0ef64bd2010-08-16 20:14:46 +02007 * Licensed under GPLv2, see file LICENSE in this source tree.
Eric Andersen87590061999-10-18 21:22:59 +00008 */
9
Denis Vlasenkob6adbf12007-05-26 19:00:18 +000010#include "libbb.h"
Eric Andersen87590061999-10-18 21:22:59 +000011#include <mntent.h>
Eric Andersene76c3b02001-04-05 03:14:39 +000012#include <sys/swap.h>
Eric Andersene76c3b02001-04-05 03:14:39 +000013
Natanael Copa9aff2992009-09-20 04:28:22 +020014#if ENABLE_FEATURE_MOUNT_LABEL
15# include "volume_id.h"
16#else
17# define resolve_mount_spec(fsname) ((void)0)
18#endif
19
Denis Vlasenkoee56e012008-05-18 23:05:34 +000020#if ENABLE_FEATURE_SWAPON_PRI
21struct globals {
22 int flags;
Denys Vlasenko98a4c7c2010-02-04 15:00:15 +010023} FIX_ALIASING;
Denis Vlasenkoee56e012008-05-18 23:05:34 +000024#define G (*(struct globals*)&bb_common_bufsiz1)
25#define g_flags (G.flags)
26#else
27#define g_flags 0
28#endif
29
Rob Landley20cc6d52006-09-12 21:42:17 +000030static int swap_enable_disable(char *device)
Eric Andersen87590061999-10-18 21:22:59 +000031{
Erik Andersene49d5ec2000-02-08 19:58:47 +000032 int status;
Eric Andersen97b141a2002-11-03 00:25:23 +000033 struct stat st;
34
Natanael Copa9aff2992009-09-20 04:28:22 +020035 resolve_mount_spec(&device);
Rob Landleyc5b1d4d2006-03-13 15:45:16 +000036 xstat(device, &st);
Eric Andersen97b141a2002-11-03 00:25:23 +000037
Denis Vlasenko56594072007-03-14 22:55:39 +000038#if ENABLE_DESKTOP
Eric Andersen97b141a2002-11-03 00:25:23 +000039 /* test for holes */
Mike Frysinger6943a942005-09-13 02:29:39 +000040 if (S_ISREG(st.st_mode))
Denis Vlasenkof8b21d02007-11-05 19:33:38 +000041 if (st.st_blocks * (off_t)512 < st.st_size)
Denis Vlasenko56594072007-03-14 22:55:39 +000042 bb_error_msg("warning: swap file has holes");
Denis Vlasenkob3f09f42007-03-12 18:16:24 +000043#endif
Eric Andersen87590061999-10-18 21:22:59 +000044
Denis Vlasenko8f8f2682006-10-03 21:00:43 +000045 if (applet_name[5] == 'n')
Denis Vlasenkoee56e012008-05-18 23:05:34 +000046 status = swapon(device, g_flags);
Erik Andersene49d5ec2000-02-08 19:58:47 +000047 else
48 status = swapoff(device);
49
Eric Andersendb1df5e2002-10-26 10:27:42 +000050 if (status != 0) {
Denis Vlasenko0c97c9d2007-10-01 11:58:38 +000051 bb_simple_perror_msg(device);
Mike Frysinger2d5e4f62005-09-16 04:41:20 +000052 return 1;
Eric Andersendb1df5e2002-10-26 10:27:42 +000053 }
Mike Frysinger6943a942005-09-13 02:29:39 +000054
Mike Frysinger2d5e4f62005-09-16 04:41:20 +000055 return 0;
Eric Andersen87590061999-10-18 21:22:59 +000056}
57
Eric Andersendb1df5e2002-10-26 10:27:42 +000058static int do_em_all(void)
Eric Andersen87590061999-10-18 21:22:59 +000059{
60 struct mntent *m;
Mike Frysinger6943a942005-09-13 02:29:39 +000061 FILE *f;
62 int err;
Eric Andersen87590061999-10-18 21:22:59 +000063
Mike Frysinger6943a942005-09-13 02:29:39 +000064 f = setmntent("/etc/fstab", "r");
Matt Kraaia9819b22000-12-22 01:48:07 +000065 if (f == NULL)
Manuel Novoa III cad53642003-03-19 09:13:01 +000066 bb_perror_msg_and_die("/etc/fstab");
Mike Frysinger6943a942005-09-13 02:29:39 +000067
68 err = 0;
Lauri Kasanend2844fc2010-04-29 22:20:57 +020069 while ((m = getmntent(f)) != NULL) {
70 if (strcmp(m->mnt_type, MNTTYPE_SWAP) == 0) {
71 /* swapon -a should ignore entries with noauto,
72 * but swapoff -a should process them */
73 if (applet_name[5] != 'n'
74 || hasmntopt(m, MNTOPT_NOAUTO) == NULL
75 ) {
76 err += swap_enable_disable(m->mnt_fsname);
77 }
78 }
79 }
Mike Frysinger6943a942005-09-13 02:29:39 +000080
Lauri Kasanend2844fc2010-04-29 22:20:57 +020081 if (ENABLE_FEATURE_CLEAN_UP)
82 endmntent(f);
Mike Frysinger6943a942005-09-13 02:29:39 +000083
Eric Andersendb1df5e2002-10-26 10:27:42 +000084 return err;
Eric Andersen87590061999-10-18 21:22:59 +000085}
86
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +000087int swap_on_off_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +000088int swap_on_off_main(int argc UNUSED_PARAM, char **argv)
Eric Andersen87590061999-10-18 21:22:59 +000089{
Mike Frysinger2d5e4f62005-09-16 04:41:20 +000090 int ret;
Mike Frysinger6943a942005-09-13 02:29:39 +000091
Denis Vlasenkoee56e012008-05-18 23:05:34 +000092#if !ENABLE_FEATURE_SWAPON_PRI
Denis Vlasenkofe7cd642007-08-18 15:32:12 +000093 ret = getopt32(argv, "a");
Denis Vlasenkoee56e012008-05-18 23:05:34 +000094#else
95 opt_complementary = "p+";
96 ret = getopt32(argv, (applet_name[5] == 'n') ? "ap:" : "a", &g_flags);
97
98 if (ret & 2) { // -p
99 g_flags = SWAP_FLAG_PREFER |
100 ((g_flags & SWAP_FLAG_PRIO_MASK) << SWAP_FLAG_PRIO_SHIFT);
101 ret &= 1;
102 }
103#endif
104
105 if (ret /* & 1: not needed */) // -a
Rob Landleybc3d4a12005-09-13 01:30:19 +0000106 return do_em_all();
Mike Frysinger6943a942005-09-13 02:29:39 +0000107
Denis Vlasenkoee56e012008-05-18 23:05:34 +0000108 argv += optind;
109 if (!*argv)
110 bb_show_usage();
111
Denis Vlasenkob3f09f42007-03-12 18:16:24 +0000112 /* ret = 0; redundant */
Denis Vlasenkoee56e012008-05-18 23:05:34 +0000113 do {
Mike Frysinger2d5e4f62005-09-16 04:41:20 +0000114 ret += swap_enable_disable(*argv);
Denis Vlasenkoee56e012008-05-18 23:05:34 +0000115 } while (*++argv);
116
Mike Frysinger2d5e4f62005-09-16 04:41:20 +0000117 return ret;
Eric Andersen87590061999-10-18 21:22:59 +0000118}