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