blob: 33ad00ac13c8a3f4bab6f33850b54bd9c805bce7 [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 *
Rob Landleye9a7a622006-09-22 02:52:41 +00007 * Licensed under the GPL version 2, see the file LICENSE in this tarball.
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;
23};
24#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;
69 while ((m = getmntent(f)) != NULL)
70 if (strcmp(m->mnt_type, MNTTYPE_SWAP) == 0)
Mike Frysinger2d5e4f62005-09-16 04:41:20 +000071 err += swap_enable_disable(m->mnt_fsname);
Mike Frysinger6943a942005-09-13 02:29:39 +000072
Erik Andersene49d5ec2000-02-08 19:58:47 +000073 endmntent(f);
Mike Frysinger6943a942005-09-13 02:29:39 +000074
Eric Andersendb1df5e2002-10-26 10:27:42 +000075 return err;
Eric Andersen87590061999-10-18 21:22:59 +000076}
77
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +000078int swap_on_off_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +000079int swap_on_off_main(int argc UNUSED_PARAM, char **argv)
Eric Andersen87590061999-10-18 21:22:59 +000080{
Mike Frysinger2d5e4f62005-09-16 04:41:20 +000081 int ret;
Mike Frysinger6943a942005-09-13 02:29:39 +000082
Denis Vlasenkoee56e012008-05-18 23:05:34 +000083#if !ENABLE_FEATURE_SWAPON_PRI
Denis Vlasenkofe7cd642007-08-18 15:32:12 +000084 ret = getopt32(argv, "a");
Denis Vlasenkoee56e012008-05-18 23:05:34 +000085#else
86 opt_complementary = "p+";
87 ret = getopt32(argv, (applet_name[5] == 'n') ? "ap:" : "a", &g_flags);
88
89 if (ret & 2) { // -p
90 g_flags = SWAP_FLAG_PREFER |
91 ((g_flags & SWAP_FLAG_PRIO_MASK) << SWAP_FLAG_PRIO_SHIFT);
92 ret &= 1;
93 }
94#endif
95
96 if (ret /* & 1: not needed */) // -a
Rob Landleybc3d4a12005-09-13 01:30:19 +000097 return do_em_all();
Mike Frysinger6943a942005-09-13 02:29:39 +000098
Denis Vlasenkoee56e012008-05-18 23:05:34 +000099 argv += optind;
100 if (!*argv)
101 bb_show_usage();
102
Denis Vlasenkob3f09f42007-03-12 18:16:24 +0000103 /* ret = 0; redundant */
Denis Vlasenkoee56e012008-05-18 23:05:34 +0000104 do {
Mike Frysinger2d5e4f62005-09-16 04:41:20 +0000105 ret += swap_enable_disable(*argv);
Denis Vlasenkoee56e012008-05-18 23:05:34 +0000106 } while (*++argv);
107
Mike Frysinger2d5e4f62005-09-16 04:41:20 +0000108 return ret;
Eric Andersen87590061999-10-18 21:22:59 +0000109}