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