2
0

swap.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. /*
  2. * Copyright (C) 1999 by Andries Brouwer
  3. * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
  4. * Copyright (C) 2001 by Andreas Dilger
  5. * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
  6. * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
  7. *
  8. * This file may be redistributed under the terms of the
  9. * GNU Lesser General Public License.
  10. */
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <unistd.h>
  14. #include <string.h>
  15. #include <errno.h>
  16. #include <ctype.h>
  17. #include <stdint.h>
  18. #include "superblocks.h"
  19. /* linux-2.6/include/linux/swap.h */
  20. struct swap_header_v1_2 {
  21. /* char bootbits[1024]; */ /* Space for disklabel etc. */
  22. uint32_t version;
  23. uint32_t lastpage;
  24. uint32_t nr_badpages;
  25. unsigned char uuid[16];
  26. unsigned char volume[16];
  27. uint32_t padding[117];
  28. uint32_t badpages[1];
  29. } __attribute__((packed));
  30. #define PAGESIZE_MIN 0xff6 /* 4086 (arm, i386, ...) */
  31. #define PAGESIZE_MAX 0xfff6 /* 65526 (ia64) */
  32. #define TOI_MAGIC_STRING "\xed\xc3\x02\xe9\x98\x56\xe5\x0c"
  33. #define TOI_MAGIC_STRLEN (sizeof(TOI_MAGIC_STRING) - 1)
  34. static int swap_set_info(blkid_probe pr, const char *version)
  35. {
  36. struct swap_header_v1_2 *hdr;
  37. /* Swap header always located at offset of 1024 bytes */
  38. hdr = (struct swap_header_v1_2 *) blkid_probe_get_buffer(pr, 1024,
  39. sizeof(struct swap_header_v1_2));
  40. if (!hdr)
  41. return errno ? -errno : 1;
  42. /* SWAPSPACE2 - check for wrong version or zeroed pagecount */
  43. if (strcmp(version, "1") == 0) {
  44. if (hdr->version != 1 && swab32(hdr->version) != 1) {
  45. DBG(LOWPROBE, ul_debug("incorrect swap version"));
  46. return 1;
  47. }
  48. if (hdr->lastpage == 0) {
  49. DBG(LOWPROBE, ul_debug("not set last swap page"));
  50. return 1;
  51. }
  52. }
  53. /* arbitrary sanity check.. is there any garbage down there? */
  54. if (hdr->padding[32] == 0 && hdr->padding[33] == 0) {
  55. if (hdr->volume[0] && blkid_probe_set_label(pr, hdr->volume,
  56. sizeof(hdr->volume)) < 0)
  57. return 1;
  58. if (blkid_probe_set_uuid(pr, hdr->uuid) < 0)
  59. return 1;
  60. }
  61. blkid_probe_set_version(pr, version);
  62. return 0;
  63. }
  64. static int probe_swap(blkid_probe pr, const struct blkid_idmag *mag)
  65. {
  66. unsigned char *buf;
  67. if (!mag)
  68. return 1;
  69. /* TuxOnIce keeps valid swap header at the end of the 1st page */
  70. buf = blkid_probe_get_buffer(pr, 0, TOI_MAGIC_STRLEN);
  71. if (!buf)
  72. return errno ? -errno : 1;
  73. if (memcmp(buf, TOI_MAGIC_STRING, TOI_MAGIC_STRLEN) == 0)
  74. return 1; /* Ignore swap signature, it's TuxOnIce */
  75. if (!memcmp(mag->magic, "SWAP-SPACE", mag->len)) {
  76. /* swap v0 doesn't support LABEL or UUID */
  77. blkid_probe_set_version(pr, "0");
  78. return 0;
  79. } else if (!memcmp(mag->magic, "SWAPSPACE2", mag->len))
  80. return swap_set_info(pr, "1");
  81. return 1;
  82. }
  83. static int probe_swsuspend(blkid_probe pr, const struct blkid_idmag *mag)
  84. {
  85. if (!mag)
  86. return 1;
  87. if (!memcmp(mag->magic, "S1SUSPEND", mag->len))
  88. return swap_set_info(pr, "s1suspend");
  89. if (!memcmp(mag->magic, "S2SUSPEND", mag->len))
  90. return swap_set_info(pr, "s2suspend");
  91. if (!memcmp(mag->magic, "ULSUSPEND", mag->len))
  92. return swap_set_info(pr, "ulsuspend");
  93. if (!memcmp(mag->magic, TOI_MAGIC_STRING, mag->len))
  94. return swap_set_info(pr, "tuxonice");
  95. if (!memcmp(mag->magic, "LINHIB0001", mag->len))
  96. return swap_set_info(pr, "linhib0001");
  97. return 1; /* no signature detected */
  98. }
  99. const struct blkid_idinfo swap_idinfo =
  100. {
  101. .name = "swap",
  102. .usage = BLKID_USAGE_OTHER,
  103. .probefunc = probe_swap,
  104. .minsz = 10 * 4096, /* 10 pages */
  105. .magics =
  106. {
  107. { "SWAP-SPACE", 10, 0, 0xff6 },
  108. { "SWAPSPACE2", 10, 0, 0xff6 },
  109. { "SWAP-SPACE", 10, 0, 0x1ff6 },
  110. { "SWAPSPACE2", 10, 0, 0x1ff6 },
  111. { "SWAP-SPACE", 10, 0, 0x3ff6 },
  112. { "SWAPSPACE2", 10, 0, 0x3ff6 },
  113. { "SWAP-SPACE", 10, 0, 0x7ff6 },
  114. { "SWAPSPACE2", 10, 0, 0x7ff6 },
  115. { "SWAP-SPACE", 10, 0, 0xfff6 },
  116. { "SWAPSPACE2", 10, 0, 0xfff6 },
  117. { NULL }
  118. }
  119. };
  120. const struct blkid_idinfo swsuspend_idinfo =
  121. {
  122. .name = "swsuspend",
  123. .usage = BLKID_USAGE_OTHER,
  124. .probefunc = probe_swsuspend,
  125. .minsz = 10 * 4096, /* 10 pages */
  126. .magics =
  127. {
  128. { TOI_MAGIC_STRING, TOI_MAGIC_STRLEN, 0, 0 },
  129. { "S1SUSPEND", 9, 0, 0xff6 },
  130. { "S2SUSPEND", 9, 0, 0xff6 },
  131. { "ULSUSPEND", 9, 0, 0xff6 },
  132. { "LINHIB0001",10,0, 0xff6 },
  133. { "S1SUSPEND", 9, 0, 0x1ff6 },
  134. { "S2SUSPEND", 9, 0, 0x1ff6 },
  135. { "ULSUSPEND", 9, 0, 0x1ff6 },
  136. { "LINHIB0001",10,0, 0x1ff6 },
  137. { "S1SUSPEND", 9, 0, 0x3ff6 },
  138. { "S2SUSPEND", 9, 0, 0x3ff6 },
  139. { "ULSUSPEND", 9, 0, 0x3ff6 },
  140. { "LINHIB0001",10,0, 0x3ff6 },
  141. { "S1SUSPEND", 9, 0, 0x7ff6 },
  142. { "S2SUSPEND", 9, 0, 0x7ff6 },
  143. { "ULSUSPEND", 9, 0, 0x7ff6 },
  144. { "LINHIB0001",10,0, 0x7ff6 },
  145. { "S1SUSPEND", 9, 0, 0xfff6 },
  146. { "S2SUSPEND", 9, 0, 0xfff6 },
  147. { "ULSUSPEND", 9, 0, 0xfff6 },
  148. { "LINHIB0001",10,0, 0xfff6 },
  149. { NULL }
  150. }
  151. };