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