(root)/
util-linux-2.39/
libblkid/
src/
superblocks/
swap.c
       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  
      19  #include "superblocks.h"
      20  
      21  /* linux-2.6/include/linux/swap.h */
      22  struct swap_header_v1_2 {
      23       /*	char		bootbits[1024];	*/ /* Space for disklabel etc. */
      24  	uint32_t	version;
      25  	uint32_t	lastpage;
      26  	uint32_t	nr_badpages;
      27  	unsigned char	uuid[16];
      28  	unsigned char	volume[16];
      29  	uint32_t	padding[117];
      30  	uint32_t	badpages[1];
      31  } __attribute__((packed));
      32  
      33  #define PAGESIZE_MIN	0xff6	/* 4086 (arm, i386, ...) */
      34  #define PAGESIZE_MAX	0xfff6	/* 65526 (ia64) */
      35  
      36  #define TOI_MAGIC_STRING	"\xed\xc3\x02\xe9\x98\x56\xe5\x0c"
      37  #define TOI_MAGIC_STRLEN	(sizeof(TOI_MAGIC_STRING) - 1)
      38  
      39  static void swap_set_info_swap1(blkid_probe pr,
      40  		const struct blkid_idmag *mag,
      41  		const struct swap_header_v1_2 *hdr)
      42  {
      43  	enum BLKID_ENDIANNESS endianness = le32_to_cpu(hdr->version) == 1 ?
      44  		BLKID_ENDIANNESS_LITTLE : BLKID_ENDIANNESS_BIG;
      45  	blkid_probe_set_fsendianness(pr, endianness);
      46  
      47  	uint32_t pagesize = mag->sboff + mag->len;
      48  	blkid_probe_set_fsblocksize(pr, pagesize);
      49  
      50  	uint32_t lastpage = endianness == BLKID_ENDIANNESS_LITTLE ?
      51  		le32_to_cpu(hdr->lastpage) : be32_to_cpu(hdr->lastpage);
      52  	blkid_probe_set_fssize(pr, (uint64_t) pagesize * lastpage);
      53  }
      54  
      55  static int swap_set_info(blkid_probe pr, const struct blkid_idmag *mag,
      56  		const char *version)
      57  {
      58  	struct swap_header_v1_2 *hdr;
      59  
      60  	/* Swap header always located at offset of 1024 bytes */
      61  	hdr = (struct swap_header_v1_2 *) blkid_probe_get_buffer(pr, 1024,
      62  				sizeof(struct swap_header_v1_2));
      63  	if (!hdr)
      64  		return errno ? -errno : 1;
      65  
      66  	/* SWAPSPACE2 - check for wrong version or zeroed pagecount */
      67  	if (strcmp(version, "1") == 0) {
      68  		if (hdr->version != 1 && swab32(hdr->version) != 1) {
      69  			DBG(LOWPROBE, ul_debug("incorrect swap version"));
      70  			return 1;
      71  		}
      72  		if (hdr->lastpage == 0) {
      73  			DBG(LOWPROBE, ul_debug("not set last swap page"));
      74  			return 1;
      75  		}
      76  		swap_set_info_swap1(pr, mag, hdr);
      77  	}
      78  
      79  	/* arbitrary sanity check.. is there any garbage down there? */
      80  	if (hdr->padding[32] == 0 && hdr->padding[33] == 0) {
      81  		if (hdr->volume[0] && blkid_probe_set_label(pr, hdr->volume,
      82  				sizeof(hdr->volume)) < 0)
      83  			return 1;
      84  		if (blkid_probe_set_uuid(pr, hdr->uuid) < 0)
      85  			return 1;
      86  	}
      87  
      88  	blkid_probe_set_version(pr, version);
      89  	return 0;
      90  }
      91  
      92  static int probe_swap(blkid_probe pr, const struct blkid_idmag *mag)
      93  {
      94  	unsigned char *buf;
      95  
      96  	if (!mag)
      97  		return 1;
      98  
      99  	/* TuxOnIce keeps valid swap header at the end of the 1st page */
     100  	buf = blkid_probe_get_buffer(pr, 0, TOI_MAGIC_STRLEN);
     101  	if (!buf)
     102  		return errno ? -errno : 1;
     103  
     104  	if (memcmp(buf, TOI_MAGIC_STRING, TOI_MAGIC_STRLEN) == 0)
     105  		return 1;	/* Ignore swap signature, it's TuxOnIce */
     106  
     107  	if (!memcmp(mag->magic, "SWAP-SPACE", mag->len)) {
     108  		/* swap v0 doesn't support LABEL or UUID */
     109  		blkid_probe_set_version(pr, "0");
     110  		return 0;
     111  
     112  	}
     113  
     114  	if (!memcmp(mag->magic, "SWAPSPACE2", mag->len))
     115  		return swap_set_info(pr, mag, "1");
     116  
     117  	return 1;
     118  }
     119  
     120  static int probe_swsuspend(blkid_probe pr, const struct blkid_idmag *mag)
     121  {
     122  	if (!mag)
     123  		return 1;
     124  	if (!memcmp(mag->magic, "S1SUSPEND", mag->len))
     125  		return swap_set_info(pr, mag, "s1suspend");
     126  	if (!memcmp(mag->magic, "S2SUSPEND", mag->len))
     127  		return swap_set_info(pr, mag, "s2suspend");
     128  	if (!memcmp(mag->magic, "ULSUSPEND", mag->len))
     129  		return swap_set_info(pr, mag, "ulsuspend");
     130  	if (!memcmp(mag->magic, TOI_MAGIC_STRING, TOI_MAGIC_STRLEN))
     131  		return swap_set_info(pr, mag, "tuxonice");
     132  	if (!memcmp(mag->magic, "LINHIB0001", mag->len))
     133  		return swap_set_info(pr, mag, "linhib0001");
     134  
     135  	return 1;	/* no signature detected */
     136  }
     137  
     138  const struct blkid_idinfo swap_idinfo =
     139  {
     140  	.name		= "swap",
     141  	.usage		= BLKID_USAGE_OTHER,
     142  	.probefunc	= probe_swap,
     143  	.minsz		= 10 * 4096,	/* 10 pages */
     144  	.magics		=
     145  	{
     146  		{ .magic = "SWAP-SPACE", .len = 10, .sboff = 0xff6 },
     147  		{ .magic = "SWAPSPACE2", .len = 10, .sboff = 0xff6 },
     148  		{ .magic = "SWAP-SPACE", .len = 10, .sboff = 0x1ff6 },
     149  		{ .magic = "SWAPSPACE2", .len = 10, .sboff = 0x1ff6 },
     150  		{ .magic = "SWAP-SPACE", .len = 10, .sboff = 0x3ff6 },
     151  		{ .magic = "SWAPSPACE2", .len = 10, .sboff = 0x3ff6 },
     152  		{ .magic = "SWAP-SPACE", .len = 10, .sboff = 0x7ff6 },
     153  		{ .magic = "SWAPSPACE2", .len = 10, .sboff = 0x7ff6 },
     154  		{ .magic = "SWAP-SPACE", .len = 10, .sboff = 0xfff6 },
     155  		{ .magic = "SWAPSPACE2", .len = 10, .sboff = 0xfff6 },
     156  		{ NULL }
     157  	}
     158  };
     159  
     160  
     161  const struct blkid_idinfo swsuspend_idinfo =
     162  {
     163  	.name		= "swsuspend",
     164  	.usage		= BLKID_USAGE_OTHER,
     165  	.probefunc	= probe_swsuspend,
     166  	.minsz		= 10 * 4096,	/* 10 pages */
     167  	.magics		=
     168  	{
     169  		{ .magic = TOI_MAGIC_STRING, .len = TOI_MAGIC_STRLEN },
     170  		{ .magic = "S1SUSPEND", .len = 9, .sboff = 0xff6 },
     171  		{ .magic = "S2SUSPEND", .len = 9, .sboff = 0xff6 },
     172  		{ .magic = "ULSUSPEND", .len = 9, .sboff = 0xff6 },
     173  		{ .magic = "LINHIB0001", .len = 10, .sboff = 0xff6 },
     174  
     175  		{ .magic = "S1SUSPEND", .len = 9, .sboff = 0x1ff6 },
     176  		{ .magic = "S2SUSPEND", .len = 9, .sboff = 0x1ff6 },
     177  		{ .magic = "ULSUSPEND", .len = 9, .sboff = 0x1ff6 },
     178  		{ .magic = "LINHIB0001", .len = 10, .sboff = 0x1ff6 },
     179  
     180  		{ .magic = "S1SUSPEND", .len = 9, .sboff = 0x3ff6 },
     181  		{ .magic = "S2SUSPEND", .len = 9, .sboff = 0x3ff6 },
     182  		{ .magic = "ULSUSPEND", .len = 9, .sboff = 0x3ff6 },
     183  		{ .magic = "LINHIB0001", .len = 10, .sboff = 0x3ff6 },
     184  
     185  		{ .magic = "S1SUSPEND", .len = 9, .sboff = 0x7ff6 },
     186  		{ .magic = "S2SUSPEND", .len = 9, .sboff = 0x7ff6 },
     187  		{ .magic = "ULSUSPEND", .len = 9, .sboff = 0x7ff6 },
     188  		{ .magic = "LINHIB0001", .len = 10, .sboff = 0x7ff6 },
     189  
     190  		{ .magic = "S1SUSPEND", .len = 9, .sboff = 0xfff6 },
     191  		{ .magic = "S2SUSPEND", .len = 9, .sboff = 0xfff6 },
     192  		{ .magic = "ULSUSPEND", .len = 9, .sboff = 0xfff6 },
     193  		{ .magic = "LINHIB0001", .len = 10, .sboff = 0xfff6 },
     194  		{ NULL }
     195  	}
     196  };