mkswap.c 3.5 KB

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