blob: 7d76916f03be073d2bc8deb9d379963fb84c7ff3 [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 *program_name = "mkswap";
73static char *device_name = NULL;
Eric Andersencc8ed391999-10-05 16:24:54 +000074static int DEV = -1;
75static long PAGES = 0;
Eric Andersene77ae3a1999-10-19 20:03:34 +000076static int check = 0;
Eric Andersencc8ed391999-10-05 16:24:54 +000077static int badpages = 0;
Eric Andersene77ae3a1999-10-19 20:03:34 +000078static int version = -1;
Eric Andersencc8ed391999-10-05 16:24:54 +000079
Eric Andersene77ae3a1999-10-19 20:03:34 +000080#define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
Eric Andersencc8ed391999-10-05 16:24:54 +000081
Erik Andersene49d5ec2000-02-08 19:58:47 +000082static int linux_version_code(void)
83{
Eric Andersene77ae3a1999-10-19 20:03:34 +000084 struct utsname my_utsname;
85 int p, q, r;
86
87 if (uname(&my_utsname) == 0) {
88 p = atoi(strtok(my_utsname.release, "."));
89 q = atoi(strtok(NULL, "."));
90 r = atoi(strtok(NULL, "."));
Erik Andersene49d5ec2000-02-08 19:58:47 +000091 return MAKE_VERSION(p, q, r);
Eric Andersene77ae3a1999-10-19 20:03:34 +000092 }
93 return 0;
94}
95
96/*
97 * The definition of the union swap_header uses the constant PAGE_SIZE.
98 * Unfortunately, on some architectures this depends on the hardware model,
99 * and can only be found at run time -- we use getpagesize().
100 */
101
102static int pagesize;
103static int *signature_page;
104
105struct swap_header_v1 {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000106 char bootbits[1024]; /* Space for disklabel etc. */
Eric Andersene77ae3a1999-10-19 20:03:34 +0000107 unsigned int version;
108 unsigned int last_page;
109 unsigned int nr_badpages;
110 unsigned int padding[125];
111 unsigned int badpages[1];
112} *p;
113
Erik Andersene49d5ec2000-02-08 19:58:47 +0000114static void init_signature_page()
115{
Eric Andersene77ae3a1999-10-19 20:03:34 +0000116 pagesize = getpagesize();
117
118#ifdef PAGE_SIZE
119 if (pagesize != PAGE_SIZE)
120 fprintf(stderr, "Assuming pages of size %d\n", pagesize);
121#endif
Erik Andersen0d068a22000-03-21 22:32:57 +0000122 signature_page = (int *) xmalloc(pagesize);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000123 memset(signature_page, 0, pagesize);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000124 p = (struct swap_header_v1 *) signature_page;
125}
126
Erik Andersene49d5ec2000-02-08 19:58:47 +0000127static void write_signature(char *sig)
128{
Eric Andersene77ae3a1999-10-19 20:03:34 +0000129 char *sp = (char *) signature_page;
130
Erik Andersene49d5ec2000-02-08 19:58:47 +0000131 strncpy(sp + pagesize - 10, sig, 10);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000132}
133
134#define V0_MAX_PAGES (8 * (pagesize - 10))
135/* Before 2.2.0pre9 */
136#define V1_OLD_MAX_PAGES ((0x7fffffff / pagesize) - 1)
137/* Since 2.2.0pre9:
138 error if nr of pages >= SWP_OFFSET(SWP_ENTRY(0,~0UL))
139 with variations on
140 #define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8))
141 #define SWP_OFFSET(entry) ((entry) >> 8)
142 on the various architectures. Below the result - yuk.
143
144 Machine pagesize SWP_ENTRY SWP_OFFSET bound+1 oldbound+2
145 i386 2^12 o<<8 e>>8 1<<24 1<<19
146 mips 2^12 o<<15 e>>15 1<<17 1<<19
147 alpha 2^13 o<<40 e>>40 1<<24 1<<18
148 m68k 2^12 o<<12 e>>12 1<<20 1<<19
149 sparc 2^{12,13} (o&0x3ffff)<<9 (e>>9)&0x3ffff 1<<18 1<<{19,18}
150 sparc64 2^13 o<<13 e>>13 1<<51 1<<18
151 ppc 2^12 o<<8 e>>8 1<<24 1<<19
152 armo 2^{13,14,15} o<<8 e>>8 1<<24 1<<{18,17,16}
153 armv 2^12 o<<9 e>>9 1<<23 1<<19
154
155 assuming that longs have 64 bits on alpha and sparc64 and 32 bits elsewhere.
156
157 The bad part is that we need to know this since the kernel will
158 refuse a swap space if it is too large.
159*/
160/* patch from jj - why does this differ from the above? */
161#if defined(__alpha__)
162#define V1_MAX_PAGES ((1 << 24) - 1)
163#elif defined(__mips__)
164#define V1_MAX_PAGES ((1 << 17) - 1)
165#elif defined(__sparc_v9__)
166#define V1_MAX_PAGES ((3 << 29) - 1)
167#elif defined(__sparc__)
168#define V1_MAX_PAGES (pagesize == 8192 ? ((3 << 29) - 1) : ((1 << 18) - 1))
169#else
170#define V1_MAX_PAGES V1_OLD_MAX_PAGES
171#endif
172/* man page now says:
173The maximum useful size of a swap area now depends on the architecture.
174It is roughly 2GB on i386, PPC, m68k, ARM, 1GB on sparc, 512MB on mips,
175128GB on alpha and 3TB on sparc64.
176*/
177
178#define MAX_BADPAGES ((pagesize-1024-128*sizeof(int)-10)/sizeof(int))
179
Erik Andersene49d5ec2000-02-08 19:58:47 +0000180static void bit_set(unsigned int *addr, unsigned int nr)
Eric Andersencc8ed391999-10-05 16:24:54 +0000181{
182 unsigned int r, m;
183
184 addr += nr / (8 * sizeof(int));
Erik Andersene49d5ec2000-02-08 19:58:47 +0000185
Eric Andersencc8ed391999-10-05 16:24:54 +0000186 r = *addr;
187 m = 1 << (nr & (8 * sizeof(int) - 1));
Erik Andersene49d5ec2000-02-08 19:58:47 +0000188
Eric Andersencc8ed391999-10-05 16:24:54 +0000189 *addr = r | m;
Eric Andersencc8ed391999-10-05 16:24:54 +0000190}
191
Erik Andersene49d5ec2000-02-08 19:58:47 +0000192static int bit_test_and_clear(unsigned int *addr, unsigned int nr)
Eric Andersencc8ed391999-10-05 16:24:54 +0000193{
194 unsigned int r, m;
195
196 addr += nr / (8 * sizeof(int));
Erik Andersene49d5ec2000-02-08 19:58:47 +0000197
Eric Andersencc8ed391999-10-05 16:24:54 +0000198 r = *addr;
199 m = 1 << (nr & (8 * sizeof(int) - 1));
Erik Andersene49d5ec2000-02-08 19:58:47 +0000200
Eric Andersencc8ed391999-10-05 16:24:54 +0000201 *addr = r & ~m;
202 return (r & m) != 0;
203}
204
Eric Andersene77ae3a1999-10-19 20:03:34 +0000205
Erik Andersene49d5ec2000-02-08 19:58:47 +0000206void die(const char *str)
207{
Eric Andersene77ae3a1999-10-19 20:03:34 +0000208 fprintf(stderr, "%s: %s\n", program_name, str);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000209 exit(FALSE);
Eric Andersencc8ed391999-10-05 16:24:54 +0000210}
211
Erik Andersene49d5ec2000-02-08 19:58:47 +0000212void page_ok(int page)
213{
214 if (version == 0)
Eric Andersene77ae3a1999-10-19 20:03:34 +0000215 bit_set(signature_page, page);
216}
Eric Andersencc8ed391999-10-05 16:24:54 +0000217
Erik Andersene49d5ec2000-02-08 19:58:47 +0000218void page_bad(int page)
219{
Eric Andersene77ae3a1999-10-19 20:03:34 +0000220 if (version == 0)
221 bit_test_and_clear(signature_page, page);
222 else {
223 if (badpages == MAX_BADPAGES)
224 die("too many bad pages");
225 p->badpages[badpages] = page;
226 }
227 badpages++;
228}
229
Erik Andersene49d5ec2000-02-08 19:58:47 +0000230void check_blocks(void)
231{
Eric Andersencc8ed391999-10-05 16:24:54 +0000232 unsigned int current_page;
233 int do_seek = 1;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000234 char *buffer;
Eric Andersencc8ed391999-10-05 16:24:54 +0000235
Erik Andersen0d068a22000-03-21 22:32:57 +0000236 buffer = xmalloc(pagesize);
Eric Andersencc8ed391999-10-05 16:24:54 +0000237 current_page = 0;
238 while (current_page < PAGES) {
Eric Andersene77ae3a1999-10-19 20:03:34 +0000239 if (!check) {
240 page_ok(current_page++);
Eric Andersencc8ed391999-10-05 16:24:54 +0000241 continue;
Eric Andersencc8ed391999-10-05 16:24:54 +0000242 }
Erik Andersene49d5ec2000-02-08 19:58:47 +0000243 if (do_seek && lseek(DEV, current_page * pagesize, SEEK_SET) !=
244 current_page * pagesize)
Eric Andersencc8ed391999-10-05 16:24:54 +0000245 die("seek failed in check_blocks");
Eric Andersene77ae3a1999-10-19 20:03:34 +0000246 if ((do_seek = (pagesize != read(DEV, buffer, pagesize)))) {
247 page_bad(current_page++);
Eric Andersencc8ed391999-10-05 16:24:54 +0000248 continue;
249 }
Eric Andersene77ae3a1999-10-19 20:03:34 +0000250 page_ok(current_page++);
Eric Andersencc8ed391999-10-05 16:24:54 +0000251 }
Eric Andersene77ae3a1999-10-19 20:03:34 +0000252 if (badpages == 1)
253 printf("one bad page\n");
254 else if (badpages > 1)
255 printf("%d bad pages\n", badpages);
Eric Andersencc8ed391999-10-05 16:24:54 +0000256}
257
Erik Andersene49d5ec2000-02-08 19:58:47 +0000258static long valid_offset(int fd, int offset)
Eric Andersencc8ed391999-10-05 16:24:54 +0000259{
260 char ch;
261
Erik Andersene49d5ec2000-02-08 19:58:47 +0000262 if (lseek(fd, offset, 0) < 0)
Eric Andersencc8ed391999-10-05 16:24:54 +0000263 return 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000264 if (read(fd, &ch, 1) < 1)
Eric Andersencc8ed391999-10-05 16:24:54 +0000265 return 0;
266 return 1;
267}
268
Erik Andersene49d5ec2000-02-08 19:58:47 +0000269static int find_size(int fd)
Eric Andersencc8ed391999-10-05 16:24:54 +0000270{
Eric Andersene77ae3a1999-10-19 20:03:34 +0000271 unsigned int high, low;
Eric Andersencc8ed391999-10-05 16:24:54 +0000272
273 low = 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000274 for (high = 1; high > 0 && valid_offset(fd, high); high *= 2)
Eric Andersencc8ed391999-10-05 16:24:54 +0000275 low = high;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000276 while (low < high - 1) {
Eric Andersencc8ed391999-10-05 16:24:54 +0000277 const int mid = (low + high) / 2;
278
Erik Andersene49d5ec2000-02-08 19:58:47 +0000279 if (valid_offset(fd, mid))
Eric Andersencc8ed391999-10-05 16:24:54 +0000280 low = mid;
281 else
282 high = mid;
283 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000284 return (low + 1);
285}
286
Eric Andersene77ae3a1999-10-19 20:03:34 +0000287/* return size in pages, to avoid integer overflow */
Erik Andersene49d5ec2000-02-08 19:58:47 +0000288static long get_size(const char *file)
Eric Andersencc8ed391999-10-05 16:24:54 +0000289{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000290 int fd;
291 long size;
Eric Andersencc8ed391999-10-05 16:24:54 +0000292
Eric Andersene77ae3a1999-10-19 20:03:34 +0000293 fd = open(file, O_RDONLY);
Eric Andersencc8ed391999-10-05 16:24:54 +0000294 if (fd < 0) {
295 perror(file);
296 exit(1);
297 }
298 if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000299 int sectors_per_page = pagesize / 512;
300
Eric Andersene77ae3a1999-10-19 20:03:34 +0000301 size /= sectors_per_page;
302 } else {
303 size = find_size(fd) / pagesize;
Eric Andersencc8ed391999-10-05 16:24:54 +0000304 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000305 close(fd);
306 return size;
307}
308
Erik Andersene49d5ec2000-02-08 19:58:47 +0000309int mkswap_main(int argc, char **argv)
Eric Andersencc8ed391999-10-05 16:24:54 +0000310{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000311 char *tmp;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000312 struct stat statbuf;
313 int sz;
314 int maxpages;
315 int goodpages;
316 int offset;
317 int force = 0;
Eric Andersencc8ed391999-10-05 16:24:54 +0000318
319 if (argc && *argv)
320 program_name = *argv;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000321
Erik Andersene49d5ec2000-02-08 19:58:47 +0000322 init_signature_page(); /* get pagesize */
Eric Andersene77ae3a1999-10-19 20:03:34 +0000323
324 while (argc-- > 1) {
Eric Andersencc8ed391999-10-05 16:24:54 +0000325 argv++;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000326 if (argv[0][0] != '-') {
Eric Andersencc8ed391999-10-05 16:24:54 +0000327 if (device_name) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000328 int blocks_per_page = pagesize / 1024;
329
330 PAGES = strtol(argv[0], &tmp, 0) / blocks_per_page;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000331 if (*tmp)
Erik Andersene49d5ec2000-02-08 19:58:47 +0000332 usage(mkswap_usage);
Eric Andersencc8ed391999-10-05 16:24:54 +0000333 } else
334 device_name = argv[0];
Eric Andersene77ae3a1999-10-19 20:03:34 +0000335 } else {
336 switch (argv[0][1]) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000337 case 'c':
338 check = 1;
339 break;
340 case 'f':
341 force = 1;
342 break;
343 case 'v':
344 version = atoi(argv[0] + 2);
345 break;
346 default:
347 usage(mkswap_usage);
Eric Andersencc8ed391999-10-05 16:24:54 +0000348 }
Eric Andersene77ae3a1999-10-19 20:03:34 +0000349 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000350 }
Eric Andersene77ae3a1999-10-19 20:03:34 +0000351 if (!device_name) {
352 fprintf(stderr,
Erik Andersene49d5ec2000-02-08 19:58:47 +0000353 "%s: error: Nowhere to set up swap on?\n", program_name);
354 usage(mkswap_usage);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000355 }
356 sz = get_size(device_name);
357 if (!PAGES) {
358 PAGES = sz;
359 } else if (PAGES > sz && !force) {
360 fprintf(stderr,
Erik Andersene49d5ec2000-02-08 19:58:47 +0000361 "%s: error: "
362 "size %ld is larger than device size %d\n",
363 program_name,
364 PAGES * (pagesize / 1024), sz * (pagesize / 1024));
365 exit(FALSE);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000366 }
367
368 if (version == -1) {
369 if (PAGES <= V0_MAX_PAGES)
370 version = 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000371 else if (linux_version_code() < MAKE_VERSION(2, 1, 117))
Eric Andersene77ae3a1999-10-19 20:03:34 +0000372 version = 0;
373 else if (pagesize < 2048)
374 version = 0;
375 else
376 version = 1;
377 }
378 if (version != 0 && version != 1) {
379 fprintf(stderr, "%s: error: unknown version %d\n",
Erik Andersene49d5ec2000-02-08 19:58:47 +0000380 program_name, version);
381 usage(mkswap_usage);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000382 }
383 if (PAGES < 10) {
384 fprintf(stderr,
Erik Andersene49d5ec2000-02-08 19:58:47 +0000385 "%s: error: swap area needs to be at least %ldkB\n",
386 program_name, (long) (10 * pagesize / 1024));
387 usage(mkswap_usage);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000388 }
389#if 0
390 maxpages = ((version == 0) ? V0_MAX_PAGES : V1_MAX_PAGES);
391#else
392 if (!version)
393 maxpages = V0_MAX_PAGES;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000394 else if (linux_version_code() >= MAKE_VERSION(2, 2, 1))
Eric Andersene77ae3a1999-10-19 20:03:34 +0000395 maxpages = V1_MAX_PAGES;
396 else {
397 maxpages = V1_OLD_MAX_PAGES;
398 if (maxpages > V1_MAX_PAGES)
399 maxpages = V1_MAX_PAGES;
400 }
401#endif
402 if (PAGES > maxpages) {
403 PAGES = maxpages;
404 fprintf(stderr, "%s: warning: truncating swap area to %ldkB\n",
Erik Andersene49d5ec2000-02-08 19:58:47 +0000405 program_name, PAGES * pagesize / 1024);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000406 }
407
Erik Andersene49d5ec2000-02-08 19:58:47 +0000408 DEV = open(device_name, O_RDWR);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000409 if (DEV < 0 || fstat(DEV, &statbuf) < 0) {
410 perror(device_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000411 exit(FALSE);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000412 }
413 if (!S_ISBLK(statbuf.st_mode))
Erik Andersene49d5ec2000-02-08 19:58:47 +0000414 check = 0;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000415 else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340)
416 die("Will not try to make swapdevice on '%s'");
417
418#ifdef __sparc__
419 if (!force && version == 0) {
420 /* Don't overwrite partition table unless forced */
Erik Andersene49d5ec2000-02-08 19:58:47 +0000421 unsigned char *buffer = (unsigned char *) signature_page;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000422 unsigned short *q, sum;
423
424 if (read(DEV, buffer, 512) != 512)
425 die("fatal: first page unreadable");
426 if (buffer[508] == 0xDA && buffer[509] == 0xBE) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000427 q = (unsigned short *) (buffer + 510);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000428 for (sum = 0; q >= (unsigned short *) buffer;)
429 sum ^= *q--;
430 if (!sum) {
431 fprintf(stderr, "\
432%s: Device '%s' contains a valid Sun disklabel.\n\
433This probably means creating v0 swap would destroy your partition table\n\
434No swap created. If you really want to create swap v0 on that device, use\n\
Erik Andersene49d5ec2000-02-08 19:58:47 +0000435the -f option to force it.\n", program_name, device_name);
436 exit(FALSE);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000437 }
438 }
439 }
440#endif
441
442 if (version == 0 || check)
443 check_blocks();
Erik Andersene49d5ec2000-02-08 19:58:47 +0000444 if (version == 0 && !bit_test_and_clear(signature_page, 0))
Eric Andersene77ae3a1999-10-19 20:03:34 +0000445 die("fatal: first page unreadable");
446 if (version == 1) {
447 p->version = version;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000448 p->last_page = PAGES - 1;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000449 p->nr_badpages = badpages;
450 }
451
452 goodpages = PAGES - badpages - 1;
453 if (goodpages <= 0)
454 die("Unable to set up swap-space: unreadable");
455 printf("Setting up swapspace version %d, size = %ld bytes\n",
Erik Andersene49d5ec2000-02-08 19:58:47 +0000456 version, (long) (goodpages * pagesize));
Eric Andersene77ae3a1999-10-19 20:03:34 +0000457 write_signature((version == 0) ? "SWAP-SPACE" : "SWAPSPACE2");
458
459 offset = ((version == 0) ? 0 : 1024);
460 if (lseek(DEV, offset, SEEK_SET) != offset)
461 die("unable to rewind swap-device");
Erik Andersene49d5ec2000-02-08 19:58:47 +0000462 if (write(DEV, (char *) signature_page + offset, pagesize - offset)
463 != pagesize - offset)
Eric Andersene77ae3a1999-10-19 20:03:34 +0000464 die("unable to write signature page");
465
466 /*
467 * A subsequent swapon() will fail if the signature
468 * is not actually on disk. (This is a kernel bug.)
469 */
470 if (fsync(DEV))
Erik Andersene49d5ec2000-02-08 19:58:47 +0000471 die("fsync failed");
472 exit(TRUE);
Eric Andersencc8ed391999-10-05 16:24:54 +0000473}