]> git.ipfire.org Git - thirdparty/util-linux.git/blob - disk-utils/mkswap.c
mkswap: default to V1 in any case
[thirdparty/util-linux.git] / disk-utils / mkswap.c
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 *
11 * Usage: mkswap [-c] [-vN] [-f] device [size-in-blocks]
12 *
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.
16 *
17 * The device may be a block device or an image of one, but this isn't
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.
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.
26 * V1_MAX_PAGES fixes, jj, 990325.
27 * sparc64 fixes, jj, 000219.
28 *
29 * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
30 * - added Native Language Support
31 *
32 */
33
34 #include <stdio.h>
35 #include <unistd.h>
36 #include <string.h>
37 #include <fcntl.h>
38 #include <stdlib.h>
39 #include <mntent.h>
40 #include <sys/ioctl.h> /* for _IO */
41 #include <sys/utsname.h>
42 #include <sys/stat.h>
43 #include <errno.h>
44 #ifdef HAVE_LIBSELINUX
45 #include <selinux/selinux.h>
46 #include <selinux/context.h>
47 #endif
48
49 #include "swapheader.h"
50 #include "xstrncpy.h"
51 #include "nls.h"
52
53 #ifdef HAVE_LIBUUID
54 #include <uuid/uuid.h>
55 #endif
56
57 #ifndef _IO
58 /* pre-1.3.45 */
59 #define BLKGETSIZE 0x1260
60 #else
61 /* same on i386, m68k, arm; different on alpha, mips, sparc, ppc */
62 #define BLKGETSIZE _IO(0x12,96)
63 #endif
64
65 static char * program_name = "mkswap";
66 static char * device_name = NULL;
67 static int DEV = -1;
68 static unsigned long PAGES = 0;
69 static unsigned long badpages = 0;
70 static int check = 0;
71 static int version = -1;
72
73 #define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
74
75 #define SELINUX_SWAPFILE_TYPE "swapfile_t"
76
77 static int
78 linux_version_code(void) {
79 struct utsname my_utsname;
80 int p, q, r;
81
82 if (uname(&my_utsname) == 0) {
83 p = atoi(strtok(my_utsname.release, "."));
84 q = atoi(strtok(NULL, "."));
85 r = atoi(strtok(NULL, "."));
86 return MAKE_VERSION(p,q,r);
87 }
88 return 0;
89 }
90
91 #ifdef __sparc__
92 # ifdef __arch64__
93 # define is_sparc64() 1
94 # define is_be64() 1
95 # else /* sparc32 */
96 static int
97 is_sparc64(void) {
98 struct utsname un;
99 static int sparc64 = -1;
100
101 if (sparc64 != -1) return sparc64;
102 sparc64 = 0;
103
104 if (uname(&un) < 0) return 0;
105 if (! strcmp(un.machine, "sparc64")) {
106 sparc64 = 1;
107 return 1;
108 }
109 if (strcmp(un.machine, "sparc"))
110 return 0; /* Should not happen */
111
112 #ifdef HAVE_PERSONALITY
113 {
114 extern int personality(unsigned long);
115 int oldpers;
116 #define PERS_LINUX 0x00000000
117 #define PERS_LINUX_32BIT 0x00800000
118 #define PERS_LINUX32 0x00000008
119
120 oldpers = personality(PERS_LINUX_32BIT);
121 if (oldpers != -1) {
122 if (personality(PERS_LINUX) != -1) {
123 uname(&un);
124 if (! strcmp(un.machine, "sparc64")) {
125 sparc64 = 1;
126 oldpers = PERS_LINUX32;
127 }
128 }
129 personality(oldpers);
130 }
131 }
132 #endif
133
134 return sparc64;
135 }
136 # define is_be64() is_sparc64()
137 # endif /* sparc32 */
138 #else /* !sparc */
139 # define is_be64() 0
140 #endif
141
142 /*
143 * The definition of the union swap_header uses the kernel constant PAGE_SIZE.
144 * Unfortunately, on some architectures this depends on the hardware model, and
145 * can only be found at run time -- we use getpagesize(), so that we do not
146 * need separate binaries e.g. for sun4, sun4c/d/m and sun4u.
147 *
148 * Even more unfortunately, getpagesize() does not always return the right
149 * information. For example, libc4, libc5 and glibc 2.0 do not use the system
150 * call but invent a value themselves (EXEC_PAGESIZE or NBPG * CLSIZE or NBPC),
151 * and thus it may happen that e.g. on a sparc kernel PAGE_SIZE=4096 and
152 * getpagesize() returns 8192.
153 *
154 * What to do? Let us allow the user to specify the pagesize explicitly.
155 *
156 * Update 05-Feb-2007 (kzak):
157 * - use sysconf(_SC_PAGESIZE) to be consistent with the rest of
158 * util-linux code. It is the standardized and preferred way of
159 * querying page size.
160 */
161 static int user_pagesize;
162 static int pagesize;
163 static unsigned long *signature_page;
164 struct swap_header_v1 *p;
165
166 static void
167 init_signature_page(void) {
168
169 int kernel_pagesize = pagesize = (int) sysconf(_SC_PAGESIZE);
170
171 if (user_pagesize) {
172 if ((user_pagesize & (user_pagesize-1)) ||
173 user_pagesize < 1024) {
174 fprintf(stderr, _("Bad user-specified page size %d\n"),
175 user_pagesize);
176 exit(1);
177 }
178 pagesize = user_pagesize;
179 }
180
181 if (user_pagesize && user_pagesize != kernel_pagesize)
182 fprintf(stderr, _("Using user-specified page size %d, "
183 "instead of the system value %d\n"),
184 pagesize, kernel_pagesize);
185
186 signature_page = (unsigned long *) malloc(pagesize);
187 memset(signature_page, 0, pagesize);
188 p = (struct swap_header_v1 *) signature_page;
189 }
190
191 static void
192 write_signature(char *sig) {
193 char *sp = (char *) signature_page;
194
195 strncpy(sp+pagesize-10, sig, 10);
196 }
197
198 #if 0
199 static int
200 tohex(int a) {
201 return ((a < 10) ? '0'+a : 'a'+a-10);
202 }
203
204 static void
205 uuid_unparse(unsigned char *uuid, char *s) {
206 int i;
207
208 for (i=0; i<16; i++) {
209 if (i == 4 || i == 6 || i == 8 || i == 10)
210 *s++ = '-';
211 *s++ = tohex((uuid[i] >> 4) & 0xf);
212 *s++ = tohex(uuid[i] & 0xf);
213 }
214 *s = 0;
215 }
216 #endif
217
218 static void
219 write_uuid_and_label(char *uuid, char *volume_name) {
220 struct swap_header_v1_2 *h;
221
222 /* Sanity check */
223 if (sizeof(struct swap_header_v1) !=
224 sizeof(struct swap_header_v1_2)) {
225 fprintf(stderr,
226 _("Bad swap header size, no label written.\n"));
227 return;
228 }
229
230 h = (struct swap_header_v1_2 *) signature_page;
231 if (uuid)
232 memcpy(h->uuid, uuid, sizeof(h->uuid));
233 if (volume_name) {
234 xstrncpy(h->volume_name, volume_name, sizeof(h->volume_name));
235 if (strlen(volume_name) > strlen(h->volume_name))
236 fprintf(stderr, _("Label was truncated.\n"));
237 }
238 if (uuid || volume_name) {
239 if (volume_name)
240 printf("LABEL=%s, ", h->volume_name);
241 else
242 printf(_("no label, "));
243 #ifdef HAVE_LIBUUID
244 if (uuid) {
245 char uuid_string[37];
246 uuid_unparse(uuid, uuid_string);
247 printf("UUID=%s\n", uuid_string);
248 } else
249 #endif
250 printf(_("no uuid\n"));
251 }
252 }
253
254 /*
255 * Find out what the maximum amount of swap space is that the kernel will
256 * handle. This wouldn't matter if the kernel just used as much of the
257 * swap space as it can handle, but until 2.3.4 it would return an error
258 * to swapon() if the swapspace was too large.
259 */
260 #define V0_MAX_PAGES (8 * (pagesize - 10))
261 /* Before 2.2.0pre9 */
262 #define V1_OLD_MAX_PAGES ((0x7fffffff / pagesize) - 1)
263 /* Since 2.2.0pre9, before 2.3.4:
264 error if nr of pages >= SWP_OFFSET(SWP_ENTRY(0,~0UL))
265 with variations on
266 #define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8))
267 #define SWP_OFFSET(entry) ((entry) >> 8)
268 on the various architectures. Below the result - yuk.
269
270 Machine pagesize SWP_ENTRY SWP_OFFSET bound+1 oldbound+2
271 i386 2^12 o<<8 e>>8 1<<24 1<<19
272 mips 2^12 o<<15 e>>15 1<<17 1<<19
273 alpha 2^13 o<<40 e>>40 1<<24 1<<18
274 m68k 2^12 o<<12 e>>12 1<<20 1<<19
275 sparc 2^{12,13} (o&0x3ffff)<<9 (e>>9)&0x3ffff 1<<18 1<<{19,18}
276 sparc64 2^13 o<<13 e>>13 1<<51 1<<18
277 ppc 2^12 o<<8 e>>8 1<<24 1<<19
278 armo 2^{13,14,15} o<<8 e>>8 1<<24 1<<{18,17,16}
279 armv 2^12 o<<9 e>>9 1<<23 1<<19
280
281 assuming that longs have 64 bits on alpha and sparc64 and 32 bits elsewhere.
282
283 The bad part is that we need to know this since the kernel will
284 refuse a swap space if it is too large.
285 */
286 /* patch from jj - why does this differ from the above? */
287 /* 32bit kernels have a second limitation of 2GB, sparc64 is limited by
288 the size of virtual address space allocation for vmalloc */
289 #if defined(__alpha__)
290 #define V1_MAX_PAGES ((1 << 24) - 1)
291 #elif defined(__mips__)
292 #define V1_MAX_PAGES ((1 << 17) - 1)
293 #elif defined(__sparc__)
294 #define V1_MAX_PAGES (is_sparc64() ? ((3 << 29) - 1) : ((1 << 18) - 1))
295 #elif defined(__ia64__)
296 /*
297 * The actual size will depend on the amount of virtual address space
298 * available to vmalloc the swap map.
299 */
300 #define V1_MAX_PAGES ((1UL << 54) - 1)
301 #else
302 #define V1_MAX_PAGES V1_OLD_MAX_PAGES
303 #endif
304 /* man page now says:
305 The maximum useful size of a swap area now depends on the architecture.
306 It is roughly 2GB on i386, PPC, m68k, ARM, 1GB on sparc, 512MB on mips,
307 128GB on alpha and 3TB on sparc64.
308 */
309
310 #define MAX_BADPAGES ((pagesize-1024-128*sizeof(int)-10)/sizeof(int))
311
312 /*
313 * One more point of lossage - Linux swapspace really is a mess.
314 * The definition of the bitmap used is architecture dependent,
315 * and requires one to know whether the machine is bigendian,
316 * and if so, whether it will use 32-bit or 64-bit units in
317 * test_bit().
318 * davem writes: "... is based upon an unsigned long type of
319 * the cpu and the native endianness".
320 * So, it seems we can write `unsigned long' below.
321 * However, sparc64 uses 64-bit units in the kernel, while
322 * mkswap may have been translated with 32-bit longs. Thus,
323 * we need an explicit test for version 0 swap on sparc64.
324 */
325
326 static void
327 bit_set (unsigned long *addr, unsigned int nr) {
328 unsigned int r, m;
329
330 if(is_be64()) {
331 unsigned long long *bitmap = (unsigned long long *) addr;
332 unsigned long long bitnum = (unsigned long long) nr;
333 unsigned long long rl, ml;
334
335 bitmap += bitnum / (8 * sizeof(long long));
336 rl = *bitmap;
337 ml = 1ULL << (bitnum & (8ULL * sizeof(long long) - 1ULL));
338 *bitmap = rl | ml;
339 return;
340 }
341
342 addr += nr / (8 * sizeof(unsigned long));
343 r = *addr;
344 m = 1 << (nr & (8 * sizeof(unsigned long) - 1));
345 *addr = r | m;
346 }
347
348 static int
349 bit_test_and_clear (unsigned long *addr, unsigned int nr) {
350 unsigned int r, m;
351
352 if(is_be64()) {
353 unsigned long long *bitmap = (unsigned long long *) addr;
354 unsigned long long bitnum = (unsigned long long) nr;
355 unsigned long long rl, ml;
356
357 bitmap += bitnum / (8 * sizeof(long long));
358 rl = *bitmap;
359 ml = 1ULL << (bitnum & (8ULL * sizeof(long long) - 1ULL));
360 *bitmap = rl & ~ml;
361 return ((rl & ml) != 0ULL);
362 }
363
364 addr += nr / (8 * sizeof(unsigned long));
365 r = *addr;
366 m = 1 << (nr & (8 * sizeof(unsigned long) - 1));
367 *addr = r & ~m;
368 return (r & m) != 0;
369 }
370
371 static void
372 usage(void) {
373 fprintf(stderr,
374 _("Usage: %s [-c] [-v0|-v1] [-pPAGESZ] [-L label] /dev/name [blocks]\n"),
375 program_name);
376 exit(1);
377 }
378
379 static void
380 die(const char *str) {
381 fprintf(stderr, "%s: %s\n", program_name, str);
382 exit(1);
383 }
384
385 static void
386 page_ok(int page) {
387 if (version==0)
388 bit_set(signature_page, page);
389 }
390
391 static void
392 page_bad(int page) {
393 if (version == 0)
394 bit_test_and_clear(signature_page, page);
395 else {
396 if (badpages == MAX_BADPAGES)
397 die(_("too many bad pages"));
398 p->badpages[badpages] = page;
399 }
400 badpages++;
401 }
402
403 static void
404 check_blocks(void) {
405 unsigned int current_page;
406 int do_seek = 1;
407 char *buffer;
408
409 buffer = malloc(pagesize);
410 if (!buffer)
411 die(_("Out of memory"));
412 current_page = 0;
413 while (current_page < PAGES) {
414 if (!check) {
415 page_ok(current_page++);
416 continue;
417 }
418 if (do_seek && lseek(DEV,current_page*pagesize,SEEK_SET) !=
419 current_page*pagesize)
420 die(_("seek failed in check_blocks"));
421 if ((do_seek = (pagesize != read(DEV, buffer, pagesize)))) {
422 page_bad(current_page++);
423 continue;
424 }
425 page_ok(current_page++);
426 }
427 if (badpages == 1)
428 printf(_("one bad page\n"));
429 else if (badpages > 1)
430 printf(_("%lu bad pages\n"), badpages);
431 }
432
433 static long
434 valid_offset (int fd, off_t offset) {
435 char ch;
436
437 if (lseek (fd, offset, 0) < 0)
438 return 0;
439 if (read (fd, &ch, 1) < 1)
440 return 0;
441 return 1;
442 }
443
444 static off_t
445 find_size (int fd) {
446 off_t high, low;
447
448 low = 0;
449 for (high = 1; high > 0 && valid_offset (fd, high); high *= 2)
450 low = high;
451 while (low < high - 1) {
452 const off_t mid = (low + high) / 2;
453
454 if (valid_offset (fd, mid))
455 low = mid;
456 else
457 high = mid;
458 }
459 return (low + 1);
460 }
461
462 /* return size in pages, to avoid integer overflow */
463 static unsigned long
464 get_size(const char *file) {
465 int fd;
466 unsigned long size;
467
468 fd = open(file, O_RDONLY);
469 if (fd < 0) {
470 perror(file);
471 exit(1);
472 }
473 if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
474 int sectors_per_page = pagesize/512;
475 size /= sectors_per_page;
476 } else {
477 size = find_size(fd) / pagesize;
478 }
479 close(fd);
480 return size;
481 }
482
483 static int
484 isnzdigit(char c) {
485 return (c >= '1' && c <= '9');
486 }
487
488
489 /*
490 * Check to make certain that our new filesystem won't be created on
491 * an already mounted partition. Code adapted from mke2fs, Copyright
492 * (C) 1994 Theodore Ts'o. Also licensed under GPL.
493 * (C) 2006 Karel Zak -- port to mkswap
494 */
495 static int
496 check_mount(void) {
497 FILE * f;
498 struct mntent * mnt;
499
500 if ((f = setmntent (MOUNTED, "r")) == NULL)
501 return 0;
502 while ((mnt = getmntent (f)) != NULL)
503 if (strcmp (device_name, mnt->mnt_fsname) == 0)
504 break;
505 endmntent (f);
506 if (!mnt)
507 return 0;
508 return 1;
509 }
510
511 int
512 main(int argc, char ** argv) {
513 struct stat statbuf;
514 int i;
515 unsigned long maxpages;
516 unsigned long goodpages;
517 unsigned long sz;
518 off_t offset;
519 int force = 0;
520 char *block_count = 0;
521 char *pp;
522 char *opt_label = NULL;
523 char *uuid = NULL;
524 #ifdef HAVE_LIBUUID
525 uuid_t uuid_dat;
526 #endif
527
528 program_name = (argc && *argv) ? argv[0] : "mkswap";
529 if ((pp = strrchr(program_name, '/')) != NULL)
530 program_name = pp+1;
531
532 setlocale(LC_ALL, "");
533 bindtextdomain(PACKAGE, LOCALEDIR);
534 textdomain(PACKAGE);
535
536 if (argc == 2 &&
537 (!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version"))) {
538 printf(_("%s (%s)\n"), program_name, PACKAGE_STRING);
539 exit(0);
540 }
541
542 for (i=1; i<argc; i++) {
543 if (argv[i][0] == '-') {
544 switch (argv[i][1]) {
545 case 'c':
546 check=1;
547 break;
548 case 'f':
549 force=1;
550 break;
551 case 'p':
552 pp = argv[i]+2;
553 if (!*pp && i+1 < argc)
554 pp = argv[++i];
555 if (isnzdigit(*pp))
556 user_pagesize = atoi(pp);
557 else
558 usage();
559 break;
560 case 'L':
561 pp = argv[i]+2;
562 if (!*pp && i+1 < argc)
563 pp = argv[++i];
564 opt_label = pp;
565 break;
566 case 'v':
567 version = atoi(argv[i]+2);
568 break;
569 default:
570 usage();
571 }
572 } else if (!device_name) {
573 device_name = argv[i];
574 } else if (!block_count) {
575 block_count = argv[i];
576 } else
577 usage();
578 }
579
580 #ifdef HAVE_LIBUUID
581 uuid_generate(uuid_dat);
582 uuid = uuid_dat;
583 #endif
584
585 init_signature_page(); /* get pagesize */
586
587 if (!device_name) {
588 fprintf(stderr,
589 _("%s: error: Nowhere to set up swap on?\n"),
590 program_name);
591 usage();
592 }
593 if (block_count) {
594 /* this silly user specified the number of blocks
595 explicitly */
596 char *tmp;
597 int blocks_per_page = pagesize/1024;
598 PAGES = strtoul(block_count,&tmp,0)/blocks_per_page;
599 if (*tmp)
600 usage();
601 }
602 sz = get_size(device_name);
603 if (!PAGES) {
604 PAGES = sz;
605 } else if (PAGES > sz && !force) {
606 fprintf(stderr,
607 _("%s: error: "
608 "size %lu is larger than device size %lu\n"),
609 program_name,
610 PAGES*(pagesize/1024), sz*(pagesize/1024));
611 exit(1);
612 }
613
614 if (version == -1) {
615 /* labels only for v1 */
616 if (opt_label)
617 version = 1;
618 else
619 /* use version 1 as default, if possible */
620 if (linux_version_code() < MAKE_VERSION(2,1,117))
621 version = 0;
622 else if (pagesize < 2048)
623 version = 0;
624 else
625 version = 1;
626 }
627 if (version != 0 && version != 1) {
628 fprintf(stderr, _("%s: error: unknown version %d\n"),
629 program_name, version);
630 usage();
631 }
632
633 if (PAGES < 10) {
634 fprintf(stderr,
635 _("%s: error: swap area needs to be at least %ldkB\n"),
636 program_name, (long)(10 * pagesize / 1000));
637 usage();
638 }
639
640 if (version == 0)
641 maxpages = V0_MAX_PAGES;
642 else if (linux_version_code() >= MAKE_VERSION(2,3,4))
643 maxpages = PAGES;
644 else if (linux_version_code() >= MAKE_VERSION(2,2,1))
645 maxpages = V1_MAX_PAGES;
646 else
647 maxpages = V1_OLD_MAX_PAGES;
648
649 if (PAGES > maxpages) {
650 PAGES = maxpages;
651 fprintf(stderr,
652 _("%s: warning: truncating swap area to %ldkB\n"),
653 program_name, PAGES * pagesize / 1000);
654 }
655
656 if (opt_label && version == 0) {
657 fprintf(stderr,
658 _("%s: error: label only with v1 swap area\n"),
659 program_name);
660 usage();
661 }
662
663 DEV = open(device_name,O_RDWR);
664 if (DEV < 0 || fstat(DEV, &statbuf) < 0) {
665 perror(device_name);
666 exit(1);
667 }
668
669 /* Want a block device. Probably not /dev/hda or /dev/hdb. */
670 if (!S_ISBLK(statbuf.st_mode))
671 check=0;
672 else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340) {
673 fprintf(stderr,
674 _("%s: error: "
675 "will not try to make swapdevice on '%s'\n"),
676 program_name, device_name);
677 exit(1);
678 } else if (check_mount()) {
679 fprintf(stderr,
680 _("%s: error: "
681 "%s is mounted; will not make swapspace.\n"),
682 program_name, device_name);
683 exit(1);
684 }
685
686 #ifdef __sparc__
687 if (!force && version == 0) {
688 /* Don't overwrite partition table unless forced */
689 unsigned char *buffer = (unsigned char *)signature_page;
690 unsigned short *q, sum;
691
692 if (read(DEV, buffer, 512) != 512)
693 die(_("fatal: first page unreadable"));
694 if (buffer[508] == 0xDA && buffer[509] == 0xBE) {
695 q = (unsigned short *)(buffer + 510);
696 for (sum = 0; q >= (unsigned short *) buffer;)
697 sum ^= *q--;
698 if (!sum) {
699 fprintf(stderr, _("\
700 %s: Device '%s' contains a valid Sun disklabel.\n\
701 This probably means creating v0 swap would destroy your partition table\n\
702 No swap created. If you really want to create swap v0 on that device, use\n\
703 the -f option to force it.\n"),
704 program_name, device_name);
705 exit(1);
706 }
707 }
708 }
709 #endif
710
711 if (version == 0 || check)
712 check_blocks();
713 if (version == 0 && !bit_test_and_clear(signature_page,0))
714 die(_("fatal: first page unreadable"));
715 if (version == 1) {
716 p->version = version;
717 p->last_page = PAGES-1;
718 p->nr_badpages = badpages;
719 }
720
721 goodpages = PAGES - badpages - 1;
722 if ((long) goodpages <= 0)
723 die(_("Unable to set up swap-space: unreadable"));
724 printf(_("Setting up swapspace version %d, size = %llu kB\n"),
725 version, (unsigned long long)goodpages * pagesize / 1000);
726 write_signature((version == 0) ? "SWAP-SPACE" : "SWAPSPACE2");
727
728 if (version == 1)
729 write_uuid_and_label(uuid, opt_label);
730
731 offset = ((version == 0) ? 0 : 1024);
732 if (lseek(DEV, offset, SEEK_SET) != offset)
733 die(_("unable to rewind swap-device"));
734 if (write(DEV,(char*)signature_page+offset, pagesize-offset)
735 != pagesize-offset)
736 die(_("unable to write signature page"));
737
738 /*
739 * A subsequent swapon() will fail if the signature
740 * is not actually on disk. (This is a kernel bug.)
741 */
742 #ifdef HAVE_FSYNC
743 if (fsync(DEV))
744 die(_("fsync failed"));
745 #endif
746
747 #ifdef HAVE_LIBSELINUX
748 if (S_ISREG(statbuf.st_mode) && is_selinux_enabled()) {
749 security_context_t context_string;
750 security_context_t oldcontext;
751 context_t newcontext;
752
753 if ((fgetfilecon(DEV, &oldcontext) < 0) &&
754 (errno != ENODATA)) {
755 fprintf(stderr, _("%s: %s: unable to obtain selinux file label: %s\n"),
756 program_name, device_name,
757 strerror(errno));
758 exit(1);
759 }
760 if (!(newcontext = context_new(oldcontext)))
761 die(_("unable to create new selinux context"));
762 if (context_type_set(newcontext, SELINUX_SWAPFILE_TYPE))
763 die(_("couldn't compute selinux context"));
764
765 context_string = context_str(newcontext);
766
767 if (strcmp(context_string, oldcontext)!=0) {
768 if (fsetfilecon(DEV, context_string)) {
769 fprintf(stderr, _("%s: unable to relabel %s to %s: %s\n"),
770 program_name, device_name,
771 context_string,
772 strerror(errno));
773 exit(1);
774 }
775 }
776 context_free(newcontext);
777 freecon(oldcontext);
778 }
779 #endif
780 return 0;
781 }