blob: 5a33945c838f7b1b76ed6c571b483503260ecdfd [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 Andersene77ae3a1999-10-19 20:03:34 +000038#include "internal.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>
Eric Andersencc8ed391999-10-05 16:24:54 +000046#include <sys/stat.h>
Erik Andersene49d5ec2000-02-08 19:58:47 +000047#include <asm/page.h> /* for PAGE_SIZE and PAGE_SHIFT */
Eric Andersene77ae3a1999-10-19 20:03:34 +000048 /* we also get PAGE_SIZE via getpagesize() */
Eric Andersencc8ed391999-10-05 16:24:54 +000049
Eric Andersencc8ed391999-10-05 16:24:54 +000050
Erik Andersene49d5ec2000-02-08 19:58:47 +000051static const char mkswap_usage[] =
Erik Andersen7ab9c7e2000-05-12 19:41:47 +000052 "mkswap [-c] [-v0|-v1] device [block-count]\n"
53#ifndef BB_FEATURE_TRIVIAL_HELP
54 "\nPrepare a disk partition to be used as a swap partition.\n\n"
Erik Andersene49d5ec2000-02-08 19:58:47 +000055 "Options:\n" "\t-c\t\tCheck for read-ability.\n"
56 "\t-v0\t\tMake version 0 swap [max 128 Megs].\n"
57 "\t-v1\t\tMake version 1 swap [big!] (default for kernels > 2.1.117).\n"
58
Erik Andersen7ab9c7e2000-05-12 19:41:47 +000059 "\tblock-count\tNumber of block to use (default is entire partition).\n"
60#endif
61 ;
Eric Andersene77ae3a1999-10-19 20:03:34 +000062
63
64#ifndef _IO
65/* pre-1.3.45 */
66#define BLKGETSIZE 0x1260
67#else
68/* same on i386, m68k, arm; different on alpha, mips, sparc, ppc */
69#define BLKGETSIZE _IO(0x12,96)
Eric Andersencc8ed391999-10-05 16:24:54 +000070#endif
71
Erik Andersene49d5ec2000-02-08 19:58:47 +000072static char *device_name = NULL;
Eric Andersencc8ed391999-10-05 16:24:54 +000073static int DEV = -1;
74static long PAGES = 0;
Eric Andersene77ae3a1999-10-19 20:03:34 +000075static int check = 0;
Eric Andersencc8ed391999-10-05 16:24:54 +000076static int badpages = 0;
Eric Andersene77ae3a1999-10-19 20:03:34 +000077static int version = -1;
Eric Andersencc8ed391999-10-05 16:24:54 +000078
Eric Andersene77ae3a1999-10-19 20:03:34 +000079#define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
Eric Andersencc8ed391999-10-05 16:24:54 +000080
Erik Andersene49d5ec2000-02-08 19:58:47 +000081static int linux_version_code(void)
82{
Eric Andersene77ae3a1999-10-19 20:03:34 +000083 struct utsname my_utsname;
84 int p, q, r;
85
86 if (uname(&my_utsname) == 0) {
87 p = atoi(strtok(my_utsname.release, "."));
88 q = atoi(strtok(NULL, "."));
89 r = atoi(strtok(NULL, "."));
Erik Andersene49d5ec2000-02-08 19:58:47 +000090 return MAKE_VERSION(p, q, r);
Eric Andersene77ae3a1999-10-19 20:03:34 +000091 }
92 return 0;
93}
94
95/*
96 * The definition of the union swap_header uses the constant PAGE_SIZE.
97 * Unfortunately, on some architectures this depends on the hardware model,
98 * and can only be found at run time -- we use getpagesize().
99 */
100
101static int pagesize;
102static int *signature_page;
103
104struct swap_header_v1 {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000105 char bootbits[1024]; /* Space for disklabel etc. */
Eric Andersene77ae3a1999-10-19 20:03:34 +0000106 unsigned int version;
107 unsigned int last_page;
108 unsigned int nr_badpages;
109 unsigned int padding[125];
110 unsigned int badpages[1];
111} *p;
112
Erik Andersene49d5ec2000-02-08 19:58:47 +0000113static void init_signature_page()
114{
Eric Andersene77ae3a1999-10-19 20:03:34 +0000115 pagesize = getpagesize();
116
117#ifdef PAGE_SIZE
118 if (pagesize != PAGE_SIZE)
Matt Kraaid537a952000-07-14 01:51:25 +0000119 errorMsg("Assuming pages of size %d\n", pagesize);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000120#endif
Erik Andersen0d068a22000-03-21 22:32:57 +0000121 signature_page = (int *) xmalloc(pagesize);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000122 memset(signature_page, 0, pagesize);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000123 p = (struct swap_header_v1 *) signature_page;
124}
125
Erik Andersene49d5ec2000-02-08 19:58:47 +0000126static void write_signature(char *sig)
127{
Eric Andersene77ae3a1999-10-19 20:03:34 +0000128 char *sp = (char *) signature_page;
129
Erik Andersene49d5ec2000-02-08 19:58:47 +0000130 strncpy(sp + pagesize - 10, sig, 10);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000131}
132
133#define V0_MAX_PAGES (8 * (pagesize - 10))
134/* Before 2.2.0pre9 */
135#define V1_OLD_MAX_PAGES ((0x7fffffff / pagesize) - 1)
136/* Since 2.2.0pre9:
137 error if nr of pages >= SWP_OFFSET(SWP_ENTRY(0,~0UL))
138 with variations on
139 #define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8))
140 #define SWP_OFFSET(entry) ((entry) >> 8)
141 on the various architectures. Below the result - yuk.
142
143 Machine pagesize SWP_ENTRY SWP_OFFSET bound+1 oldbound+2
144 i386 2^12 o<<8 e>>8 1<<24 1<<19
145 mips 2^12 o<<15 e>>15 1<<17 1<<19
146 alpha 2^13 o<<40 e>>40 1<<24 1<<18
147 m68k 2^12 o<<12 e>>12 1<<20 1<<19
148 sparc 2^{12,13} (o&0x3ffff)<<9 (e>>9)&0x3ffff 1<<18 1<<{19,18}
149 sparc64 2^13 o<<13 e>>13 1<<51 1<<18
150 ppc 2^12 o<<8 e>>8 1<<24 1<<19
151 armo 2^{13,14,15} o<<8 e>>8 1<<24 1<<{18,17,16}
152 armv 2^12 o<<9 e>>9 1<<23 1<<19
153
154 assuming that longs have 64 bits on alpha and sparc64 and 32 bits elsewhere.
155
156 The bad part is that we need to know this since the kernel will
157 refuse a swap space if it is too large.
158*/
159/* patch from jj - why does this differ from the above? */
160#if defined(__alpha__)
161#define V1_MAX_PAGES ((1 << 24) - 1)
162#elif defined(__mips__)
163#define V1_MAX_PAGES ((1 << 17) - 1)
164#elif defined(__sparc_v9__)
165#define V1_MAX_PAGES ((3 << 29) - 1)
166#elif defined(__sparc__)
167#define V1_MAX_PAGES (pagesize == 8192 ? ((3 << 29) - 1) : ((1 << 18) - 1))
168#else
169#define V1_MAX_PAGES V1_OLD_MAX_PAGES
170#endif
171/* man page now says:
172The maximum useful size of a swap area now depends on the architecture.
173It is roughly 2GB on i386, PPC, m68k, ARM, 1GB on sparc, 512MB on mips,
174128GB on alpha and 3TB on sparc64.
175*/
176
177#define MAX_BADPAGES ((pagesize-1024-128*sizeof(int)-10)/sizeof(int))
178
Erik Andersene49d5ec2000-02-08 19:58:47 +0000179static void bit_set(unsigned int *addr, unsigned int nr)
Eric Andersencc8ed391999-10-05 16:24:54 +0000180{
181 unsigned int r, m;
182
183 addr += nr / (8 * sizeof(int));
Erik Andersene49d5ec2000-02-08 19:58:47 +0000184
Eric Andersencc8ed391999-10-05 16:24:54 +0000185 r = *addr;
186 m = 1 << (nr & (8 * sizeof(int) - 1));
Erik Andersene49d5ec2000-02-08 19:58:47 +0000187
Eric Andersencc8ed391999-10-05 16:24:54 +0000188 *addr = r | m;
Eric Andersencc8ed391999-10-05 16:24:54 +0000189}
190
Erik Andersene49d5ec2000-02-08 19:58:47 +0000191static int bit_test_and_clear(unsigned int *addr, unsigned int nr)
Eric Andersencc8ed391999-10-05 16:24:54 +0000192{
193 unsigned int r, m;
194
195 addr += nr / (8 * sizeof(int));
Erik Andersene49d5ec2000-02-08 19:58:47 +0000196
Eric Andersencc8ed391999-10-05 16:24:54 +0000197 r = *addr;
198 m = 1 << (nr & (8 * sizeof(int) - 1));
Erik Andersene49d5ec2000-02-08 19:58:47 +0000199
Eric Andersencc8ed391999-10-05 16:24:54 +0000200 *addr = r & ~m;
201 return (r & m) != 0;
202}
203
Eric Andersene77ae3a1999-10-19 20:03:34 +0000204
Erik Andersene49d5ec2000-02-08 19:58:47 +0000205void die(const char *str)
206{
Matt Kraaid537a952000-07-14 01:51:25 +0000207 errorMsg("%s\n", str);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000208 exit(FALSE);
Eric Andersencc8ed391999-10-05 16:24:54 +0000209}
210
Erik Andersene49d5ec2000-02-08 19:58:47 +0000211void page_ok(int page)
212{
213 if (version == 0)
Eric Andersene77ae3a1999-10-19 20:03:34 +0000214 bit_set(signature_page, page);
215}
Eric Andersencc8ed391999-10-05 16:24:54 +0000216
Erik Andersene49d5ec2000-02-08 19:58:47 +0000217void page_bad(int page)
218{
Eric Andersene77ae3a1999-10-19 20:03:34 +0000219 if (version == 0)
220 bit_test_and_clear(signature_page, page);
221 else {
222 if (badpages == MAX_BADPAGES)
223 die("too many bad pages");
224 p->badpages[badpages] = page;
225 }
226 badpages++;
227}
228
Erik Andersene49d5ec2000-02-08 19:58:47 +0000229void check_blocks(void)
230{
Eric Andersencc8ed391999-10-05 16:24:54 +0000231 unsigned int current_page;
232 int do_seek = 1;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000233 char *buffer;
Eric Andersencc8ed391999-10-05 16:24:54 +0000234
Erik Andersen0d068a22000-03-21 22:32:57 +0000235 buffer = xmalloc(pagesize);
Eric Andersencc8ed391999-10-05 16:24:54 +0000236 current_page = 0;
237 while (current_page < PAGES) {
Eric Andersene77ae3a1999-10-19 20:03:34 +0000238 if (!check) {
239 page_ok(current_page++);
Eric Andersencc8ed391999-10-05 16:24:54 +0000240 continue;
Eric Andersencc8ed391999-10-05 16:24:54 +0000241 }
Erik Andersene49d5ec2000-02-08 19:58:47 +0000242 if (do_seek && lseek(DEV, current_page * pagesize, SEEK_SET) !=
243 current_page * pagesize)
Eric Andersencc8ed391999-10-05 16:24:54 +0000244 die("seek failed in check_blocks");
Eric Andersene77ae3a1999-10-19 20:03:34 +0000245 if ((do_seek = (pagesize != read(DEV, buffer, pagesize)))) {
246 page_bad(current_page++);
Eric Andersencc8ed391999-10-05 16:24:54 +0000247 continue;
248 }
Eric Andersene77ae3a1999-10-19 20:03:34 +0000249 page_ok(current_page++);
Eric Andersencc8ed391999-10-05 16:24:54 +0000250 }
Eric Andersene77ae3a1999-10-19 20:03:34 +0000251 if (badpages == 1)
252 printf("one bad page\n");
253 else if (badpages > 1)
254 printf("%d bad pages\n", badpages);
Eric Andersencc8ed391999-10-05 16:24:54 +0000255}
256
Erik Andersene49d5ec2000-02-08 19:58:47 +0000257static long valid_offset(int fd, int offset)
Eric Andersencc8ed391999-10-05 16:24:54 +0000258{
259 char ch;
260
Erik Andersene49d5ec2000-02-08 19:58:47 +0000261 if (lseek(fd, offset, 0) < 0)
Eric Andersencc8ed391999-10-05 16:24:54 +0000262 return 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000263 if (read(fd, &ch, 1) < 1)
Eric Andersencc8ed391999-10-05 16:24:54 +0000264 return 0;
265 return 1;
266}
267
Erik Andersene49d5ec2000-02-08 19:58:47 +0000268static int find_size(int fd)
Eric Andersencc8ed391999-10-05 16:24:54 +0000269{
Eric Andersene77ae3a1999-10-19 20:03:34 +0000270 unsigned int high, low;
Eric Andersencc8ed391999-10-05 16:24:54 +0000271
272 low = 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000273 for (high = 1; high > 0 && valid_offset(fd, high); high *= 2)
Eric Andersencc8ed391999-10-05 16:24:54 +0000274 low = high;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000275 while (low < high - 1) {
Eric Andersencc8ed391999-10-05 16:24:54 +0000276 const int mid = (low + high) / 2;
277
Erik Andersene49d5ec2000-02-08 19:58:47 +0000278 if (valid_offset(fd, mid))
Eric Andersencc8ed391999-10-05 16:24:54 +0000279 low = mid;
280 else
281 high = mid;
282 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000283 return (low + 1);
284}
285
Eric Andersene77ae3a1999-10-19 20:03:34 +0000286/* return size in pages, to avoid integer overflow */
Erik Andersene49d5ec2000-02-08 19:58:47 +0000287static long get_size(const char *file)
Eric Andersencc8ed391999-10-05 16:24:54 +0000288{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000289 int fd;
290 long size;
Eric Andersencc8ed391999-10-05 16:24:54 +0000291
Eric Andersene77ae3a1999-10-19 20:03:34 +0000292 fd = open(file, O_RDONLY);
Eric Andersencc8ed391999-10-05 16:24:54 +0000293 if (fd < 0) {
294 perror(file);
295 exit(1);
296 }
297 if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000298 int sectors_per_page = pagesize / 512;
299
Eric Andersene77ae3a1999-10-19 20:03:34 +0000300 size /= sectors_per_page;
301 } else {
302 size = find_size(fd) / pagesize;
Eric Andersencc8ed391999-10-05 16:24:54 +0000303 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000304 close(fd);
305 return size;
306}
307
Erik Andersene49d5ec2000-02-08 19:58:47 +0000308int mkswap_main(int argc, char **argv)
Eric Andersencc8ed391999-10-05 16:24:54 +0000309{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000310 char *tmp;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000311 struct stat statbuf;
312 int sz;
313 int maxpages;
314 int goodpages;
315 int offset;
316 int force = 0;
Eric Andersencc8ed391999-10-05 16:24:54 +0000317
Erik Andersene49d5ec2000-02-08 19:58:47 +0000318 init_signature_page(); /* get pagesize */
Eric Andersene77ae3a1999-10-19 20:03:34 +0000319
320 while (argc-- > 1) {
Eric Andersencc8ed391999-10-05 16:24:54 +0000321 argv++;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000322 if (argv[0][0] != '-') {
Eric Andersencc8ed391999-10-05 16:24:54 +0000323 if (device_name) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000324 int blocks_per_page = pagesize / 1024;
325
326 PAGES = strtol(argv[0], &tmp, 0) / blocks_per_page;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000327 if (*tmp)
Erik Andersene49d5ec2000-02-08 19:58:47 +0000328 usage(mkswap_usage);
Eric Andersencc8ed391999-10-05 16:24:54 +0000329 } else
330 device_name = argv[0];
Eric Andersene77ae3a1999-10-19 20:03:34 +0000331 } else {
332 switch (argv[0][1]) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000333 case 'c':
334 check = 1;
335 break;
336 case 'f':
337 force = 1;
338 break;
339 case 'v':
340 version = atoi(argv[0] + 2);
341 break;
342 default:
343 usage(mkswap_usage);
Eric Andersencc8ed391999-10-05 16:24:54 +0000344 }
Eric Andersene77ae3a1999-10-19 20:03:34 +0000345 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000346 }
Eric Andersene77ae3a1999-10-19 20:03:34 +0000347 if (!device_name) {
Matt Kraaid537a952000-07-14 01:51:25 +0000348 errorMsg("error: Nowhere to set up swap on?\n");
Erik Andersene49d5ec2000-02-08 19:58:47 +0000349 usage(mkswap_usage);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000350 }
351 sz = get_size(device_name);
352 if (!PAGES) {
353 PAGES = sz;
354 } else if (PAGES > sz && !force) {
Matt Kraaid537a952000-07-14 01:51:25 +0000355 errorMsg("error: size %ld is larger than device size %d\n",
Erik Andersene49d5ec2000-02-08 19:58:47 +0000356 PAGES * (pagesize / 1024), sz * (pagesize / 1024));
357 exit(FALSE);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000358 }
359
360 if (version == -1) {
361 if (PAGES <= V0_MAX_PAGES)
362 version = 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000363 else if (linux_version_code() < MAKE_VERSION(2, 1, 117))
Eric Andersene77ae3a1999-10-19 20:03:34 +0000364 version = 0;
365 else if (pagesize < 2048)
366 version = 0;
367 else
368 version = 1;
369 }
370 if (version != 0 && version != 1) {
Matt Kraaid537a952000-07-14 01:51:25 +0000371 errorMsg("error: unknown version %d\n", version);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000372 usage(mkswap_usage);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000373 }
374 if (PAGES < 10) {
Matt Kraaid537a952000-07-14 01:51:25 +0000375 errorMsg("error: swap area needs to be at least %ldkB\n",
376 (long) (10 * pagesize / 1024));
Erik Andersene49d5ec2000-02-08 19:58:47 +0000377 usage(mkswap_usage);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000378 }
379#if 0
380 maxpages = ((version == 0) ? V0_MAX_PAGES : V1_MAX_PAGES);
381#else
382 if (!version)
383 maxpages = V0_MAX_PAGES;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000384 else if (linux_version_code() >= MAKE_VERSION(2, 2, 1))
Eric Andersene77ae3a1999-10-19 20:03:34 +0000385 maxpages = V1_MAX_PAGES;
386 else {
387 maxpages = V1_OLD_MAX_PAGES;
388 if (maxpages > V1_MAX_PAGES)
389 maxpages = V1_MAX_PAGES;
390 }
391#endif
392 if (PAGES > maxpages) {
393 PAGES = maxpages;
Matt Kraaid537a952000-07-14 01:51:25 +0000394 errorMsg("warning: truncating swap area to %ldkB\n",
395 PAGES * pagesize / 1024);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000396 }
397
Erik Andersene49d5ec2000-02-08 19:58:47 +0000398 DEV = open(device_name, O_RDWR);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000399 if (DEV < 0 || fstat(DEV, &statbuf) < 0) {
400 perror(device_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000401 exit(FALSE);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000402 }
403 if (!S_ISBLK(statbuf.st_mode))
Erik Andersene49d5ec2000-02-08 19:58:47 +0000404 check = 0;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000405 else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340)
406 die("Will not try to make swapdevice on '%s'");
407
408#ifdef __sparc__
409 if (!force && version == 0) {
410 /* Don't overwrite partition table unless forced */
Erik Andersene49d5ec2000-02-08 19:58:47 +0000411 unsigned char *buffer = (unsigned char *) signature_page;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000412 unsigned short *q, sum;
413
414 if (read(DEV, buffer, 512) != 512)
415 die("fatal: first page unreadable");
416 if (buffer[508] == 0xDA && buffer[509] == 0xBE) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000417 q = (unsigned short *) (buffer + 510);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000418 for (sum = 0; q >= (unsigned short *) buffer;)
419 sum ^= *q--;
420 if (!sum) {
Matt Kraaid537a952000-07-14 01:51:25 +0000421 errorMsg("Device '%s' contains a valid Sun disklabel.\n"
422"This probably means creating v0 swap would destroy your partition table\n"
423"No swap created. If you really want to create swap v0 on that device, use\n"
424"the -f option to force it.\n", device_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000425 exit(FALSE);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000426 }
427 }
428 }
429#endif
430
431 if (version == 0 || check)
432 check_blocks();
Erik Andersene49d5ec2000-02-08 19:58:47 +0000433 if (version == 0 && !bit_test_and_clear(signature_page, 0))
Eric Andersene77ae3a1999-10-19 20:03:34 +0000434 die("fatal: first page unreadable");
435 if (version == 1) {
436 p->version = version;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000437 p->last_page = PAGES - 1;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000438 p->nr_badpages = badpages;
439 }
440
441 goodpages = PAGES - badpages - 1;
442 if (goodpages <= 0)
443 die("Unable to set up swap-space: unreadable");
444 printf("Setting up swapspace version %d, size = %ld bytes\n",
Erik Andersene49d5ec2000-02-08 19:58:47 +0000445 version, (long) (goodpages * pagesize));
Eric Andersene77ae3a1999-10-19 20:03:34 +0000446 write_signature((version == 0) ? "SWAP-SPACE" : "SWAPSPACE2");
447
448 offset = ((version == 0) ? 0 : 1024);
449 if (lseek(DEV, offset, SEEK_SET) != offset)
450 die("unable to rewind swap-device");
Erik Andersene49d5ec2000-02-08 19:58:47 +0000451 if (write(DEV, (char *) signature_page + offset, pagesize - offset)
452 != pagesize - offset)
Eric Andersene77ae3a1999-10-19 20:03:34 +0000453 die("unable to write signature page");
454
455 /*
456 * A subsequent swapon() will fail if the signature
457 * is not actually on disk. (This is a kernel bug.)
458 */
459 if (fsync(DEV))
Erik Andersene49d5ec2000-02-08 19:58:47 +0000460 die("fsync failed");
Eric Andersenb6106152000-06-19 17:25:40 +0000461 return(TRUE);
Eric Andersencc8ed391999-10-05 16:24:54 +0000462}