(root)/
util-linux-2.39/
libblkid/
src/
superblocks/
cramfs.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  
      12  #include <stdio.h>
      13  #include <stdlib.h>
      14  #include <unistd.h>
      15  #include <string.h>
      16  #include <stdint.h>
      17  
      18  #include "superblocks.h"
      19  #include "crc32.h"
      20  
      21  struct cramfs_super
      22  {
      23  	uint8_t		magic[4];
      24  	uint32_t	size;
      25  	uint32_t	flags;
      26  	uint32_t	future;
      27  	uint8_t		signature[16];
      28  	struct cramfs_info
      29  	{
      30  		uint32_t	crc;
      31  		uint32_t	edition;
      32  		uint32_t	blocks;
      33  		uint32_t	files;
      34  	} __attribute__((packed)) info;
      35  	uint8_t		name[16];
      36  } __attribute__((packed));
      37  
      38  #define CRAMFS_FLAG_FSID_VERSION_2	0x00000001	/* fsid version #2 */
      39  
      40  static int cramfs_is_little_endian(const struct blkid_idmag *mag)
      41  {
      42  	assert(mag->len == 4);
      43  	return memcmp(mag->magic, "\x45\x3d\xcd\x28", 4) == 0;
      44  }
      45  
      46  static uint32_t cfs32_to_cpu(int le, uint32_t value)
      47  {
      48  	if (le)
      49  		return le32_to_cpu(value);
      50  	else
      51  		return be32_to_cpu(value);
      52  }
      53  
      54  static int cramfs_verify_csum(blkid_probe pr, const struct blkid_idmag *mag,
      55  		struct cramfs_super *cs, int le)
      56  {
      57  	uint32_t crc, expected, csummed_size;
      58  	unsigned char *csummed;
      59  
      60  	expected = cfs32_to_cpu(le, cs->info.crc);
      61  	csummed_size = cfs32_to_cpu(le, cs->size);
      62  
      63  	if (csummed_size > (1 << 16)
      64  	    || csummed_size < sizeof(struct cramfs_super))
      65  		return 0;
      66  
      67  	csummed = blkid_probe_get_sb_buffer(pr, mag, csummed_size);
      68  	if (!csummed)
      69  		return 0;
      70  	memset(csummed + offsetof(struct cramfs_super, info.crc), 0, sizeof(uint32_t));
      71  
      72  	crc = ~ul_crc32(~0LL, csummed, csummed_size);
      73  
      74  	return blkid_probe_verify_csum(pr, crc, expected);
      75  }
      76  
      77  static int probe_cramfs(blkid_probe pr, const struct blkid_idmag *mag)
      78  {
      79  	struct cramfs_super *cs;
      80  
      81  	cs = blkid_probe_get_sb(pr, mag, struct cramfs_super);
      82  	if (!cs)
      83  		return errno ? -errno : 1;
      84  
      85  	int le = cramfs_is_little_endian(mag);
      86  	int v2 = cfs32_to_cpu(le, cs->flags) & CRAMFS_FLAG_FSID_VERSION_2;
      87  
      88  	if (v2 && !cramfs_verify_csum(pr, mag, cs, le))
      89  		return 1;
      90  
      91  	blkid_probe_set_label(pr, cs->name, sizeof(cs->name));
      92  	blkid_probe_set_fssize(pr, cfs32_to_cpu(le, cs->size));
      93  	blkid_probe_sprintf_version(pr, "%d", v2 ? 2 : 1);
      94  	blkid_probe_set_fsendianness(pr,
      95  			le ? BLKID_ENDIANNESS_LITTLE : BLKID_ENDIANNESS_BIG);
      96  	return 0;
      97  }
      98  
      99  const struct blkid_idinfo cramfs_idinfo =
     100  {
     101  	.name		= "cramfs",
     102  	.usage		= BLKID_USAGE_FILESYSTEM,
     103  	.probefunc	= probe_cramfs,
     104  	.magics		=
     105  	{
     106  		{ .magic = "\x45\x3d\xcd\x28", .len = 4 },
     107  		{ .magic = "\x28\xcd\x3d\x45", .len = 4 },
     108  		{ NULL }
     109  	}
     110  };
     111  
     112