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