blob: ce123e50236e34b197ee7fd26a5716308a4f06f0 [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 */
Rob Landleybc68cd12006-03-10 19:22:06 +000051enum { 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;
Bernhard Reutner-Fischer56dd0bf2006-03-29 17:32:24 +000062#if ENABLE_FEATURE_MKSWAP_V0
Eric Andersene77ae3a1999-10-19 20:03:34 +000063static int version = -1;
Eric Andersene77ae3a1999-10-19 20:03:34 +000064#define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
Bernhard Reutner-Fischer56dd0bf2006-03-29 17:32:24 +000065#else
66#define version 1
67/* and make sure that we optimize away anything which would deal with checking
68 * the kernel revision as we have v1 support only anyway.
69 */
70#define MAKE_VERSION(p,q,r) 1
71#define get_kernel_revision() 1
72#endif
Eric Andersencc8ed391999-10-05 16:24:54 +000073
Eric Andersene77ae3a1999-10-19 20:03:34 +000074/*
75 * The definition of the union swap_header uses the constant PAGE_SIZE.
76 * Unfortunately, on some architectures this depends on the hardware model,
77 * and can only be found at run time -- we use getpagesize().
78 */
79
80static int pagesize;
Eric Andersen3496fdc2006-01-30 23:09:20 +000081static unsigned int *signature_page;
Eric Andersene77ae3a1999-10-19 20:03:34 +000082
Eric Andersen3e6ff902001-03-09 21:24:12 +000083static struct swap_header_v1 {
Erik Andersene49d5ec2000-02-08 19:58:47 +000084 char bootbits[1024]; /* Space for disklabel etc. */
Bernhard Reutner-Fischer56dd0bf2006-03-29 17:32:24 +000085 unsigned int swap_version;
Eric Andersene77ae3a1999-10-19 20:03:34 +000086 unsigned int last_page;
87 unsigned int nr_badpages;
88 unsigned int padding[125];
89 unsigned int badpages[1];
90} *p;
91
Eric Andersenfcffa2c2002-04-06 05:17:57 +000092static inline void init_signature_page(void)
Erik Andersene49d5ec2000-02-08 19:58:47 +000093{
Eric Andersene77ae3a1999-10-19 20:03:34 +000094 pagesize = getpagesize();
95
96#ifdef PAGE_SIZE
97 if (pagesize != PAGE_SIZE)
Manuel Novoa III cad53642003-03-19 09:13:01 +000098 bb_error_msg("Assuming pages of size %d", pagesize);
Eric Andersene77ae3a1999-10-19 20:03:34 +000099#endif
Eric Andersen3496fdc2006-01-30 23:09:20 +0000100 signature_page = (unsigned int *) xmalloc(pagesize);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000101 memset(signature_page, 0, pagesize);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000102 p = (struct swap_header_v1 *) signature_page;
103}
104
Eric Andersenfcffa2c2002-04-06 05:17:57 +0000105static inline void write_signature(char *sig)
Erik Andersene49d5ec2000-02-08 19:58:47 +0000106{
Eric Andersene77ae3a1999-10-19 20:03:34 +0000107 char *sp = (char *) signature_page;
108
Erik Andersene49d5ec2000-02-08 19:58:47 +0000109 strncpy(sp + pagesize - 10, sig, 10);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000110}
111
112#define V0_MAX_PAGES (8 * (pagesize - 10))
113/* Before 2.2.0pre9 */
114#define V1_OLD_MAX_PAGES ((0x7fffffff / pagesize) - 1)
115/* Since 2.2.0pre9:
116 error if nr of pages >= SWP_OFFSET(SWP_ENTRY(0,~0UL))
117 with variations on
118 #define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8))
119 #define SWP_OFFSET(entry) ((entry) >> 8)
120 on the various architectures. Below the result - yuk.
121
122 Machine pagesize SWP_ENTRY SWP_OFFSET bound+1 oldbound+2
123 i386 2^12 o<<8 e>>8 1<<24 1<<19
124 mips 2^12 o<<15 e>>15 1<<17 1<<19
125 alpha 2^13 o<<40 e>>40 1<<24 1<<18
126 m68k 2^12 o<<12 e>>12 1<<20 1<<19
127 sparc 2^{12,13} (o&0x3ffff)<<9 (e>>9)&0x3ffff 1<<18 1<<{19,18}
128 sparc64 2^13 o<<13 e>>13 1<<51 1<<18
129 ppc 2^12 o<<8 e>>8 1<<24 1<<19
130 armo 2^{13,14,15} o<<8 e>>8 1<<24 1<<{18,17,16}
131 armv 2^12 o<<9 e>>9 1<<23 1<<19
132
133 assuming that longs have 64 bits on alpha and sparc64 and 32 bits elsewhere.
134
135 The bad part is that we need to know this since the kernel will
136 refuse a swap space if it is too large.
137*/
138/* patch from jj - why does this differ from the above? */
139#if defined(__alpha__)
140#define V1_MAX_PAGES ((1 << 24) - 1)
141#elif defined(__mips__)
142#define V1_MAX_PAGES ((1 << 17) - 1)
143#elif defined(__sparc_v9__)
144#define V1_MAX_PAGES ((3 << 29) - 1)
145#elif defined(__sparc__)
146#define V1_MAX_PAGES (pagesize == 8192 ? ((3 << 29) - 1) : ((1 << 18) - 1))
147#else
148#define V1_MAX_PAGES V1_OLD_MAX_PAGES
149#endif
150/* man page now says:
151The maximum useful size of a swap area now depends on the architecture.
152It is roughly 2GB on i386, PPC, m68k, ARM, 1GB on sparc, 512MB on mips,
153128GB on alpha and 3TB on sparc64.
154*/
155
156#define MAX_BADPAGES ((pagesize-1024-128*sizeof(int)-10)/sizeof(int))
157
Eric Andersenfcffa2c2002-04-06 05:17:57 +0000158static inline void bit_set(unsigned int *addr, unsigned int nr)
Eric Andersencc8ed391999-10-05 16:24:54 +0000159{
160 unsigned int r, m;
161
162 addr += nr / (8 * sizeof(int));
Erik Andersene49d5ec2000-02-08 19:58:47 +0000163
Eric Andersencc8ed391999-10-05 16:24:54 +0000164 r = *addr;
165 m = 1 << (nr & (8 * sizeof(int) - 1));
Erik Andersene49d5ec2000-02-08 19:58:47 +0000166
Eric Andersencc8ed391999-10-05 16:24:54 +0000167 *addr = r | m;
Eric Andersencc8ed391999-10-05 16:24:54 +0000168}
169
Erik Andersene49d5ec2000-02-08 19:58:47 +0000170static int bit_test_and_clear(unsigned int *addr, unsigned int nr)
Eric Andersencc8ed391999-10-05 16:24:54 +0000171{
172 unsigned int r, m;
173
174 addr += nr / (8 * sizeof(int));
Erik Andersene49d5ec2000-02-08 19:58:47 +0000175
Eric Andersencc8ed391999-10-05 16:24:54 +0000176 r = *addr;
177 m = 1 << (nr & (8 * sizeof(int) - 1));
Erik Andersene49d5ec2000-02-08 19:58:47 +0000178
Eric Andersencc8ed391999-10-05 16:24:54 +0000179 *addr = r & ~m;
180 return (r & m) != 0;
181}
182
Eric Andersen16fdbe82000-12-20 23:40:57 +0000183static void page_ok(int page)
Erik Andersene49d5ec2000-02-08 19:58:47 +0000184{
Bernhard Reutner-Fischer56dd0bf2006-03-29 17:32:24 +0000185 if (ENABLE_FEATURE_MKSWAP_V0) {
Eric Andersene77ae3a1999-10-19 20:03:34 +0000186 bit_set(signature_page, page);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000187 }
Eric Andersene77ae3a1999-10-19 20:03:34 +0000188}
189
Eric Andersen16fdbe82000-12-20 23:40:57 +0000190static void check_blocks(void)
Erik Andersene49d5ec2000-02-08 19:58:47 +0000191{
Eric Andersencc8ed391999-10-05 16:24:54 +0000192 unsigned int current_page;
193 int do_seek = 1;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000194 char *buffer;
Eric Andersencc8ed391999-10-05 16:24:54 +0000195
Erik Andersen0d068a22000-03-21 22:32:57 +0000196 buffer = xmalloc(pagesize);
Eric Andersencc8ed391999-10-05 16:24:54 +0000197 current_page = 0;
198 while (current_page < PAGES) {
Bernhard Reutner-Fischer56dd0bf2006-03-29 17:32:24 +0000199 if (!check && version == 0) {
Eric Andersene77ae3a1999-10-19 20:03:34 +0000200 page_ok(current_page++);
Eric Andersencc8ed391999-10-05 16:24:54 +0000201 continue;
Eric Andersencc8ed391999-10-05 16:24:54 +0000202 }
Erik Andersene49d5ec2000-02-08 19:58:47 +0000203 if (do_seek && lseek(DEV, current_page * pagesize, SEEK_SET) !=
204 current_page * pagesize)
Manuel Novoa III cad53642003-03-19 09:13:01 +0000205 bb_error_msg_and_die("seek failed in check_blocks");
Eric Andersene77ae3a1999-10-19 20:03:34 +0000206 if ((do_seek = (pagesize != read(DEV, buffer, pagesize)))) {
Bernhard Reutner-Fischer56dd0bf2006-03-29 17:32:24 +0000207 current_page++;
208 if (version == 0)
209 bit_test_and_clear(signature_page, current_page);
210 else {
211 if (badpages == MAX_BADPAGES)
212 bb_error_msg_and_die("too many bad pages");
213 p->badpages[badpages] = current_page;
214 }
215 badpages++;
Eric Andersencc8ed391999-10-05 16:24:54 +0000216 continue;
217 }
Eric Andersene77ae3a1999-10-19 20:03:34 +0000218 page_ok(current_page++);
Eric Andersencc8ed391999-10-05 16:24:54 +0000219 }
Bernhard Reutner-Fischer56dd0bf2006-03-29 17:32:24 +0000220 if (ENABLE_FEATURE_CLEAN_UP)
221 free(buffer);
222 if (badpages > 0)
223 printf("%d bad page%s\n", badpages, (badpages==1)?"":"s");
Eric Andersencc8ed391999-10-05 16:24:54 +0000224}
225
Erik Andersene49d5ec2000-02-08 19:58:47 +0000226static long valid_offset(int fd, int offset)
Eric Andersencc8ed391999-10-05 16:24:54 +0000227{
228 char ch;
229
Erik Andersene49d5ec2000-02-08 19:58:47 +0000230 if (lseek(fd, offset, 0) < 0)
Eric Andersencc8ed391999-10-05 16:24:54 +0000231 return 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000232 if (read(fd, &ch, 1) < 1)
Eric Andersencc8ed391999-10-05 16:24:54 +0000233 return 0;
234 return 1;
235}
236
Erik Andersene49d5ec2000-02-08 19:58:47 +0000237static int find_size(int fd)
Eric Andersencc8ed391999-10-05 16:24:54 +0000238{
Eric Andersene77ae3a1999-10-19 20:03:34 +0000239 unsigned int high, low;
Eric Andersencc8ed391999-10-05 16:24:54 +0000240
241 low = 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000242 for (high = 1; high > 0 && valid_offset(fd, high); high *= 2)
Eric Andersencc8ed391999-10-05 16:24:54 +0000243 low = high;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000244 while (low < high - 1) {
Eric Andersencc8ed391999-10-05 16:24:54 +0000245 const int mid = (low + high) / 2;
246
Erik Andersene49d5ec2000-02-08 19:58:47 +0000247 if (valid_offset(fd, mid))
Eric Andersencc8ed391999-10-05 16:24:54 +0000248 low = mid;
249 else
250 high = mid;
251 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000252 return (low + 1);
253}
254
Eric Andersene77ae3a1999-10-19 20:03:34 +0000255/* return size in pages, to avoid integer overflow */
Bernhard Reutner-Fischer56dd0bf2006-03-29 17:32:24 +0000256static inline long get_size(const char *file)
Eric Andersencc8ed391999-10-05 16:24:54 +0000257{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000258 int fd;
259 long size;
Eric Andersencc8ed391999-10-05 16:24:54 +0000260
Bernhard Reutner-Fischer56dd0bf2006-03-29 17:32:24 +0000261 if ((fd = open(file, O_RDONLY)) < 0) /* TODO: bb_xopen3 */
Manuel Novoa III cad53642003-03-19 09:13:01 +0000262 bb_perror_msg_and_die("%s", file);
Eric Andersencc8ed391999-10-05 16:24:54 +0000263 if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
Bernhard Reutner-Fischer56dd0bf2006-03-29 17:32:24 +0000264 size /= pagesize / 512;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000265 } else {
266 size = find_size(fd) / pagesize;
Eric Andersencc8ed391999-10-05 16:24:54 +0000267 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000268 close(fd);
269 return size;
270}
271
Erik Andersene49d5ec2000-02-08 19:58:47 +0000272int mkswap_main(int argc, char **argv)
Eric Andersencc8ed391999-10-05 16:24:54 +0000273{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000274 char *tmp;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000275 struct stat statbuf;
276 int sz;
277 int maxpages;
278 int goodpages;
Bernhard Reutner-Fischer56dd0bf2006-03-29 17:32:24 +0000279#ifdef __sparc__
Eric Andersene77ae3a1999-10-19 20:03:34 +0000280 int force = 0;
Bernhard Reutner-Fischer56dd0bf2006-03-29 17:32:24 +0000281#endif
Eric Andersencc8ed391999-10-05 16:24:54 +0000282
Erik Andersene49d5ec2000-02-08 19:58:47 +0000283 init_signature_page(); /* get pagesize */
Eric Andersene77ae3a1999-10-19 20:03:34 +0000284
Bernhard Reutner-Fischer56dd0bf2006-03-29 17:32:24 +0000285 bb_opt_complementally = "?"; /* call bb_show_usage internally */
286 sz = bb_getopt_ulflags(argc, argv, "+cfv:", &tmp);
287 if (sz & 1)
288 check = 1;
289#ifdef __sparc__
290 if (sz & 2)
291 force = 1;
292#endif
293#if ENABLE_FEATURE_MKSWAP_V0
294 if (sz & 4) {
295 version = bb_xgetlarg(tmp, 10, 0, 1);
296 } else {
Glenn L McGrathe64bf402003-10-31 02:04:18 +0000297 if (get_kernel_revision() < MAKE_VERSION(2, 1, 117))
Eric Andersene77ae3a1999-10-19 20:03:34 +0000298 version = 0;
299 else
300 version = 1;
301 }
Bernhard Reutner-Fischer56dd0bf2006-03-29 17:32:24 +0000302#endif
303
304 argv += optind;
305 argc -= optind;
306
307 goodpages = pagesize / 1024; /* cache division */
308 while (argc--) {
309 if (device_name) {
310 PAGES = bb_xgetlarg(argv[0], 0, 10, sz * goodpages) / goodpages;
311 argc = 0; /* ignore any surplus args.. */
312 } else {
313 device_name = argv[0];
314 sz = get_size(device_name);
315 argv++;
316 }
Eric Andersene77ae3a1999-10-19 20:03:34 +0000317 }
Bernhard Reutner-Fischer56dd0bf2006-03-29 17:32:24 +0000318
319 if (!device_name) {
320 bb_error_msg_and_die("error: Nowhere to set up swap on?");
Eric Andersene77ae3a1999-10-19 20:03:34 +0000321 }
Bernhard Reutner-Fischer56dd0bf2006-03-29 17:32:24 +0000322 if (!PAGES) {
323 PAGES = sz;
324 }
325
Eric Andersene77ae3a1999-10-19 20:03:34 +0000326#if 0
327 maxpages = ((version == 0) ? V0_MAX_PAGES : V1_MAX_PAGES);
328#else
329 if (!version)
330 maxpages = V0_MAX_PAGES;
Eric Andersenef936da2000-10-30 17:22:04 +0000331 else if (get_kernel_revision() >= MAKE_VERSION(2, 2, 1))
Eric Andersene77ae3a1999-10-19 20:03:34 +0000332 maxpages = V1_MAX_PAGES;
333 else {
334 maxpages = V1_OLD_MAX_PAGES;
335 if (maxpages > V1_MAX_PAGES)
336 maxpages = V1_MAX_PAGES;
337 }
338#endif
339 if (PAGES > maxpages) {
340 PAGES = maxpages;
Manuel Novoa III cad53642003-03-19 09:13:01 +0000341 bb_error_msg("warning: truncating swap area to %ldkB",
Bernhard Reutner-Fischer56dd0bf2006-03-29 17:32:24 +0000342 PAGES * goodpages);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000343 }
344
Erik Andersene49d5ec2000-02-08 19:58:47 +0000345 DEV = open(device_name, O_RDWR);
Matt Kraaia9819b22000-12-22 01:48:07 +0000346 if (DEV < 0 || fstat(DEV, &statbuf) < 0)
Manuel Novoa III cad53642003-03-19 09:13:01 +0000347 bb_perror_msg_and_die("%s", device_name);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000348 if (!S_ISBLK(statbuf.st_mode))
Erik Andersene49d5ec2000-02-08 19:58:47 +0000349 check = 0;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000350 else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340)
Manuel Novoa III cad53642003-03-19 09:13:01 +0000351 bb_error_msg_and_die("Will not try to make swapdevice on '%s'", device_name);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000352
353#ifdef __sparc__
354 if (!force && version == 0) {
355 /* Don't overwrite partition table unless forced */
Erik Andersene49d5ec2000-02-08 19:58:47 +0000356 unsigned char *buffer = (unsigned char *) signature_page;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000357 unsigned short *q, sum;
358
359 if (read(DEV, buffer, 512) != 512)
Manuel Novoa III cad53642003-03-19 09:13:01 +0000360 bb_error_msg_and_die("fatal: first page unreadable");
Eric Andersene77ae3a1999-10-19 20:03:34 +0000361 if (buffer[508] == 0xDA && buffer[509] == 0xBE) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000362 q = (unsigned short *) (buffer + 510);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000363 for (sum = 0; q >= (unsigned short *) buffer;)
364 sum ^= *q--;
365 if (!sum) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000366 bb_error_msg("Device '%s' contains a valid Sun disklabel.\n"
Matt Kraaid537a952000-07-14 01:51:25 +0000367"This probably means creating v0 swap would destroy your partition table\n"
368"No swap created. If you really want to create swap v0 on that device, use\n"
Matt Kraaidd19c692001-01-31 19:00:21 +0000369"the -f option to force it.", device_name);
Matt Kraai3e856ce2000-12-01 02:55:13 +0000370 return EXIT_FAILURE;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000371 }
372 }
373 }
374#endif
375
376 if (version == 0 || check)
377 check_blocks();
Erik Andersene49d5ec2000-02-08 19:58:47 +0000378 if (version == 0 && !bit_test_and_clear(signature_page, 0))
Manuel Novoa III cad53642003-03-19 09:13:01 +0000379 bb_error_msg_and_die("fatal: first page unreadable");
Eric Andersene77ae3a1999-10-19 20:03:34 +0000380 if (version == 1) {
Bernhard Reutner-Fischer56dd0bf2006-03-29 17:32:24 +0000381 p->swap_version = version;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000382 p->last_page = PAGES - 1;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000383 p->nr_badpages = badpages;
384 }
385
386 goodpages = PAGES - badpages - 1;
387 if (goodpages <= 0)
Manuel Novoa III cad53642003-03-19 09:13:01 +0000388 bb_error_msg_and_die("Unable to set up swap-space: unreadable");
Eric Andersene77ae3a1999-10-19 20:03:34 +0000389 printf("Setting up swapspace version %d, size = %ld bytes\n",
Erik Andersene49d5ec2000-02-08 19:58:47 +0000390 version, (long) (goodpages * pagesize));
Eric Andersene77ae3a1999-10-19 20:03:34 +0000391 write_signature((version == 0) ? "SWAP-SPACE" : "SWAPSPACE2");
392
Bernhard Reutner-Fischer56dd0bf2006-03-29 17:32:24 +0000393 sz = ((version == 0) ? 0 : 1024); /* offset */
394 if (lseek(DEV, sz, SEEK_SET) != sz)
Manuel Novoa III cad53642003-03-19 09:13:01 +0000395 bb_error_msg_and_die("unable to rewind swap-device");
Bernhard Reutner-Fischer56dd0bf2006-03-29 17:32:24 +0000396 goodpages = pagesize - sz; /* cache substraction */
397 if (write(DEV, (char *) signature_page + sz, goodpages)
398 != goodpages)
Manuel Novoa III cad53642003-03-19 09:13:01 +0000399 bb_error_msg_and_die("unable to write signature page");
Eric Andersene77ae3a1999-10-19 20:03:34 +0000400
401 /*
402 * A subsequent swapon() will fail if the signature
403 * is not actually on disk. (This is a kernel bug.)
404 */
405 if (fsync(DEV))
Manuel Novoa III cad53642003-03-19 09:13:01 +0000406 bb_error_msg_and_die("fsync failed");
Bernhard Reutner-Fischer56dd0bf2006-03-29 17:32:24 +0000407 if (ENABLE_FEATURE_CLEAN_UP) {
408 close(DEV);
409 free(signature_page);
410 }
Matt Kraai3e856ce2000-12-01 02:55:13 +0000411 return EXIT_SUCCESS;
Eric Andersencc8ed391999-10-05 16:24:54 +0000412}