]> git.ipfire.org Git - thirdparty/util-linux.git/blame - disk-utils/mkswap.c
libblkid: no more probe for btrfs backup superblock
[thirdparty/util-linux.git] / disk-utils / mkswap.c
CommitLineData
6dbe3af9
KZ
1/*
2 * mkswap.c - set up a linux swap device
3 *
4 * (C) 1991 Linus Torvalds. This file may be redistributed as per
5 * the Linux copyright.
6 */
7
8/*
9 * 20.12.91 - time began. Got VM working yesterday by doing this by hand.
10 *
7eda085c 11 * Usage: mkswap [-c] [-vN] [-f] device [size-in-blocks]
6dbe3af9 12 *
5c36a0eb
KZ
13 * -c for readability checking. (Use it unless you are SURE!)
14 * -vN for swap areas version N. (Only N=0,1 known today.)
15 * -f for forcing swap creation even if it would smash partition table.
6dbe3af9 16 *
5c36a0eb 17 * The device may be a block device or an image of one, but this isn't
6dbe3af9
KZ
18 * enforced (but it's not much fun on a character device :-).
19 *
20 * Patches from jaggy@purplet.demon.co.uk (Mike Jagdis) to make the
21 * size-in-blocks parameter optional added Wed Feb 8 10:33:43 1995.
5c36a0eb
KZ
22 *
23 * Version 1 swap area code (for kernel 2.1.117), aeb, 981010.
24 *
25 * Sparc fixes, jj@ultra.linux.cz (Jakub Jelinek), 981201 - mangled by aeb.
7eda085c 26 * V1_MAX_PAGES fixes, jj, 990325.
22853e4a 27 * sparc64 fixes, jj, 000219.
7eda085c 28 *
b50945d4 29 * 1999-02-22 Arkadiusz Miƛkiewicz <misiek@pld.ORG.PL>
7eda085c 30 * - added Native Language Support
3e18b040 31 *
6dbe3af9
KZ
32 */
33
34#include <stdio.h>
35#include <unistd.h>
36#include <string.h>
37#include <fcntl.h>
38#include <stdlib.h>
99e6d525 39#include <limits.h>
8abb4c2e 40#include <mntent.h>
5c36a0eb 41#include <sys/utsname.h>
6dbe3af9 42#include <sys/stat.h>
3e18b040 43#include <errno.h>
e079c4e6 44#include <getopt.h>
3e18b040
KZ
45#ifdef HAVE_LIBSELINUX
46#include <selinux/selinux.h>
47#include <selinux/context.h>
48#endif
49
8023c83b 50#include "linux_version.h"
756bfd01 51#include "swapheader.h"
8abcf290 52#include "strutils.h"
66ee8158 53#include "nls.h"
54e377b3 54#include "blkdev.h"
fc68cd49 55#include "pathnames.h"
ff3bed80 56#include "wholedisk.h"
e12c9866 57#include "all-io.h"
94a50e28 58#include "xalloc.h"
08675263 59#include "c.h"
45ca68ec 60#include "closestream.h"
def478cf 61#include "ismounted.h"
66ee8158 62
766dd757 63#ifdef HAVE_LIBUUID
7ee96990 64# include <uuid.h>
756bfd01
KZ
65#endif
66
64d15476 67#ifdef HAVE_LIBBLKID
566f35bc
KZ
68# include <blkid.h>
69#endif
70
f2704664 71static char *device_name = NULL;
6dbe3af9 72static int DEV = -1;
99e6d525 73static unsigned long long PAGES = 0;
d03dd608 74static unsigned long badpages = 0;
6dbe3af9 75static int check = 0;
5c36a0eb 76
3e18b040
KZ
77#define SELINUX_SWAPFILE_TYPE "swapfile_t"
78
22853e4a
KZ
79#ifdef __sparc__
80# ifdef __arch64__
81# define is_sparc64() 1
82# define is_be64() 1
83# else /* sparc32 */
84static int
f2704664
SK
85is_sparc64(void)
86{
22853e4a
KZ
87 struct utsname un;
88 static int sparc64 = -1;
89
f2704664
SK
90 if (sparc64 != -1)
91 return sparc64;
22853e4a
KZ
92 sparc64 = 0;
93
f2704664
SK
94 if (uname(&un) < 0)
95 return 0;
22853e4a
KZ
96 if (! strcmp(un.machine, "sparc64")) {
97 sparc64 = 1;
98 return 1;
99 }
100 if (strcmp(un.machine, "sparc"))
101 return 0; /* Should not happen */
102
48d7b13a 103#ifdef HAVE_PERSONALITY
22853e4a
KZ
104 {
105 extern int personality(unsigned long);
106 int oldpers;
107#define PERS_LINUX 0x00000000
108#define PERS_LINUX_32BIT 0x00800000
109#define PERS_LINUX32 0x00000008
110
111 oldpers = personality(PERS_LINUX_32BIT);
112 if (oldpers != -1) {
113 if (personality(PERS_LINUX) != -1) {
114 uname(&un);
115 if (! strcmp(un.machine, "sparc64")) {
116 sparc64 = 1;
117 oldpers = PERS_LINUX32;
118 }
119 }
120 personality(oldpers);
121 }
122 }
123#endif
124
125 return sparc64;
126}
127# define is_be64() is_sparc64()
128# endif /* sparc32 */
129#else /* !sparc */
130# define is_be64() 0
131#endif
132
5c36a0eb 133/*
7ac3b5b8
KZ
134 * The definition of the union swap_header uses the kernel constant PAGE_SIZE.
135 * Unfortunately, on some architectures this depends on the hardware model, and
136 * can only be found at run time -- we use getpagesize(), so that we do not
137 * need separate binaries e.g. for sun4, sun4c/d/m and sun4u.
138 *
139 * Even more unfortunately, getpagesize() does not always return the right
140 * information. For example, libc4, libc5 and glibc 2.0 do not use the system
141 * call but invent a value themselves (EXEC_PAGESIZE or NBPG * CLSIZE or NBPC),
142 * and thus it may happen that e.g. on a sparc kernel PAGE_SIZE=4096 and
143 * getpagesize() returns 8192.
eb63b9b8 144 *
eb63b9b8 145 * What to do? Let us allow the user to specify the pagesize explicitly.
7ac3b5b8 146 *
5c36a0eb 147 */
33fb5cfd
KZ
148static unsigned int user_pagesize;
149static unsigned int pagesize;
3216beb0 150static unsigned long *signature_page = NULL;
5c36a0eb
KZ
151
152static void
f2704664
SK
153init_signature_page(void)
154{
756bfd01 155
33fb5cfd 156 unsigned int kernel_pagesize = pagesize = getpagesize();
eb63b9b8
KZ
157
158 if (user_pagesize) {
33fb5cfd
KZ
159 if (!is_power_of_2(user_pagesize) ||
160 user_pagesize < sizeof(struct swap_header_v1_2) + 10)
00a7d0d2 161 errx(EXIT_FAILURE,
33fb5cfd 162 _("Bad user-specified page size %u"),
eb63b9b8 163 user_pagesize);
eb63b9b8
KZ
164 pagesize = user_pagesize;
165 }
166
7ac3b5b8 167 if (user_pagesize && user_pagesize != kernel_pagesize)
00a7d0d2
SK
168 warnx(_("Using user-specified page size %d, "
169 "instead of the system value %d"),
7ac3b5b8 170 pagesize, kernel_pagesize);
eb63b9b8 171
94a50e28 172 signature_page = (unsigned long *) xcalloc(1, pagesize);
5c36a0eb
KZ
173}
174
175static void
f2704664
SK
176write_signature(char *sig)
177{
5c36a0eb
KZ
178 char *sp = (char *) signature_page;
179
f2704664 180 strncpy(sp + pagesize - 10, sig, 10);
5c36a0eb
KZ
181}
182
756bfd01 183static void
f2704664
SK
184write_uuid_and_label(unsigned char *uuid, char *volume_name)
185{
756bfd01
KZ
186 struct swap_header_v1_2 *h;
187
188 /* Sanity check */
189 if (sizeof(struct swap_header_v1) !=
190 sizeof(struct swap_header_v1_2)) {
00a7d0d2 191 warnx(_("Bad swap header size, no label written."));
756bfd01
KZ
192 return;
193 }
194
195 h = (struct swap_header_v1_2 *) signature_page;
196 if (uuid)
197 memcpy(h->uuid, uuid, sizeof(h->uuid));
198 if (volume_name) {
199 xstrncpy(h->volume_name, volume_name, sizeof(h->volume_name));
200 if (strlen(volume_name) > strlen(h->volume_name))
00a7d0d2 201 warnx(_("Label was truncated."));
756bfd01
KZ
202 }
203 if (uuid || volume_name) {
204 if (volume_name)
205 printf("LABEL=%s, ", h->volume_name);
206 else
207 printf(_("no label, "));
766dd757 208#ifdef HAVE_LIBUUID
756bfd01
KZ
209 if (uuid) {
210 char uuid_string[37];
211 uuid_unparse(uuid, uuid_string);
212 printf("UUID=%s\n", uuid_string);
213 } else
214#endif
215 printf(_("no uuid\n"));
216 }
217}
218
0e6f4a20
KZ
219/*
220 * Find out what the maximum amount of swap space is that the kernel will
221 * handle. This wouldn't matter if the kernel just used as much of the
222 * swap space as it can handle, but until 2.3.4 it would return an error
223 * to swapon() if the swapspace was too large.
224 */
7eda085c
KZ
225/* Before 2.2.0pre9 */
226#define V1_OLD_MAX_PAGES ((0x7fffffff / pagesize) - 1)
0e6f4a20 227/* Since 2.2.0pre9, before 2.3.4:
7eda085c
KZ
228 error if nr of pages >= SWP_OFFSET(SWP_ENTRY(0,~0UL))
229 with variations on
230 #define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8))
231 #define SWP_OFFSET(entry) ((entry) >> 8)
232 on the various architectures. Below the result - yuk.
233
234 Machine pagesize SWP_ENTRY SWP_OFFSET bound+1 oldbound+2
235 i386 2^12 o<<8 e>>8 1<<24 1<<19
236 mips 2^12 o<<15 e>>15 1<<17 1<<19
237 alpha 2^13 o<<40 e>>40 1<<24 1<<18
238 m68k 2^12 o<<12 e>>12 1<<20 1<<19
239 sparc 2^{12,13} (o&0x3ffff)<<9 (e>>9)&0x3ffff 1<<18 1<<{19,18}
240 sparc64 2^13 o<<13 e>>13 1<<51 1<<18
241 ppc 2^12 o<<8 e>>8 1<<24 1<<19
242 armo 2^{13,14,15} o<<8 e>>8 1<<24 1<<{18,17,16}
243 armv 2^12 o<<9 e>>9 1<<23 1<<19
244
245 assuming that longs have 64 bits on alpha and sparc64 and 32 bits elsewhere.
246
247 The bad part is that we need to know this since the kernel will
248 refuse a swap space if it is too large.
249*/
250/* patch from jj - why does this differ from the above? */
22853e4a
KZ
251/* 32bit kernels have a second limitation of 2GB, sparc64 is limited by
252 the size of virtual address space allocation for vmalloc */
7eda085c
KZ
253#if defined(__alpha__)
254#define V1_MAX_PAGES ((1 << 24) - 1)
255#elif defined(__mips__)
256#define V1_MAX_PAGES ((1 << 17) - 1)
7eda085c 257#elif defined(__sparc__)
22853e4a 258#define V1_MAX_PAGES (is_sparc64() ? ((3 << 29) - 1) : ((1 << 18) - 1))
1d4ad1de 259#elif defined(__ia64__)
3e18b040 260/*
1d4ad1de
KZ
261 * The actual size will depend on the amount of virtual address space
262 * available to vmalloc the swap map.
263 */
264#define V1_MAX_PAGES ((1UL << 54) - 1)
7eda085c
KZ
265#else
266#define V1_MAX_PAGES V1_OLD_MAX_PAGES
267#endif
268/* man page now says:
269The maximum useful size of a swap area now depends on the architecture.
270It is roughly 2GB on i386, PPC, m68k, ARM, 1GB on sparc, 512MB on mips,
271128GB on alpha and 3TB on sparc64.
272*/
5c36a0eb
KZ
273
274#define MAX_BADPAGES ((pagesize-1024-128*sizeof(int)-10)/sizeof(int))
99e6d525 275#define MIN_GOODPAGES 10
6dbe3af9 276
e079c4e6
SK
277static void __attribute__ ((__noreturn__)) usage(FILE *out)
278{
279 fprintf(out,
280 _("\nUsage:\n"
281 " %s [options] device [size]\n"),
00a7d0d2 282 program_invocation_short_name);
e079c4e6
SK
283
284 fprintf(out, _(
285 "\nOptions:\n"
286 " -c, --check check bad blocks before creating the swap area\n"
287 " -f, --force allow swap size area be larger than device\n"
288 " -p, --pagesize SIZE specify page size in bytes\n"
289 " -L, --label LABEL specify label\n"
290 " -v, --swapversion NUM specify swap-space version number\n"
291 " -U, --uuid UUID specify the uuid to use\n"
292 " -V, --version output version information and exit\n"
293 " -h, --help display this help and exit\n\n"));
294
295 exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
eb63b9b8 296}
6dbe3af9 297
22853e4a 298static void
f2704664
SK
299page_bad(int page)
300{
3e16599a
KZ
301 struct swap_header_v1_2 *p = (struct swap_header_v1_2 *) signature_page;
302
4c85aa3a 303 if (badpages == MAX_BADPAGES)
00a7d0d2 304 errx(EXIT_FAILURE, _("too many bad pages"));
4c85aa3a 305 p->badpages[badpages] = page;
5c36a0eb
KZ
306 badpages++;
307}
308
22853e4a 309static void
f2704664
SK
310check_blocks(void)
311{
6dbe3af9
KZ
312 unsigned int current_page;
313 int do_seek = 1;
5c36a0eb 314 char *buffer;
6dbe3af9 315
94a50e28 316 buffer = xmalloc(pagesize);
6dbe3af9
KZ
317 current_page = 0;
318 while (current_page < PAGES) {
f3b16286
KZ
319
320 ssize_t rc;
321
5c36a0eb
KZ
322 if (do_seek && lseek(DEV,current_page*pagesize,SEEK_SET) !=
323 current_page*pagesize)
00a7d0d2 324 errx(EXIT_FAILURE, _("seek failed in check_blocks"));
f3b16286
KZ
325
326 rc = read(DEV, buffer, pagesize);
327 do_seek = (rc < 0 || (size_t) rc != pagesize);
328 if (do_seek)
adda7f7e 329 page_bad(current_page);
adda7f7e 330 current_page++;
6dbe3af9 331 }
ff21848c 332 printf(P_("%lu bad page\n", "%lu bad pages\n", badpages), badpages);
3216beb0 333 free(buffer);
6dbe3af9
KZ
334}
335
99e6d525
HD
336/* return size in pages */
337static unsigned long long
f2704664
SK
338get_size(const char *file)
339{
340 int fd;
54e377b3 341 unsigned long long size;
6dbe3af9 342
5c36a0eb 343 fd = open(file, O_RDONLY);
6dbe3af9
KZ
344 if (fd < 0) {
345 perror(file);
a4d3e778 346 exit(EXIT_FAILURE);
6dbe3af9 347 }
54e377b3
KZ
348 if (blkdev_get_size(fd, &size) == 0)
349 size /= pagesize;
54e377b3 350
6dbe3af9
KZ
351 close(fd);
352 return size;
353}
354
979f1dd5
KZ
355#ifdef HAVE_LIBBLKID
356static blkid_probe
357new_prober(int fd)
358{
359 blkid_probe pr = blkid_new_probe();
360 if (!pr)
361 errx(EXIT_FAILURE, _("unable to alloc new libblkid probe"));
362 if (blkid_probe_set_device(pr, fd, 0, 0))
363 errx(EXIT_FAILURE, _("unable to assign device to libblkid probe"));
364 return pr;
365}
366#endif
367
ff3bed80 368static void
c1f1b301 369wipe_device(int fd, const char *devname, int force)
ff3bed80 370{
566f35bc 371 char *type = NULL;
ff3bed80 372 int zap = 1;
9206b238 373#ifdef HAVE_LIBBLKID
979f1dd5 374 blkid_probe pr = NULL;
9206b238 375#endif
ff3bed80
KZ
376 if (!force) {
377 if (lseek(fd, 0, SEEK_SET) != 0)
00a7d0d2 378 errx(EXIT_FAILURE, _("unable to rewind swap-device"));
ff3bed80 379
64d15476 380#ifdef HAVE_LIBBLKID
c1f1b301
MB
381 pr = new_prober(fd);
382 blkid_probe_enable_partitions(pr, 1);
383 blkid_probe_enable_superblocks(pr, 0);
384
385 if (blkid_do_fullprobe(pr) == 0 &&
386 blkid_probe_lookup_value(pr, "PTTYPE",
387 (const char **) &type, NULL) == 0 && type) {
388 type = xstrdup(type);
ff3bed80 389 zap = 0;
566f35bc 390 }
c1f1b301
MB
391#else
392 /* don't zap if compiled without libblkid */
393 zap = 0;
394#endif
ff3bed80
KZ
395 }
396
397 if (zap) {
979f1dd5
KZ
398 /*
399 * Wipe boodbits
400 */
ff3bed80 401 char buf[1024];
c1f1b301 402 const char *data = NULL;
ff3bed80
KZ
403
404 if (lseek(fd, 0, SEEK_SET) != 0)
00a7d0d2 405 errx(EXIT_FAILURE, _("unable to rewind swap-device"));
ff3bed80
KZ
406
407 memset(buf, 0, sizeof(buf));
408 if (write_all(fd, buf, sizeof(buf)))
00a7d0d2 409 errx(EXIT_FAILURE, _("unable to erase bootbits sectors"));
979f1dd5
KZ
410#ifdef HAVE_LIBBLKID
411 /*
412 * Wipe rest of the device
413 */
414 if (!pr)
415 pr = new_prober(fd);
416
417 blkid_probe_enable_superblocks(pr, 1);
418 blkid_probe_enable_partitions(pr, 0);
c1f1b301 419 blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_MAGIC|BLKID_SUBLKS_TYPE);
979f1dd5 420
c1f1b301
MB
421 while (blkid_do_probe(pr) == 0) {
422 if (blkid_probe_lookup_value(pr, "TYPE", &data, NULL) == 0 && data)
423 warnx(_("%s: warning: wiping old %s signature."), devname, data);
979f1dd5 424 blkid_do_wipe(pr, 0);
c1f1b301 425 }
979f1dd5
KZ
426#endif
427 } else {
428 warnx(_("%s: warning: don't erase bootbits sectors"),
429 devname);
430 if (type)
431 fprintf(stderr, _(" (%s partition table detected). "), type);
979f1dd5
KZ
432 else
433 fprintf(stderr, _(" (compiled without libblkid). "));
8c219bf4 434 fprintf(stderr, _("Use -f to force.\n"));
ff3bed80 435 }
979f1dd5
KZ
436#ifdef HAVE_LIBBLKID
437 blkid_free_probe(pr);
438#endif
ff3bed80
KZ
439}
440
eb63b9b8 441int
f2704664 442main(int argc, char **argv) {
6dbe3af9 443 struct stat statbuf;
3e16599a 444 struct swap_header_v1_2 *hdr;
e079c4e6 445 int c;
99e6d525
HD
446 unsigned long long maxpages;
447 unsigned long long goodpages;
448 unsigned long long sz;
1d4ad1de 449 off_t offset;
5c36a0eb 450 int force = 0;
33fb5cfd 451 int version = 1;
eb63b9b8 452 char *block_count = 0;
756bfd01 453 char *opt_label = NULL;
f88c89db 454 unsigned char *uuid = NULL;
766dd757 455#ifdef HAVE_LIBUUID
7b241808 456 const char *opt_uuid = NULL;
756bfd01
KZ
457 uuid_t uuid_dat;
458#endif
6c7d5ae9 459 static const struct option longopts[] = {
e079c4e6
SK
460 { "check", no_argument, 0, 'c' },
461 { "force", no_argument, 0, 'f' },
462 { "pagesize", required_argument, 0, 'p' },
463 { "label", required_argument, 0, 'L' },
464 { "swapversion", required_argument, 0, 'v' },
465 { "uuid", required_argument, 0, 'U' },
466 { "version", no_argument, 0, 'V' },
467 { "help", no_argument, 0, 'h' },
468 { NULL, 0, 0, 0 }
469 };
eb63b9b8 470
7eda085c
KZ
471 setlocale(LC_ALL, "");
472 bindtextdomain(PACKAGE, LOCALEDIR);
473 textdomain(PACKAGE);
45ca68ec 474 atexit(close_stdout);
5c36a0eb 475
e079c4e6
SK
476 while((c = getopt_long(argc, argv, "cfp:L:v:U:Vh", longopts, NULL)) != -1) {
477 switch (c) {
478 case 'c':
479 check=1;
480 break;
481 case 'f':
482 force=1;
483 break;
484 case 'p':
8c219bf4 485 user_pagesize = strtou32_or_err(optarg, _("parsing page size failed"));
e079c4e6
SK
486 break;
487 case 'L':
488 opt_label = optarg;
489 break;
490 case 'v':
8c219bf4 491 version = strtos32_or_err(optarg, _("parsing version number failed"));
e079c4e6
SK
492 break;
493 case 'U':
93bf0f28 494#ifdef HAVE_LIBUUID
e079c4e6 495 opt_uuid = optarg;
93bf0f28 496#else
4e096801 497 warnx(_("warning: ignoring -U (UUIDs are unsupported by %s)"),
e079c4e6 498 program_invocation_short_name);
93bf0f28 499#endif
e079c4e6
SK
500 break;
501 case 'V':
33fb5cfd 502 printf(UTIL_LINUX_VERSION);
e079c4e6
SK
503 exit(EXIT_SUCCESS);
504 case 'h':
505 usage(stdout);
506 default:
507 usage(stderr);
508 }
509 }
510 if (optind < argc)
511 device_name = argv[optind++];
512 if (optind < argc)
513 block_count = argv[optind++];
514 if (optind != argc) {
8c219bf4 515 warnx(_("only one device argument is currently supported"));
e079c4e6 516 usage(stderr);
6dbe3af9 517 }
eb63b9b8 518
f2704664 519 if (version != 1)
00a7d0d2 520 errx(EXIT_FAILURE,
4e096801 521 _("swapspace version %d is not supported"), version);
4c85aa3a 522
766dd757 523#ifdef HAVE_LIBUUID
93bf0f28
MS
524 if(opt_uuid) {
525 if (uuid_parse(opt_uuid, uuid_dat) != 0)
8c219bf4 526 errx(EXIT_FAILURE, _("error: parsing UUID failed"));
93bf0f28
MS
527 } else
528 uuid_generate(uuid_dat);
756bfd01
KZ
529 uuid = uuid_dat;
530#endif
531
eb63b9b8
KZ
532 init_signature_page(); /* get pagesize */
533
fd6b7a7f 534 if (!device_name) {
00a7d0d2 535 warnx(_("error: Nowhere to set up swap on?"));
e079c4e6 536 usage(stderr);
fd6b7a7f 537 }
eb63b9b8 538 if (block_count) {
20543e61 539 /* this silly user specified the number of blocks explicitly */
33fb5cfd
KZ
540 uint64_t blks = strtou64_or_err(block_count,
541 _("invalid block count argument"));
20543e61 542 PAGES = blks / (pagesize / 1024);
eb63b9b8 543 }
7eda085c 544 sz = get_size(device_name);
f2704664 545 if (!PAGES)
7eda085c 546 PAGES = sz;
f2704664 547 else if (PAGES > sz && !force) {
00a7d0d2
SK
548 errx(EXIT_FAILURE,
549 _("error: "
550 "size %llu KiB is larger than device size %llu KiB"),
7eda085c 551 PAGES*(pagesize/1024), sz*(pagesize/1024));
5c36a0eb
KZ
552 }
553
99e6d525 554 if (PAGES < MIN_GOODPAGES) {
00a7d0d2
SK
555 warnx(_("error: swap area needs to be at least %ld KiB"),
556 (long)(MIN_GOODPAGES * pagesize/1024));
e079c4e6 557 usage(stderr);
726f69e2 558 }
0e6f4a20 559
ff035f67 560#ifdef __linux__
4c85aa3a 561 if (get_linux_version() >= KERNEL_VERSION(2,3,4))
99e6d525 562 maxpages = UINT_MAX + 1ULL;
8023c83b 563 else if (get_linux_version() >= KERNEL_VERSION(2,2,1))
7eda085c 564 maxpages = V1_MAX_PAGES;
0e6f4a20 565 else
4c85aa3a 566#endif
7eda085c 567 maxpages = V1_OLD_MAX_PAGES;
0e6f4a20 568
5c36a0eb
KZ
569 if (PAGES > maxpages) {
570 PAGES = maxpages;
00a7d0d2
SK
571 warnx(_("warning: truncating swap area to %llu KiB"),
572 PAGES * pagesize / 1024);
726f69e2 573 }
5c36a0eb 574
dceb1f22
PU
575 if (is_mounted(device_name))
576 errx(EXIT_FAILURE, _("error: "
4e096801 577 "%s is mounted; will not make swapspace"),
dceb1f22
PU
578 device_name);
579
20186299
MK
580 if (stat(device_name, &statbuf) < 0) {
581 perror(device_name);
a4d3e778 582 exit(EXIT_FAILURE);
20186299
MK
583 }
584 if (S_ISBLK(statbuf.st_mode))
585 DEV = open(device_name, O_RDWR | O_EXCL);
586 else
587 DEV = open(device_name, O_RDWR);
588
589 if (DEV < 0) {
6dbe3af9 590 perror(device_name);
a4d3e778 591 exit(EXIT_FAILURE);
6dbe3af9 592 }
95f1bdee 593
6dbe3af9
KZ
594 if (!S_ISBLK(statbuf.st_mode))
595 check=0;
95fa64da
DB
596 else if (blkdev_is_misaligned(DEV))
597 warnx(_("warning: %s is misaligned"), device_name);
5c36a0eb 598
4c85aa3a 599 if (check)
5c36a0eb 600 check_blocks();
4c85aa3a 601
c1f1b301 602 wipe_device(DEV, device_name, force);
ff3bed80 603
3e16599a
KZ
604 hdr = (struct swap_header_v1_2 *) signature_page;
605 hdr->version = 1;
606 hdr->last_page = PAGES - 1;
607 hdr->nr_badpages = badpages;
5c36a0eb 608
99e6d525 609 if (badpages > PAGES - MIN_GOODPAGES)
00a7d0d2 610 errx(EXIT_FAILURE, _("Unable to set up swap-space: unreadable"));
4c85aa3a 611
99e6d525 612 goodpages = PAGES - badpages - 1;
4c85aa3a
KZ
613 printf(_("Setting up swapspace version 1, size = %llu KiB\n"),
614 goodpages * pagesize / 1024);
5c36a0eb 615
4c85aa3a
KZ
616 write_signature("SWAPSPACE2");
617 write_uuid_and_label(uuid, opt_label);
756bfd01 618
4c85aa3a 619 offset = 1024;
5c36a0eb 620 if (lseek(DEV, offset, SEEK_SET) != offset)
00a7d0d2 621 errx(EXIT_FAILURE, _("unable to rewind swap-device"));
db83e35c 622 if (write_all(DEV, (char *) signature_page + offset,
00a7d0d2
SK
623 pagesize - offset) == -1)
624 err(EXIT_FAILURE,
625 _("%s: unable to write signature page"),
626 device_name);
5c36a0eb 627
3e18b040 628#ifdef HAVE_LIBSELINUX
4ba66edf 629 if (S_ISREG(statbuf.st_mode) && is_selinux_enabled() > 0) {
3e18b040
KZ
630 security_context_t context_string;
631 security_context_t oldcontext;
632 context_t newcontext;
633
71bf7884 634 if (fgetfilecon(DEV, &oldcontext) < 0) {
00a7d0d2
SK
635 if (errno != ENODATA)
636 err(EXIT_FAILURE,
8d1b0fe2 637 _("%s: unable to obtain selinux file label"),
00a7d0d2 638 device_name);
71bf7884 639 if (matchpathcon(device_name, statbuf.st_mode, &oldcontext))
00a7d0d2 640 errx(EXIT_FAILURE, _("unable to matchpathcon()"));
3e18b040
KZ
641 }
642 if (!(newcontext = context_new(oldcontext)))
00a7d0d2 643 errx(EXIT_FAILURE, _("unable to create new selinux context"));
3e18b040 644 if (context_type_set(newcontext, SELINUX_SWAPFILE_TYPE))
00a7d0d2 645 errx(EXIT_FAILURE, _("couldn't compute selinux context"));
3e18b040
KZ
646
647 context_string = context_str(newcontext);
648
649 if (strcmp(context_string, oldcontext)!=0) {
00a7d0d2
SK
650 if (fsetfilecon(DEV, context_string))
651 err(EXIT_FAILURE, _("unable to relabel %s to %s"),
652 device_name, context_string);
3e18b040
KZ
653 }
654 context_free(newcontext);
655 freecon(oldcontext);
656 }
657#endif
833b7e0d
SK
658 /*
659 * A subsequent swapon() will fail if the signature
660 * is not actually on disk. (This is a kernel bug.)
661 * The fsync() in close_fd() will take care of writing.
662 */
663 if (close_fd(DEV) != 0)
664 err(EXIT_FAILURE, _("write failed"));
a4d3e778 665 return EXIT_SUCCESS;
6dbe3af9 666}