blob: e203f0db683443f405d3d4e4c57fb58fadcf0849 [file] [log] [blame]
Erik Andersene49d5ec2000-02-08 19:58:47 +00001/* vi: set sw=4 ts=4: */
Eric Andersencc8ed391999-10-05 16:24:54 +00002/*
3 * mkswap.c - set up a linux swap device
4 *
5 * (C) 1991 Linus Torvalds. This file may be redistributed as per
6 * the Linux copyright.
7 */
8
9/*
10 * 20.12.91 - time began. Got VM working yesterday by doing this by hand.
11 *
Eric Andersene77ae3a1999-10-19 20:03:34 +000012 * Usage: mkswap [-c] [-vN] [-f] device [size-in-blocks]
Eric Andersencc8ed391999-10-05 16:24:54 +000013 *
Eric Andersene77ae3a1999-10-19 20:03:34 +000014 * -c for readability checking. (Use it unless you are SURE!)
15 * -vN for swap areas version N. (Only N=0,1 known today.)
16 * -f for forcing swap creation even if it would smash partition table.
Eric Andersencc8ed391999-10-05 16:24:54 +000017 *
Eric Andersene77ae3a1999-10-19 20:03:34 +000018 * The device may be a block device or an image of one, but this isn't
Eric Andersencc8ed391999-10-05 16:24:54 +000019 * enforced (but it's not much fun on a character device :-).
20 *
21 * Patches from jaggy@purplet.demon.co.uk (Mike Jagdis) to make the
22 * size-in-blocks parameter optional added Wed Feb 8 10:33:43 1995.
Eric Andersene77ae3a1999-10-19 20:03:34 +000023 *
24 * Version 1 swap area code (for kernel 2.1.117), aeb, 981010.
25 *
26 * Sparc fixes, jj@ultra.linux.cz (Jakub Jelinek), 981201 - mangled by aeb.
27 * V1_MAX_PAGES fixes, jj, 990325.
28 *
29 * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@misiek.eu.org>
30 * - added Native Language Support
31 *
32 * from util-linux -- adapted for busybox by
Eric Andersencb81e642003-07-14 21:21:08 +000033 * Erik Andersen <andersen@codepoet.org>. I ripped out Native Language
Eric Andersene77ae3a1999-10-19 20:03:34 +000034 * Support, made some stuff smaller, and fitted for life in busybox.
35 *
Eric Andersencc8ed391999-10-05 16:24:54 +000036 */
37
38#include <stdio.h>
39#include <unistd.h>
40#include <string.h>
41#include <fcntl.h>
42#include <stdlib.h>
Erik Andersene49d5ec2000-02-08 19:58:47 +000043#include <sys/ioctl.h> /* for _IO */
Eric Andersene77ae3a1999-10-19 20:03:34 +000044#include <sys/utsname.h>
Erik Andersene49d5ec2000-02-08 19:58:47 +000045#include <asm/page.h> /* for PAGE_SIZE and PAGE_SHIFT */
Eric Andersene77ae3a1999-10-19 20:03:34 +000046 /* we also get PAGE_SIZE via getpagesize() */
Eric Andersencbe31da2001-02-20 06:14:08 +000047#include "busybox.h"
Eric Andersencc8ed391999-10-05 16:24:54 +000048
Eric Andersene77ae3a1999-10-19 20:03:34 +000049#ifndef _IO
50/* pre-1.3.45 */
Mark Whitley59ab0252001-01-23 22:30:04 +000051static const int BLKGETSIZE = 0x1260;
Eric Andersene77ae3a1999-10-19 20:03:34 +000052#else
53/* same on i386, m68k, arm; different on alpha, mips, sparc, ppc */
54#define BLKGETSIZE _IO(0x12,96)
Eric Andersencc8ed391999-10-05 16:24:54 +000055#endif
56
Erik Andersene49d5ec2000-02-08 19:58:47 +000057static char *device_name = NULL;
Eric Andersencc8ed391999-10-05 16:24:54 +000058static int DEV = -1;
59static long PAGES = 0;
Eric Andersene77ae3a1999-10-19 20:03:34 +000060static int check = 0;
Eric Andersencc8ed391999-10-05 16:24:54 +000061static int badpages = 0;
Eric Andersene77ae3a1999-10-19 20:03:34 +000062static int version = -1;
Eric Andersencc8ed391999-10-05 16:24:54 +000063
Eric Andersene77ae3a1999-10-19 20:03:34 +000064#define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
Eric Andersencc8ed391999-10-05 16:24:54 +000065
Eric Andersene77ae3a1999-10-19 20:03:34 +000066/*
67 * The definition of the union swap_header uses the constant PAGE_SIZE.
68 * Unfortunately, on some architectures this depends on the hardware model,
69 * and can only be found at run time -- we use getpagesize().
70 */
71
72static int pagesize;
Eric Andersen3496fdc2006-01-30 23:09:20 +000073static unsigned int *signature_page;
Eric Andersene77ae3a1999-10-19 20:03:34 +000074
Eric Andersen3e6ff902001-03-09 21:24:12 +000075static struct swap_header_v1 {
Erik Andersene49d5ec2000-02-08 19:58:47 +000076 char bootbits[1024]; /* Space for disklabel etc. */
Eric Andersene77ae3a1999-10-19 20:03:34 +000077 unsigned int version;
78 unsigned int last_page;
79 unsigned int nr_badpages;
80 unsigned int padding[125];
81 unsigned int badpages[1];
82} *p;
83
Eric Andersenfcffa2c2002-04-06 05:17:57 +000084static inline void init_signature_page(void)
Erik Andersene49d5ec2000-02-08 19:58:47 +000085{
Eric Andersene77ae3a1999-10-19 20:03:34 +000086 pagesize = getpagesize();
87
88#ifdef PAGE_SIZE
89 if (pagesize != PAGE_SIZE)
Manuel Novoa III cad53642003-03-19 09:13:01 +000090 bb_error_msg("Assuming pages of size %d", pagesize);
Eric Andersene77ae3a1999-10-19 20:03:34 +000091#endif
Eric Andersen3496fdc2006-01-30 23:09:20 +000092 signature_page = (unsigned int *) xmalloc(pagesize);
Erik Andersene49d5ec2000-02-08 19:58:47 +000093 memset(signature_page, 0, pagesize);
Eric Andersene77ae3a1999-10-19 20:03:34 +000094 p = (struct swap_header_v1 *) signature_page;
95}
96
Eric Andersenfcffa2c2002-04-06 05:17:57 +000097static inline void write_signature(char *sig)
Erik Andersene49d5ec2000-02-08 19:58:47 +000098{
Eric Andersene77ae3a1999-10-19 20:03:34 +000099 char *sp = (char *) signature_page;
100
Erik Andersene49d5ec2000-02-08 19:58:47 +0000101 strncpy(sp + pagesize - 10, sig, 10);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000102}
103
104#define V0_MAX_PAGES (8 * (pagesize - 10))
105/* Before 2.2.0pre9 */
106#define V1_OLD_MAX_PAGES ((0x7fffffff / pagesize) - 1)
107/* Since 2.2.0pre9:
108 error if nr of pages >= SWP_OFFSET(SWP_ENTRY(0,~0UL))
109 with variations on
110 #define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8))
111 #define SWP_OFFSET(entry) ((entry) >> 8)
112 on the various architectures. Below the result - yuk.
113
114 Machine pagesize SWP_ENTRY SWP_OFFSET bound+1 oldbound+2
115 i386 2^12 o<<8 e>>8 1<<24 1<<19
116 mips 2^12 o<<15 e>>15 1<<17 1<<19
117 alpha 2^13 o<<40 e>>40 1<<24 1<<18
118 m68k 2^12 o<<12 e>>12 1<<20 1<<19
119 sparc 2^{12,13} (o&0x3ffff)<<9 (e>>9)&0x3ffff 1<<18 1<<{19,18}
120 sparc64 2^13 o<<13 e>>13 1<<51 1<<18
121 ppc 2^12 o<<8 e>>8 1<<24 1<<19
122 armo 2^{13,14,15} o<<8 e>>8 1<<24 1<<{18,17,16}
123 armv 2^12 o<<9 e>>9 1<<23 1<<19
124
125 assuming that longs have 64 bits on alpha and sparc64 and 32 bits elsewhere.
126
127 The bad part is that we need to know this since the kernel will
128 refuse a swap space if it is too large.
129*/
130/* patch from jj - why does this differ from the above? */
131#if defined(__alpha__)
132#define V1_MAX_PAGES ((1 << 24) - 1)
133#elif defined(__mips__)
134#define V1_MAX_PAGES ((1 << 17) - 1)
135#elif defined(__sparc_v9__)
136#define V1_MAX_PAGES ((3 << 29) - 1)
137#elif defined(__sparc__)
138#define V1_MAX_PAGES (pagesize == 8192 ? ((3 << 29) - 1) : ((1 << 18) - 1))
139#else
140#define V1_MAX_PAGES V1_OLD_MAX_PAGES
141#endif
142/* man page now says:
143The maximum useful size of a swap area now depends on the architecture.
144It is roughly 2GB on i386, PPC, m68k, ARM, 1GB on sparc, 512MB on mips,
145128GB on alpha and 3TB on sparc64.
146*/
147
148#define MAX_BADPAGES ((pagesize-1024-128*sizeof(int)-10)/sizeof(int))
149
Eric Andersenfcffa2c2002-04-06 05:17:57 +0000150static inline void bit_set(unsigned int *addr, unsigned int nr)
Eric Andersencc8ed391999-10-05 16:24:54 +0000151{
152 unsigned int r, m;
153
154 addr += nr / (8 * sizeof(int));
Erik Andersene49d5ec2000-02-08 19:58:47 +0000155
Eric Andersencc8ed391999-10-05 16:24:54 +0000156 r = *addr;
157 m = 1 << (nr & (8 * sizeof(int) - 1));
Erik Andersene49d5ec2000-02-08 19:58:47 +0000158
Eric Andersencc8ed391999-10-05 16:24:54 +0000159 *addr = r | m;
Eric Andersencc8ed391999-10-05 16:24:54 +0000160}
161
Erik Andersene49d5ec2000-02-08 19:58:47 +0000162static int bit_test_and_clear(unsigned int *addr, unsigned int nr)
Eric Andersencc8ed391999-10-05 16:24:54 +0000163{
164 unsigned int r, m;
165
166 addr += nr / (8 * sizeof(int));
Erik Andersene49d5ec2000-02-08 19:58:47 +0000167
Eric Andersencc8ed391999-10-05 16:24:54 +0000168 r = *addr;
169 m = 1 << (nr & (8 * sizeof(int) - 1));
Erik Andersene49d5ec2000-02-08 19:58:47 +0000170
Eric Andersencc8ed391999-10-05 16:24:54 +0000171 *addr = r & ~m;
172 return (r & m) != 0;
173}
174
Eric Andersene77ae3a1999-10-19 20:03:34 +0000175
Eric Andersen16fdbe82000-12-20 23:40:57 +0000176static void page_ok(int page)
Erik Andersene49d5ec2000-02-08 19:58:47 +0000177{
178 if (version == 0)
Eric Andersene77ae3a1999-10-19 20:03:34 +0000179 bit_set(signature_page, page);
180}
Eric Andersencc8ed391999-10-05 16:24:54 +0000181
Eric Andersenfcffa2c2002-04-06 05:17:57 +0000182static inline void page_bad(int page)
Erik Andersene49d5ec2000-02-08 19:58:47 +0000183{
Eric Andersene77ae3a1999-10-19 20:03:34 +0000184 if (version == 0)
185 bit_test_and_clear(signature_page, page);
186 else {
187 if (badpages == MAX_BADPAGES)
Manuel Novoa III cad53642003-03-19 09:13:01 +0000188 bb_error_msg_and_die("too many bad pages");
Eric Andersene77ae3a1999-10-19 20:03:34 +0000189 p->badpages[badpages] = page;
190 }
191 badpages++;
192}
193
Eric Andersen16fdbe82000-12-20 23:40:57 +0000194static void check_blocks(void)
Erik Andersene49d5ec2000-02-08 19:58:47 +0000195{
Eric Andersencc8ed391999-10-05 16:24:54 +0000196 unsigned int current_page;
197 int do_seek = 1;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000198 char *buffer;
Eric Andersencc8ed391999-10-05 16:24:54 +0000199
Erik Andersen0d068a22000-03-21 22:32:57 +0000200 buffer = xmalloc(pagesize);
Eric Andersencc8ed391999-10-05 16:24:54 +0000201 current_page = 0;
202 while (current_page < PAGES) {
Eric Andersene77ae3a1999-10-19 20:03:34 +0000203 if (!check) {
204 page_ok(current_page++);
Eric Andersencc8ed391999-10-05 16:24:54 +0000205 continue;
Eric Andersencc8ed391999-10-05 16:24:54 +0000206 }
Erik Andersene49d5ec2000-02-08 19:58:47 +0000207 if (do_seek && lseek(DEV, current_page * pagesize, SEEK_SET) !=
208 current_page * pagesize)
Manuel Novoa III cad53642003-03-19 09:13:01 +0000209 bb_error_msg_and_die("seek failed in check_blocks");
Eric Andersene77ae3a1999-10-19 20:03:34 +0000210 if ((do_seek = (pagesize != read(DEV, buffer, pagesize)))) {
211 page_bad(current_page++);
Eric Andersencc8ed391999-10-05 16:24:54 +0000212 continue;
213 }
Eric Andersene77ae3a1999-10-19 20:03:34 +0000214 page_ok(current_page++);
Eric Andersencc8ed391999-10-05 16:24:54 +0000215 }
Eric Andersene77ae3a1999-10-19 20:03:34 +0000216 if (badpages == 1)
217 printf("one bad page\n");
218 else if (badpages > 1)
219 printf("%d bad pages\n", badpages);
Eric Andersencc8ed391999-10-05 16:24:54 +0000220}
221
Erik Andersene49d5ec2000-02-08 19:58:47 +0000222static long valid_offset(int fd, int offset)
Eric Andersencc8ed391999-10-05 16:24:54 +0000223{
224 char ch;
225
Erik Andersene49d5ec2000-02-08 19:58:47 +0000226 if (lseek(fd, offset, 0) < 0)
Eric Andersencc8ed391999-10-05 16:24:54 +0000227 return 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000228 if (read(fd, &ch, 1) < 1)
Eric Andersencc8ed391999-10-05 16:24:54 +0000229 return 0;
230 return 1;
231}
232
Erik Andersene49d5ec2000-02-08 19:58:47 +0000233static int find_size(int fd)
Eric Andersencc8ed391999-10-05 16:24:54 +0000234{
Eric Andersene77ae3a1999-10-19 20:03:34 +0000235 unsigned int high, low;
Eric Andersencc8ed391999-10-05 16:24:54 +0000236
237 low = 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000238 for (high = 1; high > 0 && valid_offset(fd, high); high *= 2)
Eric Andersencc8ed391999-10-05 16:24:54 +0000239 low = high;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000240 while (low < high - 1) {
Eric Andersencc8ed391999-10-05 16:24:54 +0000241 const int mid = (low + high) / 2;
242
Erik Andersene49d5ec2000-02-08 19:58:47 +0000243 if (valid_offset(fd, mid))
Eric Andersencc8ed391999-10-05 16:24:54 +0000244 low = mid;
245 else
246 high = mid;
247 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000248 return (low + 1);
249}
250
Eric Andersene77ae3a1999-10-19 20:03:34 +0000251/* return size in pages, to avoid integer overflow */
Erik Andersene49d5ec2000-02-08 19:58:47 +0000252static long get_size(const char *file)
Eric Andersencc8ed391999-10-05 16:24:54 +0000253{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000254 int fd;
255 long size;
Eric Andersencc8ed391999-10-05 16:24:54 +0000256
Matt Kraaia9819b22000-12-22 01:48:07 +0000257 if ((fd = open(file, O_RDONLY)) < 0)
Manuel Novoa III cad53642003-03-19 09:13:01 +0000258 bb_perror_msg_and_die("%s", file);
Eric Andersencc8ed391999-10-05 16:24:54 +0000259 if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000260 int sectors_per_page = pagesize / 512;
261
Eric Andersene77ae3a1999-10-19 20:03:34 +0000262 size /= sectors_per_page;
263 } else {
264 size = find_size(fd) / pagesize;
Eric Andersencc8ed391999-10-05 16:24:54 +0000265 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000266 close(fd);
267 return size;
268}
269
Erik Andersene49d5ec2000-02-08 19:58:47 +0000270int mkswap_main(int argc, char **argv)
Eric Andersencc8ed391999-10-05 16:24:54 +0000271{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000272 char *tmp;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000273 struct stat statbuf;
274 int sz;
275 int maxpages;
276 int goodpages;
277 int offset;
278 int force = 0;
Eric Andersencc8ed391999-10-05 16:24:54 +0000279
Erik Andersene49d5ec2000-02-08 19:58:47 +0000280 init_signature_page(); /* get pagesize */
Eric Andersene77ae3a1999-10-19 20:03:34 +0000281
282 while (argc-- > 1) {
Eric Andersencc8ed391999-10-05 16:24:54 +0000283 argv++;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000284 if (argv[0][0] != '-') {
Eric Andersencc8ed391999-10-05 16:24:54 +0000285 if (device_name) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000286 int blocks_per_page = pagesize / 1024;
287
288 PAGES = strtol(argv[0], &tmp, 0) / blocks_per_page;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000289 if (*tmp)
Manuel Novoa III cad53642003-03-19 09:13:01 +0000290 bb_show_usage();
Eric Andersencc8ed391999-10-05 16:24:54 +0000291 } else
292 device_name = argv[0];
Eric Andersene77ae3a1999-10-19 20:03:34 +0000293 } else {
294 switch (argv[0][1]) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000295 case 'c':
296 check = 1;
297 break;
298 case 'f':
299 force = 1;
300 break;
301 case 'v':
302 version = atoi(argv[0] + 2);
303 break;
304 default:
Manuel Novoa III cad53642003-03-19 09:13:01 +0000305 bb_show_usage();
Eric Andersencc8ed391999-10-05 16:24:54 +0000306 }
Eric Andersene77ae3a1999-10-19 20:03:34 +0000307 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000308 }
Eric Andersene77ae3a1999-10-19 20:03:34 +0000309 if (!device_name) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000310 bb_error_msg("error: Nowhere to set up swap on?");
311 bb_show_usage();
Eric Andersene77ae3a1999-10-19 20:03:34 +0000312 }
313 sz = get_size(device_name);
314 if (!PAGES) {
315 PAGES = sz;
316 } else if (PAGES > sz && !force) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000317 bb_error_msg("error: size %ld is larger than device size %d",
Erik Andersene49d5ec2000-02-08 19:58:47 +0000318 PAGES * (pagesize / 1024), sz * (pagesize / 1024));
Matt Kraai3e856ce2000-12-01 02:55:13 +0000319 return EXIT_FAILURE;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000320 }
321
322 if (version == -1) {
Glenn L McGrathe64bf402003-10-31 02:04:18 +0000323 if (get_kernel_revision() < MAKE_VERSION(2, 1, 117))
Eric Andersene77ae3a1999-10-19 20:03:34 +0000324 version = 0;
325 else
326 version = 1;
327 }
328 if (version != 0 && version != 1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000329 bb_error_msg("error: unknown version %d", version);
330 bb_show_usage();
Eric Andersene77ae3a1999-10-19 20:03:34 +0000331 }
332 if (PAGES < 10) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000333 bb_error_msg("error: swap area needs to be at least %ldkB",
Matt Kraaid537a952000-07-14 01:51:25 +0000334 (long) (10 * pagesize / 1024));
Manuel Novoa III cad53642003-03-19 09:13:01 +0000335 bb_show_usage();
Eric Andersene77ae3a1999-10-19 20:03:34 +0000336 }
337#if 0
338 maxpages = ((version == 0) ? V0_MAX_PAGES : V1_MAX_PAGES);
339#else
340 if (!version)
341 maxpages = V0_MAX_PAGES;
Eric Andersenef936da2000-10-30 17:22:04 +0000342 else if (get_kernel_revision() >= MAKE_VERSION(2, 2, 1))
Eric Andersene77ae3a1999-10-19 20:03:34 +0000343 maxpages = V1_MAX_PAGES;
344 else {
345 maxpages = V1_OLD_MAX_PAGES;
346 if (maxpages > V1_MAX_PAGES)
347 maxpages = V1_MAX_PAGES;
348 }
349#endif
350 if (PAGES > maxpages) {
351 PAGES = maxpages;
Manuel Novoa III cad53642003-03-19 09:13:01 +0000352 bb_error_msg("warning: truncating swap area to %ldkB",
Matt Kraaid537a952000-07-14 01:51:25 +0000353 PAGES * pagesize / 1024);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000354 }
355
Erik Andersene49d5ec2000-02-08 19:58:47 +0000356 DEV = open(device_name, O_RDWR);
Matt Kraaia9819b22000-12-22 01:48:07 +0000357 if (DEV < 0 || fstat(DEV, &statbuf) < 0)
Manuel Novoa III cad53642003-03-19 09:13:01 +0000358 bb_perror_msg_and_die("%s", device_name);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000359 if (!S_ISBLK(statbuf.st_mode))
Erik Andersene49d5ec2000-02-08 19:58:47 +0000360 check = 0;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000361 else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340)
Manuel Novoa III cad53642003-03-19 09:13:01 +0000362 bb_error_msg_and_die("Will not try to make swapdevice on '%s'", device_name);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000363
364#ifdef __sparc__
365 if (!force && version == 0) {
366 /* Don't overwrite partition table unless forced */
Erik Andersene49d5ec2000-02-08 19:58:47 +0000367 unsigned char *buffer = (unsigned char *) signature_page;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000368 unsigned short *q, sum;
369
370 if (read(DEV, buffer, 512) != 512)
Manuel Novoa III cad53642003-03-19 09:13:01 +0000371 bb_error_msg_and_die("fatal: first page unreadable");
Eric Andersene77ae3a1999-10-19 20:03:34 +0000372 if (buffer[508] == 0xDA && buffer[509] == 0xBE) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000373 q = (unsigned short *) (buffer + 510);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000374 for (sum = 0; q >= (unsigned short *) buffer;)
375 sum ^= *q--;
376 if (!sum) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000377 bb_error_msg("Device '%s' contains a valid Sun disklabel.\n"
Matt Kraaid537a952000-07-14 01:51:25 +0000378"This probably means creating v0 swap would destroy your partition table\n"
379"No swap created. If you really want to create swap v0 on that device, use\n"
Matt Kraaidd19c692001-01-31 19:00:21 +0000380"the -f option to force it.", device_name);
Matt Kraai3e856ce2000-12-01 02:55:13 +0000381 return EXIT_FAILURE;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000382 }
383 }
384 }
385#endif
386
387 if (version == 0 || check)
388 check_blocks();
Erik Andersene49d5ec2000-02-08 19:58:47 +0000389 if (version == 0 && !bit_test_and_clear(signature_page, 0))
Manuel Novoa III cad53642003-03-19 09:13:01 +0000390 bb_error_msg_and_die("fatal: first page unreadable");
Eric Andersene77ae3a1999-10-19 20:03:34 +0000391 if (version == 1) {
392 p->version = version;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000393 p->last_page = PAGES - 1;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000394 p->nr_badpages = badpages;
395 }
396
397 goodpages = PAGES - badpages - 1;
398 if (goodpages <= 0)
Manuel Novoa III cad53642003-03-19 09:13:01 +0000399 bb_error_msg_and_die("Unable to set up swap-space: unreadable");
Eric Andersene77ae3a1999-10-19 20:03:34 +0000400 printf("Setting up swapspace version %d, size = %ld bytes\n",
Erik Andersene49d5ec2000-02-08 19:58:47 +0000401 version, (long) (goodpages * pagesize));
Eric Andersene77ae3a1999-10-19 20:03:34 +0000402 write_signature((version == 0) ? "SWAP-SPACE" : "SWAPSPACE2");
403
404 offset = ((version == 0) ? 0 : 1024);
405 if (lseek(DEV, offset, SEEK_SET) != offset)
Manuel Novoa III cad53642003-03-19 09:13:01 +0000406 bb_error_msg_and_die("unable to rewind swap-device");
Erik Andersene49d5ec2000-02-08 19:58:47 +0000407 if (write(DEV, (char *) signature_page + offset, pagesize - offset)
408 != pagesize - offset)
Manuel Novoa III cad53642003-03-19 09:13:01 +0000409 bb_error_msg_and_die("unable to write signature page");
Eric Andersene77ae3a1999-10-19 20:03:34 +0000410
411 /*
412 * A subsequent swapon() will fail if the signature
413 * is not actually on disk. (This is a kernel bug.)
414 */
415 if (fsync(DEV))
Manuel Novoa III cad53642003-03-19 09:13:01 +0000416 bb_error_msg_and_die("fsync failed");
Matt Kraai3e856ce2000-12-01 02:55:13 +0000417 return EXIT_SUCCESS;
Eric Andersencc8ed391999-10-05 16:24:54 +0000418}