blob: 3a396894ceed7688ea1224ce34d5d42f65a24159 [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
33 * Erik Andersen <andersee@debian.org>. I ripped out Native Language
34 * Support, made some stuff smaller, and fitted for life in busybox.
35 *
Eric Andersencc8ed391999-10-05 16:24:54 +000036 */
37
Eric Andersen3570a342000-09-25 21:45:58 +000038#include "busybox.h"
Eric Andersencc8ed391999-10-05 16:24:54 +000039#include <stdio.h>
40#include <unistd.h>
41#include <string.h>
42#include <fcntl.h>
43#include <stdlib.h>
Erik Andersene49d5ec2000-02-08 19:58:47 +000044#include <sys/ioctl.h> /* for _IO */
Eric Andersene77ae3a1999-10-19 20:03:34 +000045#include <sys/utsname.h>
Erik Andersene49d5ec2000-02-08 19:58:47 +000046#include <asm/page.h> /* for PAGE_SIZE and PAGE_SHIFT */
Eric Andersene77ae3a1999-10-19 20:03:34 +000047 /* we also get PAGE_SIZE via getpagesize() */
Eric Andersencc8ed391999-10-05 16:24:54 +000048
Eric Andersene77ae3a1999-10-19 20:03:34 +000049#ifndef _IO
50/* pre-1.3.45 */
51#define BLKGETSIZE 0x1260
52#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;
73static int *signature_page;
74
75struct 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
Erik Andersene49d5ec2000-02-08 19:58:47 +000084static void init_signature_page()
85{
Eric Andersene77ae3a1999-10-19 20:03:34 +000086 pagesize = getpagesize();
87
88#ifdef PAGE_SIZE
89 if (pagesize != PAGE_SIZE)
Mark Whitleyf57c9442000-12-07 19:56:48 +000090 error_msg("Assuming pages of size %d\n", pagesize);
Eric Andersene77ae3a1999-10-19 20:03:34 +000091#endif
Erik Andersen0d068a22000-03-21 22:32:57 +000092 signature_page = (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
Erik Andersene49d5ec2000-02-08 19:58:47 +000097static void write_signature(char *sig)
98{
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
Erik Andersene49d5ec2000-02-08 19:58:47 +0000150static 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
Erik Andersene49d5ec2000-02-08 19:58:47 +0000176void die(const char *str)
177{
Mark Whitleyf57c9442000-12-07 19:56:48 +0000178 error_msg("%s\n", str);
Matt Kraai3e856ce2000-12-01 02:55:13 +0000179 exit(EXIT_FAILURE);
Eric Andersencc8ed391999-10-05 16:24:54 +0000180}
181
Erik Andersene49d5ec2000-02-08 19:58:47 +0000182void page_ok(int page)
183{
184 if (version == 0)
Eric Andersene77ae3a1999-10-19 20:03:34 +0000185 bit_set(signature_page, page);
186}
Eric Andersencc8ed391999-10-05 16:24:54 +0000187
Erik Andersene49d5ec2000-02-08 19:58:47 +0000188void page_bad(int page)
189{
Eric Andersene77ae3a1999-10-19 20:03:34 +0000190 if (version == 0)
191 bit_test_and_clear(signature_page, page);
192 else {
193 if (badpages == MAX_BADPAGES)
194 die("too many bad pages");
195 p->badpages[badpages] = page;
196 }
197 badpages++;
198}
199
Erik Andersene49d5ec2000-02-08 19:58:47 +0000200void check_blocks(void)
201{
Eric Andersencc8ed391999-10-05 16:24:54 +0000202 unsigned int current_page;
203 int do_seek = 1;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000204 char *buffer;
Eric Andersencc8ed391999-10-05 16:24:54 +0000205
Erik Andersen0d068a22000-03-21 22:32:57 +0000206 buffer = xmalloc(pagesize);
Eric Andersencc8ed391999-10-05 16:24:54 +0000207 current_page = 0;
208 while (current_page < PAGES) {
Eric Andersene77ae3a1999-10-19 20:03:34 +0000209 if (!check) {
210 page_ok(current_page++);
Eric Andersencc8ed391999-10-05 16:24:54 +0000211 continue;
Eric Andersencc8ed391999-10-05 16:24:54 +0000212 }
Erik Andersene49d5ec2000-02-08 19:58:47 +0000213 if (do_seek && lseek(DEV, current_page * pagesize, SEEK_SET) !=
214 current_page * pagesize)
Eric Andersencc8ed391999-10-05 16:24:54 +0000215 die("seek failed in check_blocks");
Eric Andersene77ae3a1999-10-19 20:03:34 +0000216 if ((do_seek = (pagesize != read(DEV, buffer, pagesize)))) {
217 page_bad(current_page++);
Eric Andersencc8ed391999-10-05 16:24:54 +0000218 continue;
219 }
Eric Andersene77ae3a1999-10-19 20:03:34 +0000220 page_ok(current_page++);
Eric Andersencc8ed391999-10-05 16:24:54 +0000221 }
Eric Andersene77ae3a1999-10-19 20:03:34 +0000222 if (badpages == 1)
223 printf("one bad page\n");
224 else if (badpages > 1)
225 printf("%d bad pages\n", badpages);
Eric Andersencc8ed391999-10-05 16:24:54 +0000226}
227
Erik Andersene49d5ec2000-02-08 19:58:47 +0000228static long valid_offset(int fd, int offset)
Eric Andersencc8ed391999-10-05 16:24:54 +0000229{
230 char ch;
231
Erik Andersene49d5ec2000-02-08 19:58:47 +0000232 if (lseek(fd, offset, 0) < 0)
Eric Andersencc8ed391999-10-05 16:24:54 +0000233 return 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000234 if (read(fd, &ch, 1) < 1)
Eric Andersencc8ed391999-10-05 16:24:54 +0000235 return 0;
236 return 1;
237}
238
Erik Andersene49d5ec2000-02-08 19:58:47 +0000239static int find_size(int fd)
Eric Andersencc8ed391999-10-05 16:24:54 +0000240{
Eric Andersene77ae3a1999-10-19 20:03:34 +0000241 unsigned int high, low;
Eric Andersencc8ed391999-10-05 16:24:54 +0000242
243 low = 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000244 for (high = 1; high > 0 && valid_offset(fd, high); high *= 2)
Eric Andersencc8ed391999-10-05 16:24:54 +0000245 low = high;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000246 while (low < high - 1) {
Eric Andersencc8ed391999-10-05 16:24:54 +0000247 const int mid = (low + high) / 2;
248
Erik Andersene49d5ec2000-02-08 19:58:47 +0000249 if (valid_offset(fd, mid))
Eric Andersencc8ed391999-10-05 16:24:54 +0000250 low = mid;
251 else
252 high = mid;
253 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000254 return (low + 1);
255}
256
Eric Andersene77ae3a1999-10-19 20:03:34 +0000257/* return size in pages, to avoid integer overflow */
Erik Andersene49d5ec2000-02-08 19:58:47 +0000258static long get_size(const char *file)
Eric Andersencc8ed391999-10-05 16:24:54 +0000259{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000260 int fd;
261 long size;
Eric Andersencc8ed391999-10-05 16:24:54 +0000262
Eric Andersene77ae3a1999-10-19 20:03:34 +0000263 fd = open(file, O_RDONLY);
Eric Andersencc8ed391999-10-05 16:24:54 +0000264 if (fd < 0) {
265 perror(file);
266 exit(1);
267 }
268 if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000269 int sectors_per_page = pagesize / 512;
270
Eric Andersene77ae3a1999-10-19 20:03:34 +0000271 size /= sectors_per_page;
272 } else {
273 size = find_size(fd) / pagesize;
Eric Andersencc8ed391999-10-05 16:24:54 +0000274 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000275 close(fd);
276 return size;
277}
278
Erik Andersene49d5ec2000-02-08 19:58:47 +0000279int mkswap_main(int argc, char **argv)
Eric Andersencc8ed391999-10-05 16:24:54 +0000280{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000281 char *tmp;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000282 struct stat statbuf;
283 int sz;
284 int maxpages;
285 int goodpages;
286 int offset;
287 int force = 0;
Eric Andersencc8ed391999-10-05 16:24:54 +0000288
Erik Andersene49d5ec2000-02-08 19:58:47 +0000289 init_signature_page(); /* get pagesize */
Eric Andersene77ae3a1999-10-19 20:03:34 +0000290
291 while (argc-- > 1) {
Eric Andersencc8ed391999-10-05 16:24:54 +0000292 argv++;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000293 if (argv[0][0] != '-') {
Eric Andersencc8ed391999-10-05 16:24:54 +0000294 if (device_name) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000295 int blocks_per_page = pagesize / 1024;
296
297 PAGES = strtol(argv[0], &tmp, 0) / blocks_per_page;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000298 if (*tmp)
Erik Andersene49d5ec2000-02-08 19:58:47 +0000299 usage(mkswap_usage);
Eric Andersencc8ed391999-10-05 16:24:54 +0000300 } else
301 device_name = argv[0];
Eric Andersene77ae3a1999-10-19 20:03:34 +0000302 } else {
303 switch (argv[0][1]) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000304 case 'c':
305 check = 1;
306 break;
307 case 'f':
308 force = 1;
309 break;
310 case 'v':
311 version = atoi(argv[0] + 2);
312 break;
313 default:
314 usage(mkswap_usage);
Eric Andersencc8ed391999-10-05 16:24:54 +0000315 }
Eric Andersene77ae3a1999-10-19 20:03:34 +0000316 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000317 }
Eric Andersene77ae3a1999-10-19 20:03:34 +0000318 if (!device_name) {
Mark Whitleyf57c9442000-12-07 19:56:48 +0000319 error_msg("error: Nowhere to set up swap on?\n");
Erik Andersene49d5ec2000-02-08 19:58:47 +0000320 usage(mkswap_usage);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000321 }
322 sz = get_size(device_name);
323 if (!PAGES) {
324 PAGES = sz;
325 } else if (PAGES > sz && !force) {
Mark Whitleyf57c9442000-12-07 19:56:48 +0000326 error_msg("error: size %ld is larger than device size %d\n",
Erik Andersene49d5ec2000-02-08 19:58:47 +0000327 PAGES * (pagesize / 1024), sz * (pagesize / 1024));
Matt Kraai3e856ce2000-12-01 02:55:13 +0000328 return EXIT_FAILURE;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000329 }
330
331 if (version == -1) {
332 if (PAGES <= V0_MAX_PAGES)
333 version = 0;
Eric Andersenef936da2000-10-30 17:22:04 +0000334 else if (get_kernel_revision() < MAKE_VERSION(2, 1, 117))
Eric Andersene77ae3a1999-10-19 20:03:34 +0000335 version = 0;
336 else if (pagesize < 2048)
337 version = 0;
338 else
339 version = 1;
340 }
341 if (version != 0 && version != 1) {
Mark Whitleyf57c9442000-12-07 19:56:48 +0000342 error_msg("error: unknown version %d\n", version);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000343 usage(mkswap_usage);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000344 }
345 if (PAGES < 10) {
Mark Whitleyf57c9442000-12-07 19:56:48 +0000346 error_msg("error: swap area needs to be at least %ldkB\n",
Matt Kraaid537a952000-07-14 01:51:25 +0000347 (long) (10 * pagesize / 1024));
Erik Andersene49d5ec2000-02-08 19:58:47 +0000348 usage(mkswap_usage);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000349 }
350#if 0
351 maxpages = ((version == 0) ? V0_MAX_PAGES : V1_MAX_PAGES);
352#else
353 if (!version)
354 maxpages = V0_MAX_PAGES;
Eric Andersenef936da2000-10-30 17:22:04 +0000355 else if (get_kernel_revision() >= MAKE_VERSION(2, 2, 1))
Eric Andersene77ae3a1999-10-19 20:03:34 +0000356 maxpages = V1_MAX_PAGES;
357 else {
358 maxpages = V1_OLD_MAX_PAGES;
359 if (maxpages > V1_MAX_PAGES)
360 maxpages = V1_MAX_PAGES;
361 }
362#endif
363 if (PAGES > maxpages) {
364 PAGES = maxpages;
Mark Whitleyf57c9442000-12-07 19:56:48 +0000365 error_msg("warning: truncating swap area to %ldkB\n",
Matt Kraaid537a952000-07-14 01:51:25 +0000366 PAGES * pagesize / 1024);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000367 }
368
Erik Andersene49d5ec2000-02-08 19:58:47 +0000369 DEV = open(device_name, O_RDWR);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000370 if (DEV < 0 || fstat(DEV, &statbuf) < 0) {
371 perror(device_name);
Matt Kraai3e856ce2000-12-01 02:55:13 +0000372 return EXIT_FAILURE;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000373 }
374 if (!S_ISBLK(statbuf.st_mode))
Erik Andersene49d5ec2000-02-08 19:58:47 +0000375 check = 0;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000376 else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340)
377 die("Will not try to make swapdevice on '%s'");
378
379#ifdef __sparc__
380 if (!force && version == 0) {
381 /* Don't overwrite partition table unless forced */
Erik Andersene49d5ec2000-02-08 19:58:47 +0000382 unsigned char *buffer = (unsigned char *) signature_page;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000383 unsigned short *q, sum;
384
385 if (read(DEV, buffer, 512) != 512)
386 die("fatal: first page unreadable");
387 if (buffer[508] == 0xDA && buffer[509] == 0xBE) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000388 q = (unsigned short *) (buffer + 510);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000389 for (sum = 0; q >= (unsigned short *) buffer;)
390 sum ^= *q--;
391 if (!sum) {
Mark Whitleyf57c9442000-12-07 19:56:48 +0000392 error_msg("Device '%s' contains a valid Sun disklabel.\n"
Matt Kraaid537a952000-07-14 01:51:25 +0000393"This probably means creating v0 swap would destroy your partition table\n"
394"No swap created. If you really want to create swap v0 on that device, use\n"
395"the -f option to force it.\n", device_name);
Matt Kraai3e856ce2000-12-01 02:55:13 +0000396 return EXIT_FAILURE;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000397 }
398 }
399 }
400#endif
401
402 if (version == 0 || check)
403 check_blocks();
Erik Andersene49d5ec2000-02-08 19:58:47 +0000404 if (version == 0 && !bit_test_and_clear(signature_page, 0))
Eric Andersene77ae3a1999-10-19 20:03:34 +0000405 die("fatal: first page unreadable");
406 if (version == 1) {
407 p->version = version;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000408 p->last_page = PAGES - 1;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000409 p->nr_badpages = badpages;
410 }
411
412 goodpages = PAGES - badpages - 1;
413 if (goodpages <= 0)
414 die("Unable to set up swap-space: unreadable");
415 printf("Setting up swapspace version %d, size = %ld bytes\n",
Erik Andersene49d5ec2000-02-08 19:58:47 +0000416 version, (long) (goodpages * pagesize));
Eric Andersene77ae3a1999-10-19 20:03:34 +0000417 write_signature((version == 0) ? "SWAP-SPACE" : "SWAPSPACE2");
418
419 offset = ((version == 0) ? 0 : 1024);
420 if (lseek(DEV, offset, SEEK_SET) != offset)
421 die("unable to rewind swap-device");
Erik Andersene49d5ec2000-02-08 19:58:47 +0000422 if (write(DEV, (char *) signature_page + offset, pagesize - offset)
423 != pagesize - offset)
Eric Andersene77ae3a1999-10-19 20:03:34 +0000424 die("unable to write signature page");
425
426 /*
427 * A subsequent swapon() will fail if the signature
428 * is not actually on disk. (This is a kernel bug.)
429 */
430 if (fsync(DEV))
Erik Andersene49d5ec2000-02-08 19:58:47 +0000431 die("fsync failed");
Matt Kraai3e856ce2000-12-01 02:55:13 +0000432 return EXIT_SUCCESS;
Eric Andersencc8ed391999-10-05 16:24:54 +0000433}