blob: 986472e92f05f977771a4502a77c39d9ec6ca2a5 [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
Rob Landleybc8c5032006-06-16 04:25:19 +000038#include "busybox.h"
Eric Andersencc8ed391999-10-05 16:24:54 +000039#include <unistd.h>
40#include <string.h>
41#include <fcntl.h>
Erik Andersene49d5ec2000-02-08 19:58:47 +000042#include <sys/ioctl.h> /* for _IO */
Eric Andersene77ae3a1999-10-19 20:03:34 +000043#include <sys/utsname.h>
Erik Andersene49d5ec2000-02-08 19:58:47 +000044#include <asm/page.h> /* for PAGE_SIZE and PAGE_SHIFT */
Eric Andersene77ae3a1999-10-19 20:03:34 +000045 /* we also get PAGE_SIZE via getpagesize() */
Eric Andersencc8ed391999-10-05 16:24:54 +000046
Erik Andersene49d5ec2000-02-08 19:58:47 +000047static char *device_name = NULL;
Eric Andersencc8ed391999-10-05 16:24:54 +000048static int DEV = -1;
49static long PAGES = 0;
Eric Andersene77ae3a1999-10-19 20:03:34 +000050static int check = 0;
Eric Andersencc8ed391999-10-05 16:24:54 +000051static int badpages = 0;
Bernhard Reutner-Fischer56dd0bf2006-03-29 17:32:24 +000052#if ENABLE_FEATURE_MKSWAP_V0
Eric Andersene77ae3a1999-10-19 20:03:34 +000053static int version = -1;
Bernhard Reutner-Fischer56dd0bf2006-03-29 17:32:24 +000054#else
55#define version 1
56/* and make sure that we optimize away anything which would deal with checking
57 * the kernel revision as we have v1 support only anyway.
58 */
Bernhard Reutner-Fischere2e56c72006-05-19 11:54:02 +000059#undef KERNEL_VERSION
60#define KERNEL_VERSION(p,q,r) 1
61#define get_linux_version_code() 1
Bernhard Reutner-Fischer56dd0bf2006-03-29 17:32:24 +000062#endif
Eric Andersencc8ed391999-10-05 16:24:54 +000063
Eric Andersene77ae3a1999-10-19 20:03:34 +000064/*
65 * The definition of the union swap_header uses the constant PAGE_SIZE.
66 * Unfortunately, on some architectures this depends on the hardware model,
67 * and can only be found at run time -- we use getpagesize().
68 */
69
70static int pagesize;
Eric Andersen3496fdc2006-01-30 23:09:20 +000071static unsigned int *signature_page;
Eric Andersene77ae3a1999-10-19 20:03:34 +000072
Eric Andersen3e6ff902001-03-09 21:24:12 +000073static struct swap_header_v1 {
Erik Andersene49d5ec2000-02-08 19:58:47 +000074 char bootbits[1024]; /* Space for disklabel etc. */
Bernhard Reutner-Fischer56dd0bf2006-03-29 17:32:24 +000075 unsigned int swap_version;
Eric Andersene77ae3a1999-10-19 20:03:34 +000076 unsigned int last_page;
77 unsigned int nr_badpages;
78 unsigned int padding[125];
79 unsigned int badpages[1];
80} *p;
81
Eric Andersenfcffa2c2002-04-06 05:17:57 +000082static inline void init_signature_page(void)
Erik Andersene49d5ec2000-02-08 19:58:47 +000083{
Eric Andersene77ae3a1999-10-19 20:03:34 +000084 pagesize = getpagesize();
85
86#ifdef PAGE_SIZE
87 if (pagesize != PAGE_SIZE)
Manuel Novoa III cad53642003-03-19 09:13:01 +000088 bb_error_msg("Assuming pages of size %d", pagesize);
Eric Andersene77ae3a1999-10-19 20:03:34 +000089#endif
Eric Andersen3496fdc2006-01-30 23:09:20 +000090 signature_page = (unsigned int *) xmalloc(pagesize);
Erik Andersene49d5ec2000-02-08 19:58:47 +000091 memset(signature_page, 0, pagesize);
Eric Andersene77ae3a1999-10-19 20:03:34 +000092 p = (struct swap_header_v1 *) signature_page;
93}
94
Eric Andersenfcffa2c2002-04-06 05:17:57 +000095static inline void write_signature(char *sig)
Erik Andersene49d5ec2000-02-08 19:58:47 +000096{
Eric Andersene77ae3a1999-10-19 20:03:34 +000097 char *sp = (char *) signature_page;
98
Erik Andersene49d5ec2000-02-08 19:58:47 +000099 strncpy(sp + pagesize - 10, sig, 10);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000100}
101
102#define V0_MAX_PAGES (8 * (pagesize - 10))
103/* Before 2.2.0pre9 */
104#define V1_OLD_MAX_PAGES ((0x7fffffff / pagesize) - 1)
105/* Since 2.2.0pre9:
106 error if nr of pages >= SWP_OFFSET(SWP_ENTRY(0,~0UL))
107 with variations on
108 #define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8))
109 #define SWP_OFFSET(entry) ((entry) >> 8)
110 on the various architectures. Below the result - yuk.
111
112 Machine pagesize SWP_ENTRY SWP_OFFSET bound+1 oldbound+2
113 i386 2^12 o<<8 e>>8 1<<24 1<<19
114 mips 2^12 o<<15 e>>15 1<<17 1<<19
115 alpha 2^13 o<<40 e>>40 1<<24 1<<18
116 m68k 2^12 o<<12 e>>12 1<<20 1<<19
117 sparc 2^{12,13} (o&0x3ffff)<<9 (e>>9)&0x3ffff 1<<18 1<<{19,18}
118 sparc64 2^13 o<<13 e>>13 1<<51 1<<18
119 ppc 2^12 o<<8 e>>8 1<<24 1<<19
120 armo 2^{13,14,15} o<<8 e>>8 1<<24 1<<{18,17,16}
121 armv 2^12 o<<9 e>>9 1<<23 1<<19
122
123 assuming that longs have 64 bits on alpha and sparc64 and 32 bits elsewhere.
124
125 The bad part is that we need to know this since the kernel will
126 refuse a swap space if it is too large.
127*/
128/* patch from jj - why does this differ from the above? */
129#if defined(__alpha__)
130#define V1_MAX_PAGES ((1 << 24) - 1)
131#elif defined(__mips__)
132#define V1_MAX_PAGES ((1 << 17) - 1)
133#elif defined(__sparc_v9__)
134#define V1_MAX_PAGES ((3 << 29) - 1)
135#elif defined(__sparc__)
136#define V1_MAX_PAGES (pagesize == 8192 ? ((3 << 29) - 1) : ((1 << 18) - 1))
137#else
138#define V1_MAX_PAGES V1_OLD_MAX_PAGES
139#endif
140/* man page now says:
141The maximum useful size of a swap area now depends on the architecture.
142It is roughly 2GB on i386, PPC, m68k, ARM, 1GB on sparc, 512MB on mips,
143128GB on alpha and 3TB on sparc64.
144*/
145
146#define MAX_BADPAGES ((pagesize-1024-128*sizeof(int)-10)/sizeof(int))
147
Eric Andersenfcffa2c2002-04-06 05:17:57 +0000148static inline void bit_set(unsigned int *addr, unsigned int nr)
Eric Andersencc8ed391999-10-05 16:24:54 +0000149{
150 unsigned int r, m;
151
152 addr += nr / (8 * sizeof(int));
Erik Andersene49d5ec2000-02-08 19:58:47 +0000153
Eric Andersencc8ed391999-10-05 16:24:54 +0000154 r = *addr;
155 m = 1 << (nr & (8 * sizeof(int) - 1));
Erik Andersene49d5ec2000-02-08 19:58:47 +0000156
Eric Andersencc8ed391999-10-05 16:24:54 +0000157 *addr = r | m;
Eric Andersencc8ed391999-10-05 16:24:54 +0000158}
159
Erik Andersene49d5ec2000-02-08 19:58:47 +0000160static int bit_test_and_clear(unsigned int *addr, unsigned int nr)
Eric Andersencc8ed391999-10-05 16:24:54 +0000161{
162 unsigned int r, m;
163
164 addr += nr / (8 * sizeof(int));
Erik Andersene49d5ec2000-02-08 19:58:47 +0000165
Eric Andersencc8ed391999-10-05 16:24:54 +0000166 r = *addr;
167 m = 1 << (nr & (8 * sizeof(int) - 1));
Erik Andersene49d5ec2000-02-08 19:58:47 +0000168
Eric Andersencc8ed391999-10-05 16:24:54 +0000169 *addr = r & ~m;
170 return (r & m) != 0;
171}
172
Eric Andersen16fdbe82000-12-20 23:40:57 +0000173static void page_ok(int page)
Erik Andersene49d5ec2000-02-08 19:58:47 +0000174{
Bernhard Reutner-Fischer56dd0bf2006-03-29 17:32:24 +0000175 if (ENABLE_FEATURE_MKSWAP_V0) {
Eric Andersene77ae3a1999-10-19 20:03:34 +0000176 bit_set(signature_page, page);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000177 }
Eric Andersene77ae3a1999-10-19 20:03:34 +0000178}
179
Eric Andersen16fdbe82000-12-20 23:40:57 +0000180static void check_blocks(void)
Erik Andersene49d5ec2000-02-08 19:58:47 +0000181{
Eric Andersencc8ed391999-10-05 16:24:54 +0000182 unsigned int current_page;
183 int do_seek = 1;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000184 char *buffer;
Eric Andersencc8ed391999-10-05 16:24:54 +0000185
Erik Andersen0d068a22000-03-21 22:32:57 +0000186 buffer = xmalloc(pagesize);
Eric Andersencc8ed391999-10-05 16:24:54 +0000187 current_page = 0;
188 while (current_page < PAGES) {
Bernhard Reutner-Fischer56dd0bf2006-03-29 17:32:24 +0000189 if (!check && version == 0) {
Eric Andersene77ae3a1999-10-19 20:03:34 +0000190 page_ok(current_page++);
Eric Andersencc8ed391999-10-05 16:24:54 +0000191 continue;
Eric Andersencc8ed391999-10-05 16:24:54 +0000192 }
Erik Andersene49d5ec2000-02-08 19:58:47 +0000193 if (do_seek && lseek(DEV, current_page * pagesize, SEEK_SET) !=
194 current_page * pagesize)
Manuel Novoa III cad53642003-03-19 09:13:01 +0000195 bb_error_msg_and_die("seek failed in check_blocks");
Eric Andersene77ae3a1999-10-19 20:03:34 +0000196 if ((do_seek = (pagesize != read(DEV, buffer, pagesize)))) {
Bernhard Reutner-Fischer56dd0bf2006-03-29 17:32:24 +0000197 current_page++;
198 if (version == 0)
199 bit_test_and_clear(signature_page, current_page);
200 else {
201 if (badpages == MAX_BADPAGES)
202 bb_error_msg_and_die("too many bad pages");
203 p->badpages[badpages] = current_page;
204 }
205 badpages++;
Eric Andersencc8ed391999-10-05 16:24:54 +0000206 continue;
207 }
Eric Andersene77ae3a1999-10-19 20:03:34 +0000208 page_ok(current_page++);
Eric Andersencc8ed391999-10-05 16:24:54 +0000209 }
Bernhard Reutner-Fischer56dd0bf2006-03-29 17:32:24 +0000210 if (ENABLE_FEATURE_CLEAN_UP)
211 free(buffer);
212 if (badpages > 0)
213 printf("%d bad page%s\n", badpages, (badpages==1)?"":"s");
Eric Andersencc8ed391999-10-05 16:24:54 +0000214}
215
Erik Andersene49d5ec2000-02-08 19:58:47 +0000216static long valid_offset(int fd, int offset)
Eric Andersencc8ed391999-10-05 16:24:54 +0000217{
218 char ch;
219
Erik Andersene49d5ec2000-02-08 19:58:47 +0000220 if (lseek(fd, offset, 0) < 0)
Eric Andersencc8ed391999-10-05 16:24:54 +0000221 return 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000222 if (read(fd, &ch, 1) < 1)
Eric Andersencc8ed391999-10-05 16:24:54 +0000223 return 0;
224 return 1;
225}
226
Erik Andersene49d5ec2000-02-08 19:58:47 +0000227static int find_size(int fd)
Eric Andersencc8ed391999-10-05 16:24:54 +0000228{
Eric Andersene77ae3a1999-10-19 20:03:34 +0000229 unsigned int high, low;
Eric Andersencc8ed391999-10-05 16:24:54 +0000230
231 low = 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000232 for (high = 1; high > 0 && valid_offset(fd, high); high *= 2)
Eric Andersencc8ed391999-10-05 16:24:54 +0000233 low = high;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000234 while (low < high - 1) {
Eric Andersencc8ed391999-10-05 16:24:54 +0000235 const int mid = (low + high) / 2;
236
Erik Andersene49d5ec2000-02-08 19:58:47 +0000237 if (valid_offset(fd, mid))
Eric Andersencc8ed391999-10-05 16:24:54 +0000238 low = mid;
239 else
240 high = mid;
241 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000242 return (low + 1);
243}
244
Eric Andersene77ae3a1999-10-19 20:03:34 +0000245/* return size in pages, to avoid integer overflow */
Bernhard Reutner-Fischer56dd0bf2006-03-29 17:32:24 +0000246static inline long get_size(const char *file)
Eric Andersencc8ed391999-10-05 16:24:54 +0000247{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000248 int fd;
249 long size;
Eric Andersencc8ed391999-10-05 16:24:54 +0000250
Bernhard Reutner-Fischerc2cb0f32006-04-13 12:45:04 +0000251 fd = bb_xopen3(file, O_RDONLY, 0);
Eric Andersencc8ed391999-10-05 16:24:54 +0000252 if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
Bernhard Reutner-Fischer56dd0bf2006-03-29 17:32:24 +0000253 size /= pagesize / 512;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000254 } else {
255 size = find_size(fd) / pagesize;
Eric Andersencc8ed391999-10-05 16:24:54 +0000256 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000257 close(fd);
258 return size;
259}
260
Erik Andersene49d5ec2000-02-08 19:58:47 +0000261int mkswap_main(int argc, char **argv)
Eric Andersencc8ed391999-10-05 16:24:54 +0000262{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000263 char *tmp;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000264 struct stat statbuf;
265 int sz;
266 int maxpages;
267 int goodpages;
Bernhard Reutner-Fischer56dd0bf2006-03-29 17:32:24 +0000268#ifdef __sparc__
Eric Andersene77ae3a1999-10-19 20:03:34 +0000269 int force = 0;
Bernhard Reutner-Fischer56dd0bf2006-03-29 17:32:24 +0000270#endif
Eric Andersencc8ed391999-10-05 16:24:54 +0000271
Erik Andersene49d5ec2000-02-08 19:58:47 +0000272 init_signature_page(); /* get pagesize */
Eric Andersene77ae3a1999-10-19 20:03:34 +0000273
Bernhard Reutner-Fischer56dd0bf2006-03-29 17:32:24 +0000274 bb_opt_complementally = "?"; /* call bb_show_usage internally */
275 sz = bb_getopt_ulflags(argc, argv, "+cfv:", &tmp);
276 if (sz & 1)
277 check = 1;
278#ifdef __sparc__
279 if (sz & 2)
280 force = 1;
281#endif
282#if ENABLE_FEATURE_MKSWAP_V0
283 if (sz & 4) {
284 version = bb_xgetlarg(tmp, 10, 0, 1);
285 } else {
Bernhard Reutner-Fischere2e56c72006-05-19 11:54:02 +0000286 if (get_linux_version_code() < KERNEL_VERSION(2, 1, 117))
Eric Andersene77ae3a1999-10-19 20:03:34 +0000287 version = 0;
288 else
289 version = 1;
290 }
Bernhard Reutner-Fischer56dd0bf2006-03-29 17:32:24 +0000291#endif
292
293 argv += optind;
294 argc -= optind;
295
296 goodpages = pagesize / 1024; /* cache division */
297 while (argc--) {
298 if (device_name) {
299 PAGES = bb_xgetlarg(argv[0], 0, 10, sz * goodpages) / goodpages;
300 argc = 0; /* ignore any surplus args.. */
301 } else {
302 device_name = argv[0];
303 sz = get_size(device_name);
304 argv++;
305 }
Eric Andersene77ae3a1999-10-19 20:03:34 +0000306 }
Bernhard Reutner-Fischer56dd0bf2006-03-29 17:32:24 +0000307
308 if (!device_name) {
309 bb_error_msg_and_die("error: Nowhere to set up swap on?");
Eric Andersene77ae3a1999-10-19 20:03:34 +0000310 }
Bernhard Reutner-Fischer56dd0bf2006-03-29 17:32:24 +0000311 if (!PAGES) {
312 PAGES = sz;
313 }
314
Eric Andersene77ae3a1999-10-19 20:03:34 +0000315 if (!version)
316 maxpages = V0_MAX_PAGES;
Bernhard Reutner-Fischere2e56c72006-05-19 11:54:02 +0000317 else if (get_linux_version_code() >= KERNEL_VERSION(2,2,1))
Eric Andersene77ae3a1999-10-19 20:03:34 +0000318 maxpages = V1_MAX_PAGES;
319 else {
320 maxpages = V1_OLD_MAX_PAGES;
321 if (maxpages > V1_MAX_PAGES)
322 maxpages = V1_MAX_PAGES;
323 }
Eric Andersene77ae3a1999-10-19 20:03:34 +0000324 if (PAGES > maxpages) {
325 PAGES = maxpages;
Manuel Novoa III cad53642003-03-19 09:13:01 +0000326 bb_error_msg("warning: truncating swap area to %ldkB",
Bernhard Reutner-Fischer56dd0bf2006-03-29 17:32:24 +0000327 PAGES * goodpages);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000328 }
329
Bernhard Reutner-Fischerc2cb0f32006-04-13 12:45:04 +0000330 DEV = bb_xopen3(device_name, O_RDWR, 0);
Bernhard Reutner-Fischerdac7ff12006-04-12 17:55:51 +0000331 if (fstat(DEV, &statbuf) < 0)
Manuel Novoa III cad53642003-03-19 09:13:01 +0000332 bb_perror_msg_and_die("%s", device_name);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000333 if (!S_ISBLK(statbuf.st_mode))
Erik Andersene49d5ec2000-02-08 19:58:47 +0000334 check = 0;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000335 else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340)
Manuel Novoa III cad53642003-03-19 09:13:01 +0000336 bb_error_msg_and_die("Will not try to make swapdevice on '%s'", device_name);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000337
338#ifdef __sparc__
339 if (!force && version == 0) {
340 /* Don't overwrite partition table unless forced */
Erik Andersene49d5ec2000-02-08 19:58:47 +0000341 unsigned char *buffer = (unsigned char *) signature_page;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000342 unsigned short *q, sum;
343
344 if (read(DEV, buffer, 512) != 512)
Manuel Novoa III cad53642003-03-19 09:13:01 +0000345 bb_error_msg_and_die("fatal: first page unreadable");
Eric Andersene77ae3a1999-10-19 20:03:34 +0000346 if (buffer[508] == 0xDA && buffer[509] == 0xBE) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000347 q = (unsigned short *) (buffer + 510);
Eric Andersene77ae3a1999-10-19 20:03:34 +0000348 for (sum = 0; q >= (unsigned short *) buffer;)
349 sum ^= *q--;
350 if (!sum) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000351 bb_error_msg("Device '%s' contains a valid Sun disklabel.\n"
Matt Kraaid537a952000-07-14 01:51:25 +0000352"This probably means creating v0 swap would destroy your partition table\n"
353"No swap created. If you really want to create swap v0 on that device, use\n"
Matt Kraaidd19c692001-01-31 19:00:21 +0000354"the -f option to force it.", device_name);
Matt Kraai3e856ce2000-12-01 02:55:13 +0000355 return EXIT_FAILURE;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000356 }
357 }
358 }
359#endif
360
361 if (version == 0 || check)
362 check_blocks();
Erik Andersene49d5ec2000-02-08 19:58:47 +0000363 if (version == 0 && !bit_test_and_clear(signature_page, 0))
Manuel Novoa III cad53642003-03-19 09:13:01 +0000364 bb_error_msg_and_die("fatal: first page unreadable");
Eric Andersene77ae3a1999-10-19 20:03:34 +0000365 if (version == 1) {
Bernhard Reutner-Fischer56dd0bf2006-03-29 17:32:24 +0000366 p->swap_version = version;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000367 p->last_page = PAGES - 1;
Eric Andersene77ae3a1999-10-19 20:03:34 +0000368 p->nr_badpages = badpages;
369 }
370
371 goodpages = PAGES - badpages - 1;
372 if (goodpages <= 0)
Manuel Novoa III cad53642003-03-19 09:13:01 +0000373 bb_error_msg_and_die("Unable to set up swap-space: unreadable");
Eric Andersene77ae3a1999-10-19 20:03:34 +0000374 printf("Setting up swapspace version %d, size = %ld bytes\n",
Erik Andersene49d5ec2000-02-08 19:58:47 +0000375 version, (long) (goodpages * pagesize));
Eric Andersene77ae3a1999-10-19 20:03:34 +0000376 write_signature((version == 0) ? "SWAP-SPACE" : "SWAPSPACE2");
377
Bernhard Reutner-Fischer56dd0bf2006-03-29 17:32:24 +0000378 sz = ((version == 0) ? 0 : 1024); /* offset */
379 if (lseek(DEV, sz, SEEK_SET) != sz)
Manuel Novoa III cad53642003-03-19 09:13:01 +0000380 bb_error_msg_and_die("unable to rewind swap-device");
Bernhard Reutner-Fischer56dd0bf2006-03-29 17:32:24 +0000381 goodpages = pagesize - sz; /* cache substraction */
382 if (write(DEV, (char *) signature_page + sz, goodpages)
383 != goodpages)
Manuel Novoa III cad53642003-03-19 09:13:01 +0000384 bb_error_msg_and_die("unable to write signature page");
Eric Andersene77ae3a1999-10-19 20:03:34 +0000385
386 /*
387 * A subsequent swapon() will fail if the signature
388 * is not actually on disk. (This is a kernel bug.)
389 */
390 if (fsync(DEV))
Manuel Novoa III cad53642003-03-19 09:13:01 +0000391 bb_error_msg_and_die("fsync failed");
Bernhard Reutner-Fischer56dd0bf2006-03-29 17:32:24 +0000392 if (ENABLE_FEATURE_CLEAN_UP) {
393 close(DEV);
394 free(signature_page);
395 }
Matt Kraai3e856ce2000-12-01 02:55:13 +0000396 return EXIT_SUCCESS;
Eric Andersencc8ed391999-10-05 16:24:54 +0000397}