Ejemplo n.º 1
0
/* read super block and bitmaps. fixme: only 4k blocks, pre-journaled format
   is refused */
reiserfs_filsys_t reiserfs_open (char * filename, int flags, int *error, void * vp)
{
    reiserfs_filsys_t fs;
    struct buffer_head * bh;
    struct reiserfs_super_block * rs;
    int fd, i;
    
    fd = open (filename, flags | O_LARGEFILE);
    if (fd == -1) {
	if (error)
	    *error = errno;
	return 0;
    }

    fs = getmem (sizeof (*fs));
    fs->s_dev = fd;
    fs->s_vp = vp;
    asprintf (&fs->file_name, "%s", filename);

    /* reiserfs super block is either in 16-th or in 2-nd 4k block of the
       device */
    for (i = 16; i > 0; i -= 14) {
	bh = bread (fd, i, 4096);
	if (!bh) {
	    reiserfs_warning (stderr, "reiserfs_open: bread failed reading block %d\n", i);
	} else {
	    rs = (struct reiserfs_super_block *)bh->b_data;
	    
	    if (is_reiser2fs_magic_string (rs) || is_reiserfs_magic_string (rs))
		goto found;

	    /* reiserfs signature is not found at the i-th 4k block */
	    brelse (bh);
	}
    }

    reiserfs_warning (stderr, "reiserfs_open: neither new nor old reiserfs format "
		      "found on %s\n", filename);
    if (error)
	*error = 0;
    return fs;

 found:

    /* fixme: we could make some check to make sure that super block looks
       correctly */
    fs->s_version = is_reiser2fs_magic_string (rs) ? REISERFS_VERSION_2 :
	REISERFS_VERSION_1;
    fs->s_blocksize = rs_blocksize (rs);
    fs->s_hash_function = code2func (rs_hash (rs));
    SB_BUFFER_WITH_SB (fs) = bh;
    fs->s_rs = rs;
    fs->s_flags = flags; /* O_RDONLY or O_RDWR */
    fs->s_vp = vp;

    reiserfs_read_bitmap_blocks(fs);
	
    return fs;

}
Ejemplo n.º 2
0
static int read_super_block (struct super_block * s, int size, int offset)
{
    struct buffer_head * bh;
    struct reiserfs_super_block * rs;
 

    bh = bread (s->s_dev, offset / size, size);
    if (!bh) {
      printk ("read_super_block: "
              "bread failed (dev %s, block %d, size %d)\n",
              kdevname (s->s_dev), offset / size, size);
      return 1;
    }
 
    rs = (struct reiserfs_super_block *)bh->b_data;
    if (!is_reiserfs_magic_string (rs)) {
      printk ("read_super_block: "
              "can't find a reiserfs filesystem on (dev %s, block %lu, size %d)\n",
              kdevname(s->s_dev), bh->b_blocknr, size);
      brelse (bh);
      return 1;
    }
 
    //
    // ok, reiserfs signature (old or new) found in at the given offset
    //    
    s->s_blocksize = sb_blocksize(rs);
    s->s_blocksize_bits = 0;
    while ((1 << s->s_blocksize_bits) != s->s_blocksize)
	s->s_blocksize_bits ++;

    brelse (bh);
    
    if (s->s_blocksize != size)
	set_blocksize (s->s_dev, s->s_blocksize);

    bh = reiserfs_bread (s, offset / s->s_blocksize, s->s_blocksize);
    if (!bh) {
	printk("read_super_block: "
                "bread failed (dev %s, block %d, size %d)\n",
                kdevname (s->s_dev), offset / size, size);
	return 1;
    }
    
    rs = (struct reiserfs_super_block *)bh->b_data;
    if (!is_reiserfs_magic_string (rs) ||
	sb_blocksize(rs) != s->s_blocksize) {
	printk ("read_super_block: "
		"can't find a reiserfs filesystem on (dev %s, block %lu, size %d)\n",
		kdevname(s->s_dev), bh->b_blocknr, size);
	brelse (bh);
	printk ("read_super_block: can't find a reiserfs filesystem on dev %s.\n", kdevname(s->s_dev));
	return 1;
    }
    /* must check to be sure we haven't pulled an old format super out
    ** of the old format's log.  This is a kludge of a check, but it
    ** will work.  If block we've just read in is inside the
    ** journal for that super, it can't be valid.  
    */
    if (bh->b_blocknr >= sb_journal_block(rs) && 
	bh->b_blocknr < (sb_journal_block(rs) + JOURNAL_BLOCK_COUNT)) {
	brelse(bh) ;
	printk("super-459: read_super_block: "
	       "super found at block %lu is within its own log. "
	       "It must not be of this format type.\n", bh->b_blocknr) ;
	return 1 ;
    }

    if ( rs->s_root_block == -1 ) {
	brelse(bh) ;
	printk("dev %s: Unfinished reiserfsck --rebuild-tree run detected. Please run\n"
	       "reiserfsck --rebuild-tree and wait for a completion. If that fails\n"
	       "get newer reiserfsprogs package\n", kdevname (s->s_dev));
	return 1;
    }

    SB_BUFFER_WITH_SB (s) = bh;
    SB_DISK_SUPER_BLOCK (s) = rs;

    s->s_op = &reiserfs_sops;

    /* new format is limited by the 32 bit wide i_blocks field, want to
    ** be one full block below that.
    */
    s->s_maxbytes = (512LL << 32) - s->s_blocksize ;
    return 0;
}
Ejemplo n.º 3
0
char *fstype(const char *device)
{
    int fd;
    char *type = NULL;
    struct stat64 statbuf;

    /*
     * opening and reading an arbitrary unknown path can have
     * undesired side effects - first check that `device' refers
     * to a block device
     */
    if(
        stat64(device, &statbuf) ||
        !(S_ISBLK(statbuf.st_mode) || S_ISREG(statbuf.st_mode))
    ) {
        return 0;
    }

    fd = open(device, O_RDONLY | O_LARGEFILE);
    /* try harder */
    if(fd < 0 && errno == ENOMEDIUM) fd = open(device, O_RDONLY | O_LARGEFILE);
    if(fd < 0) {
        perror_debug((char *) device);
        return 0;
    }

    /*
     * do seeks and reads in disk order, otherwise a very short
     * partition may cause a failure because of read error
     */

    if(!type) {
        union {
            struct xiafs_super_block xiasb;
            char romfs_magic[8];
            char qnx4fs_magic[10];	/* ignore first 4 bytes */
            long bfs_magic;
            struct ntfs_super_block ntfssb;
            struct fat_super_block fatsb;
            struct xfs_super_block xfsb;
            struct cramfs_super_block cramfssb;
            unsigned char data[512];
        } xsb;

        /* block 0 */
        if(
            lseek(fd, 0, SEEK_SET) == 0 &&
            read(fd, &xsb, sizeof xsb) == sizeof xsb
        ) {
            if(xiafsmagic(xsb.xiasb) == _XIAFS_SUPER_MAGIC) {
                type = "xiafs";
            }
            else if(!strncmp(xsb.romfs_magic, "-rom1fs-", 8)) {
                type = "romfs";
            }
            else if(!strncmp(xsb.xfsb.s_magic, XFS_SUPER_MAGIC, 4)) {
                type = "xfs";
            }
            else if(!strncmp(xsb.qnx4fs_magic+4, "QNX4FS", 6)) {
                type = "qnx4";
            }
            else if(xsb.bfs_magic == 0x1badface) {
                type = "bfs";
            }
            else if(!strncmp(xsb.ntfssb.s_magic, NTFS_SUPER_MAGIC, sizeof xsb.ntfssb.s_magic)) {
                type = "ntfs";
            }
            else if(
                cramfsmagic(xsb.cramfssb) == CRAMFS_SUPER_MAGIC ||
                cramfsmagic(xsb.cramfssb) == CRAMFS_SUPER_MAGIC_BIG
            ) {
                type = "cramfs";
            }
            else if(
                xsb.data[0x1fe] == 0x55 &&
                xsb.data[0x1ff] == 0xaa &&
                xsb.data[0x0b] == 0 &&	/* bytes per sector, bits 0-7 */
                (
                    (	/* FAT12/16 */
                        xsb.data[0x26] == 0x29 && (
                            !strncmp(xsb.fatsb.s_fs, "FAT12   ", 8) ||
                            !strncmp(xsb.fatsb.s_fs, "FAT16   ", 8)
                        )
                    ) ||
                    (	/* FAT32 */
                        xsb.data[0x42] == 0x29 &&
                        !strncmp(xsb.fatsb.s_fs2, "FAT32   ", 8)
                    )
                )
            ) {
                type = "vfat";
            }
        }
    }

    if(!type) {
        char buf[6];

        if(
            lseek(fd, 0, SEEK_SET) == 0 &&
            read(fd, buf, sizeof buf) == sizeof buf
        ) {
            if(!memcmp(buf, "070701", 6) || !memcmp(buf, "\xc7\x71", 2)) type = "cpio";
            else if(!memcmp(buf, "hsqs", 4) || !memcmp(buf, "sqsh", 4)) type = "squashfs";
            else if(!memcmp(buf, "\xed\xab\xee\xdb", 4) && buf[4] >= 3) type = "rpm";
        }
    }

    if(!type) {	/* sector 1 */
        struct sysv_super_block svsb;

        if(
            lseek(fd, 512 , SEEK_SET) == 512 &&
            read(fd, &svsb, sizeof svsb) == sizeof svsb &&
            sysvmagic(svsb) == SYSV_SUPER_MAGIC
        ) {
            type = "sysv";
        }
    }

    if(!type) {	/* block 1 */
        union {
            struct minix_super_block ms;
            struct ext_super_block es;
            struct ext2_super_block e2s;
            struct vxfs_super_block vs;
        } sb;

        if(
            lseek(fd, 1024, SEEK_SET) == 1024 &&
            read(fd, &sb, sizeof sb) == sizeof sb
        ) {
            /*
             * ext2 has magic in little-endian on disk, so "swapped" is
             * superfluous; however, there have existed strange byteswapped
             * PPC ext2 systems
             */
            if(
                ext2magic(sb.e2s) == EXT2_SUPER_MAGIC ||
                ext2magic(sb.e2s) == EXT2_PRE_02B_MAGIC ||
                ext2magic(sb.e2s) == swapped(EXT2_SUPER_MAGIC)
            ) {
                type = "ext2";

                if(
                    (assemble4le(sb.e2s.s_feature_compat) & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
                    assemble4le(sb.e2s.s_journal_inum) != 0
                ) {
                    type = "ext3";

                    if((assemble4le(sb.e2s.s_feature_incompat) & EXT4_FEATURE_INCOMPAT_EXTENTS)) {
                        type = "ext4";
                    }
                }
            }
            else if(
                minixmagic(sb.ms) == MINIX_SUPER_MAGIC ||
                minixmagic(sb.ms) == MINIX_SUPER_MAGIC2 ||
                minixmagic(sb.ms) == MINIX2_SUPER_MAGIC ||
                minixmagic(sb.ms) == MINIX2_SUPER_MAGIC2
            ) {
                type = "minix";
            }
            else if(extmagic(sb.es) == EXT_SUPER_MAGIC) {
                type = "ext";
            }
            else if(vxfsmagic(sb.vs) == VXFS_SUPER_MAGIC) {
                type = "vxfs";
            }
        }
    }

    if(!type) {	/* block 1 */
        struct hfs_super_block hfssb;

        /*
         * also check if block size is equal to 512 bytes,
         * since the hfs driver currently only has support
         * for block sizes of 512 bytes long, and to be
         * more accurate (sb magic is only a short int)
         */
        if(
            lseek(fd, 0x400, SEEK_SET) == 0x400 &&
            read(fd, &hfssb, sizeof hfssb) == sizeof hfssb &&
            (
                (hfsmagic(hfssb) == HFS_SUPER_MAGIC && hfsblksize(hfssb) == 0x20000) ||
                (swapped(hfsmagic(hfssb)) == HFS_SUPER_MAGIC && hfsblksize(hfssb) == 0x200)
            )
        ) {
            type = "hfs";
        }
    }

    if(!type) {	/* block 8 */
        struct ufs_super_block ufssb;

        if(
            lseek(fd, 8192, SEEK_SET) == 8192 &&
            read(fd, &ufssb, sizeof ufssb) == sizeof ufssb &&
            ufsmagic(ufssb) == UFS_SUPER_MAGIC	/* also test swapped version? */
        ) {
            type = "ufs";
        }
    }

    if(!type) {	/* block 8 */
        struct reiserfs_super_block reiserfssb;

        if(
            lseek(fd, REISERFS_OLD_DISK_OFFSET_IN_BYTES, SEEK_SET) == REISERFS_OLD_DISK_OFFSET_IN_BYTES &&
            read(fd, &reiserfssb, sizeof(reiserfssb)) == sizeof(reiserfssb) &&
            is_reiserfs_magic_string(&reiserfssb)
        ) {
            type = "reiserfs";
        }
    }

    if(!type) {	/* block 8 */
        struct hpfs_super_block hpfssb;

        if(
            lseek(fd, 0x2000, SEEK_SET) == 0x2000 &&
            read(fd, &hpfssb, sizeof hpfssb) == sizeof hpfssb &&
            hpfsmagic(hpfssb) == HPFS_SUPER_MAGIC
        ) {
            type = "hpfs";
        }
    }

    if(!type) {	/* block 32 */
        struct jfs_super_block jfssb;

        if(
            lseek(fd, JFS_SUPER1_OFF, SEEK_SET) == JFS_SUPER1_OFF &&
            read(fd, &jfssb, sizeof jfssb) == sizeof jfssb &&
            !strncmp(jfssb.s_magic, JFS_MAGIC, 4)
        ) {
            type = "jfs";
        }
    }

    if(!type) {	/* block 32 */
        union {
            struct iso_volume_descriptor iso;
            struct hs_volume_descriptor hs;
        } isosb;

        if(
            lseek(fd, 0x8000, SEEK_SET) == 0x8000 &&
            read(fd, &isosb, sizeof isosb) == sizeof isosb
        ) {
            if(
                !strncmp(isosb.iso.id, ISO_STANDARD_ID, sizeof(isosb.iso.id)) ||
                !strncmp(isosb.hs.id, HS_STANDARD_ID, sizeof(isosb.hs.id))
            ) {
                type = "iso9660";
            }
            else if(may_be_udf(isosb.iso.id)) {
                type = "udf";
            }
        }
    }

    if(!type) {	/* block 64 */
        struct reiserfs_super_block reiserfssb;

        if(
            lseek(fd, REISERFS_DISK_OFFSET_IN_BYTES, SEEK_SET) == REISERFS_DISK_OFFSET_IN_BYTES &&
            read(fd, &reiserfssb, sizeof reiserfssb) == sizeof reiserfssb &&
            is_reiserfs_magic_string(&reiserfssb)
        ) {
            type = "reiserfs";
        }
    }

    if(!type) {
        char buf[8];

        if(
            lseek(fd, 0x10040, SEEK_SET) == 0x10040 &&
            read(fd, buf, sizeof buf) == sizeof buf &&
            !memcmp(buf, "_BHRfS_M", sizeof buf)
        ) {
            type = "btrfs";
        }
    }

    if(!type) {
        char buf[6];

        if(
            lseek(fd, 0x101, SEEK_SET) == 0x101 &&
            read(fd, buf, sizeof buf) == sizeof buf &&
            !memcmp(buf, "ustar", 6 /* with \0 */)
        ) {
            type = "tar";
        }
    }

    if(!type) {
        /*
         * perhaps the user tries to mount the swap space
         * on a new disk; warn her before she does mke2fs on it
         */
        int pagesize = getpagesize();
        int rd;
        char buf[pagesize + 32768];

        rd = pagesize;
        if(rd < 8192) rd = 8192;
        if(rd > sizeof buf) rd = sizeof buf;
        if(
            lseek(fd, 0, SEEK_SET) == 0 &&
            read(fd, buf, rd) == rd &&
            (
                may_be_swap(buf + pagesize) ||
                may_be_swap(buf + 4096) ||
                may_be_swap(buf + 8192)
            )
        ) {
            type = "swap";
        }
    }

    close(fd);

    return type;
}