--- util-linux-2.11z/mount/get_label_uuid.c +++ util-linux-2.11z/mount/get_label_uuid.c @@ -6,6 +6,7 @@ #include #include #include +#include /* reiserfs uses stat */ #include "linux_fs.h" #include "get_label_uuid.h" @@ -43,6 +44,79 @@ #endif } + +static int +valid_reiserfs_v2_super(int fd, struct reiserfs_super_block *s, int offset) { + dev_t dev; + struct stat st; + int version; + unsigned long blocksize; + unsigned long journal_block; + + /* only 3.6.x format supers have labels or uuids */ + if (!strncmp(s->s_magic, REISER2FS_SUPER_MAGIC_STRING, + strlen(REISER2FS_SUPER_MAGIC_STRING))) { + + blocksize = assemble2le(s->s_blocksize); + journal_block = assemble4le(s->s_journal_block); + /* we need to make sure we aren't looking at a logged copy + * of a super block, so we check to make sure the offset + * we just read is before the offset of the first journal + * block. + */ + if ((blocksize * journal_block) < offset) { + return 0; + } + return 1; + } + if (!strncmp(s->s_magic, REISER2FS_JR_SUPER_MAGIC_STRING, + strlen(REISER2FS_JR_SUPER_MAGIC_STRING))) { + + /* it is possible to have a relocated journal on a + * 3.5.x formatted disk. These don't support uuids or + * labels + */ + version = assemble2le(s->s_version); + if (version != REISERFS_VERSION_2) { + return 0; + } + + if (fstat(fd, &st)) { + return 0; + } + dev = assemble4le(s->s_journal_dev); + if (dev == st.st_rdev) { + /* if the journal device in the super is the + * device we just read, this is a logged copy + * and the FS doesn't live here. + */ + return 0; + } + return 1; + } + return 0; +} + +/* + * helper function to check all the possible reiserfs super locations + */ +static int +reiserfs_super_found(int fd, struct reiserfs_super_block *reisersb) { + int i; + int offsets[] = {REISERFS_DISK_OFFSET_IN_BYTES, + REISERFS_OLD_DISK_OFFSET_IN_BYTES, 0}; + + for (i = 0 ; offsets[i] ; i++) { + if (lseek(fd, offsets[i], SEEK_SET) == offsets[i] && + read(fd, (char *)reisersb, sizeof(*reisersb)) == + sizeof(*reisersb) + && valid_reiserfs_v2_super(fd, reisersb, offsets[i])) { + return 1; + } + } + return 0; +} + /* for now, only ext2, ext3, xfs, ocfs are supported */ int get_label_uuid(const char *device, char **label, char *uuid) { @@ -54,6 +128,7 @@ struct jfs_super_block jfssb; struct ocfs_volume_header ovh; /* Oracle */ struct ocfs_volume_label olbl; + struct reiserfs_super_block reisersb; fd = open(device, O_RDONLY); if (fd < 0) @@ -112,6 +187,13 @@ } rv = 0; } + else if (reiserfs_super_found(fd, &reisersb)) { + memcpy(uuid, reisersb.s_uuid, sizeof(reisersb.s_uuid)); + namesize = sizeof(reisersb.s_label); + if ((*label = calloc(namesize + 1, 1)) != NULL) + memcpy(*label, reisersb.s_label, namesize); + rv = 0; + } close(fd); return rv; --- util-linux-2.11z/mount/linux_fs.h +++ util-linux-2.11z/mount/linux_fs.h @@ -82,14 +82,26 @@ u_char s_oid_maxsize[2]; u_char s_oid_cursize[2]; u_char s_state[2]; - u_char s_magic[12]; + u_char s_magic[10]; + u_char s_dummy1[10]; + u_char s_version[2]; /* only valid with relocated journal */ + + /* only valid in 3.6.x format --mason@suse.com */ + u_char s_dummy2[10]; + u_char s_uuid[16]; + u_char s_label[16]; }; #define REISERFS_SUPER_MAGIC_STRING "ReIsErFs" #define REISER2FS_SUPER_MAGIC_STRING "ReIsEr2Fs" +#define REISER2FS_JR_SUPER_MAGIC_STRING "ReIsEr3Fs" #define REISERFS_DISK_OFFSET_IN_BYTES (64 * 1024) /* the spot for the super in versions 3.5 - 3.5.10 (inclusive) */ #define REISERFS_OLD_DISK_OFFSET_IN_BYTES (8 * 1024) +/* values of s_version when REISER2FS_JR_SUPER_MAGIC_STRING is found */ +#define REISERFS_VERSION_1 0 /* 3.5.x disk format */ +#define REISERFS_VERSION_2 2 /* 3.6.x disk format */ + #define _XIAFS_SUPER_MAGIC 0x012FD16D struct xiafs_super_block { u_char s_boot_segment[512]; /* 1st sector reserved for boot */ --- util-linux-2.11z/mount/mount_guess_fstype.c +++ util-linux-2.11z/mount/mount_guess_fstype.c @@ -221,7 +221,9 @@ return (!strncmp (rs->s_magic, REISERFS_SUPER_MAGIC_STRING, strlen ( REISERFS_SUPER_MAGIC_STRING)) || !strncmp (rs->s_magic, REISER2FS_SUPER_MAGIC_STRING, - strlen ( REISER2FS_SUPER_MAGIC_STRING))); + strlen ( REISER2FS_SUPER_MAGIC_STRING))|| + !strncmp (rs->s_magic, REISER2FS_JR_SUPER_MAGIC_STRING, + strlen ( REISER2FS_JR_SUPER_MAGIC_STRING))); } char * .