mkswap.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. /* vi: set sw=4 ts=4: */
  2. /* mkswap.c - format swap device (Linux v1 only)
  3. *
  4. * Copyright 2006 Rob Landley <rob@landley.net>
  5. *
  6. * Licensed under GPLv2, see file LICENSE in this source tree.
  7. */
  8. #include "libbb.h"
  9. #if ENABLE_SELINUX
  10. static void mkswap_selinux_setcontext(int fd, const char *path)
  11. {
  12. struct stat stbuf;
  13. if (!is_selinux_enabled())
  14. return;
  15. xfstat(fd, &stbuf, path);
  16. if (S_ISREG(stbuf.st_mode)) {
  17. security_context_t newcon;
  18. security_context_t oldcon = NULL;
  19. context_t context;
  20. if (fgetfilecon(fd, &oldcon) < 0) {
  21. if (errno != ENODATA)
  22. goto error;
  23. if (matchpathcon(path, stbuf.st_mode, &oldcon) < 0)
  24. goto error;
  25. }
  26. context = context_new(oldcon);
  27. if (!context || context_type_set(context, "swapfile_t"))
  28. goto error;
  29. newcon = context_str(context);
  30. if (!newcon)
  31. goto error;
  32. /* fsetfilecon_raw is hidden */
  33. if (strcmp(oldcon, newcon) != 0 && fsetfilecon(fd, newcon) < 0)
  34. goto error;
  35. if (ENABLE_FEATURE_CLEAN_UP) {
  36. context_free(context);
  37. freecon(oldcon);
  38. }
  39. }
  40. return;
  41. error:
  42. bb_perror_msg_and_die("SELinux relabeling failed");
  43. }
  44. #else
  45. # define mkswap_selinux_setcontext(fd, path) ((void)0)
  46. #endif
  47. /* from Linux 2.6.23 */
  48. /*
  49. * Magic header for a swap area. ... Note that the first
  50. * kilobyte is reserved for boot loader or disk label stuff.
  51. */
  52. struct swap_header_v1 {
  53. /* char bootbits[1024]; Space for disklabel etc. */
  54. uint32_t version; /* second kbyte, word 0 */
  55. uint32_t last_page; /* 1 */
  56. uint32_t nr_badpages; /* 2 */
  57. char sws_uuid[16]; /* 3,4,5,6 */
  58. char sws_volume[16]; /* 7,8,9,10 */
  59. uint32_t padding[117]; /* 11..127 */
  60. uint32_t badpages[1]; /* 128 */
  61. /* total 129 32-bit words in 2nd kilobyte */
  62. } FIX_ALIASING;
  63. #define NWORDS 129
  64. #define hdr ((struct swap_header_v1*)bb_common_bufsiz1)
  65. struct BUG_sizes {
  66. char swap_header_v1_wrong[sizeof(*hdr) != (NWORDS * 4) ? -1 : 1];
  67. char bufsiz1_is_too_small[COMMON_BUFSIZE < (NWORDS * 4) ? -1 : 1];
  68. };
  69. /* Stored without terminating NUL */
  70. static const char SWAPSPACE2[sizeof("SWAPSPACE2")-1] ALIGN1 = "SWAPSPACE2";
  71. int mkswap_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  72. int mkswap_main(int argc UNUSED_PARAM, char **argv)
  73. {
  74. int fd;
  75. unsigned pagesize;
  76. off_t len;
  77. const char *label = "";
  78. opt_complementary = "-1"; /* at least one param */
  79. /* TODO: -p PAGESZ, -U UUID */
  80. getopt32(argv, "L:", &label);
  81. argv += optind;
  82. fd = xopen(argv[0], O_WRONLY);
  83. /* Figure out how big the device is */
  84. len = get_volume_size_in_bytes(fd, argv[1], 1024, /*extend:*/ 1);
  85. pagesize = getpagesize();
  86. len -= pagesize;
  87. /* Announce our intentions */
  88. printf("Setting up swapspace version 1, size = %"OFF_FMT"u bytes\n", len);
  89. mkswap_selinux_setcontext(fd, argv[0]);
  90. /* hdr is zero-filled so far. Clear the first kbyte, or else
  91. * mkswap-ing former FAT partition does NOT erase its signature.
  92. *
  93. * util-linux-ng 2.17.2 claims to erase it only if it does not see
  94. * a partition table and is not run on whole disk. -f forces it.
  95. */
  96. xwrite(fd, hdr, 1024);
  97. /* Fill the header. */
  98. hdr->version = 1;
  99. hdr->last_page = (uoff_t)len / pagesize;
  100. if (ENABLE_FEATURE_MKSWAP_UUID) {
  101. char uuid_string[32];
  102. generate_uuid((void*)hdr->sws_uuid);
  103. bin2hex(uuid_string, hdr->sws_uuid, 16);
  104. /* f.e. UUID=dfd9c173-be52-4d27-99a5-c34c6c2ff55f */
  105. printf("UUID=%.8s" "-%.4s-%.4s-%.4s-%.12s\n",
  106. uuid_string,
  107. uuid_string+8,
  108. uuid_string+8+4,
  109. uuid_string+8+4+4,
  110. uuid_string+8+4+4+4
  111. );
  112. }
  113. safe_strncpy(hdr->sws_volume, label, 16);
  114. /* Write the header. Sync to disk because some kernel versions check
  115. * signature on disk (not in cache) during swapon. */
  116. xwrite(fd, hdr, NWORDS * 4);
  117. xlseek(fd, pagesize - 10, SEEK_SET);
  118. xwrite(fd, SWAPSPACE2, 10);
  119. fsync(fd);
  120. if (ENABLE_FEATURE_CLEAN_UP)
  121. close(fd);
  122. return 0;
  123. }