Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 1 | /* |
| 2 | * probe.c - identify a block device by its contents, and return a dev |
| 3 | * struct with the details |
| 4 | * |
| 5 | * Copyright (C) 1999 by Andries Brouwer |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 6 | * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 7 | * Copyright (C) 2001 by Andreas Dilger |
Theodore Ts'o | 2f79e51 | 2005-09-10 21:51:20 -0400 | [diff] [blame] | 8 | * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 9 | * |
| 10 | * %Begin-Header% |
| 11 | * This file may be redistributed under the terms of the |
| 12 | * GNU Lesser General Public License. |
| 13 | * %End-Header% |
| 14 | */ |
| 15 | |
| 16 | #include <stdio.h> |
| 17 | #include <string.h> |
| 18 | #include <stdlib.h> |
| 19 | #include <unistd.h> |
| 20 | #include <fcntl.h> |
| 21 | #include <sys/types.h> |
| 22 | #ifdef HAVE_SYS_STAT_H |
| 23 | #include <sys/stat.h> |
| 24 | #endif |
| 25 | #ifdef HAVE_SYS_MKDEV_H |
| 26 | #include <sys/mkdev.h> |
| 27 | #endif |
| 28 | #ifdef HAVE_ERRNO_H |
| 29 | #include <errno.h> |
| 30 | #endif |
Theodore Ts'o | 7a603aa | 2003-01-26 01:54:39 -0500 | [diff] [blame] | 31 | #include "blkidP.h" |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 32 | #include "uuid/uuid.h" |
| 33 | #include "probe.h" |
| 34 | |
Theodore Ts'o | 45a3fa8 | 2005-09-10 15:46:57 -0400 | [diff] [blame] | 35 | static int figure_label_len(const unsigned char *label, int len) |
| 36 | { |
| 37 | const unsigned char *end = label + len - 1; |
| 38 | |
| 39 | while ((*end == ' ' || *end == 0) && end >= label) |
| 40 | --end; |
| 41 | if (end >= label) { |
| 42 | label = label; |
| 43 | return end - label + 1; |
| 44 | } |
| 45 | return 0; |
| 46 | } |
| 47 | |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 48 | static unsigned char *get_buffer(struct blkid_probe *pr, |
| 49 | unsigned off, size_t len) |
| 50 | { |
| 51 | ssize_t ret_read; |
| 52 | unsigned char *newbuf; |
| 53 | |
| 54 | if (off + len <= SB_BUFFER_SIZE) { |
| 55 | if (!pr->sbbuf) { |
| 56 | pr->sbbuf = malloc(SB_BUFFER_SIZE); |
| 57 | if (!pr->sbbuf) |
| 58 | return NULL; |
| 59 | if (lseek(pr->fd, 0, SEEK_SET) < 0) |
| 60 | return NULL; |
| 61 | ret_read = read(pr->fd, pr->sbbuf, SB_BUFFER_SIZE); |
| 62 | if (ret_read < 0) |
| 63 | ret_read = 0; |
| 64 | pr->sb_valid = ret_read; |
| 65 | } |
| 66 | if (off+len > pr->sb_valid) |
| 67 | return NULL; |
| 68 | return pr->sbbuf + off; |
| 69 | } else { |
| 70 | if (len > pr->buf_max) { |
| 71 | newbuf = realloc(pr->buf, len); |
| 72 | if (newbuf == NULL) |
| 73 | return NULL; |
| 74 | pr->buf = newbuf; |
| 75 | pr->buf_max = len; |
| 76 | } |
| 77 | if (lseek(pr->fd, off, SEEK_SET) < 0) |
| 78 | return NULL; |
| 79 | ret_read = read(pr->fd, pr->buf, len); |
| 80 | if (ret_read != (ssize_t) len) |
| 81 | return NULL; |
| 82 | return pr->buf; |
| 83 | } |
| 84 | } |
| 85 | |
| 86 | |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 87 | /* |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 88 | * This is a special case code to check for an MDRAID device. We do |
| 89 | * this special since it requires checking for a superblock at the end |
| 90 | * of the device. |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 91 | */ |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 92 | static int check_mdraid(int fd, unsigned char *ret_uuid) |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 93 | { |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 94 | struct mdp_superblock_s *md; |
| 95 | blkid_loff_t offset; |
| 96 | char buf[4096]; |
| 97 | |
| 98 | if (fd < 0) |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 99 | return -BLKID_ERR_PARAM; |
| 100 | |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 101 | offset = (blkid_get_dev_size(fd) & ~((blkid_loff_t)65535)) - 65536; |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 102 | |
| 103 | if (blkid_llseek(fd, offset, 0) < 0 || |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 104 | read(fd, buf, 4096) != 4096) |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 105 | return -BLKID_ERR_IO; |
| 106 | |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 107 | /* Check for magic number */ |
| 108 | if (memcmp("\251+N\374", buf, 4)) |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 109 | return -BLKID_ERR_PARAM; |
| 110 | |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 111 | if (!ret_uuid) |
| 112 | return 0; |
| 113 | *ret_uuid = 0; |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 114 | |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 115 | /* The MD UUID is not contiguous in the superblock, make it so */ |
| 116 | md = (struct mdp_superblock_s *)buf; |
| 117 | if (md->set_uuid0 || md->set_uuid1 || md->set_uuid2 || md->set_uuid3) { |
| 118 | memcpy(ret_uuid, &md->set_uuid0, 4); |
| 119 | memcpy(ret_uuid, &md->set_uuid1, 12); |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 120 | } |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 121 | return 0; |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 122 | } |
| 123 | |
Theodore Ts'o | ba5e384 | 2006-03-10 18:11:35 -0500 | [diff] [blame] | 124 | static void set_uuid(blkid_dev dev, uuid_t uuid, char *tag) |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 125 | { |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 126 | char str[37]; |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 127 | |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 128 | if (!uuid_is_null(uuid)) { |
| 129 | uuid_unparse(uuid, str); |
Theodore Ts'o | ba5e384 | 2006-03-10 18:11:35 -0500 | [diff] [blame] | 130 | blkid_set_tag(dev, tag ? tag : "UUID", str, sizeof(str)); |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 131 | } |
| 132 | } |
| 133 | |
Theodore Ts'o | 2e6a9fe | 2005-01-05 17:45:32 -0500 | [diff] [blame] | 134 | static void get_ext2_info(blkid_dev dev, unsigned char *buf) |
| 135 | { |
| 136 | struct ext2_super_block *es = (struct ext2_super_block *) buf; |
| 137 | const char *label = 0; |
| 138 | |
| 139 | DBG(DEBUG_PROBE, printf("ext2_sb.compat = %08X:%08X:%08X\n", |
| 140 | blkid_le32(es->s_feature_compat), |
| 141 | blkid_le32(es->s_feature_incompat), |
| 142 | blkid_le32(es->s_feature_ro_compat))); |
| 143 | |
Theodore Ts'o | 7369f0c | 2005-01-10 23:58:11 -0500 | [diff] [blame] | 144 | if (strlen(es->s_volume_name)) |
Theodore Ts'o | 2e6a9fe | 2005-01-05 17:45:32 -0500 | [diff] [blame] | 145 | label = es->s_volume_name; |
Theodore Ts'o | 7369f0c | 2005-01-10 23:58:11 -0500 | [diff] [blame] | 146 | blkid_set_tag(dev, "LABEL", label, sizeof(es->s_volume_name)); |
Theodore Ts'o | 2e6a9fe | 2005-01-05 17:45:32 -0500 | [diff] [blame] | 147 | |
Theodore Ts'o | ba5e384 | 2006-03-10 18:11:35 -0500 | [diff] [blame] | 148 | set_uuid(dev, es->s_uuid, 0); |
Theodore Ts'o | 2e6a9fe | 2005-01-05 17:45:32 -0500 | [diff] [blame] | 149 | } |
| 150 | |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 151 | static int probe_ext3(struct blkid_probe *probe, |
Theodore Ts'o | 12b3c8e | 2005-05-07 14:38:10 -0400 | [diff] [blame] | 152 | struct blkid_magic *id __BLKID_ATTR((unused)), |
| 153 | unsigned char *buf) |
Theodore Ts'o | 2e6a9fe | 2005-01-05 17:45:32 -0500 | [diff] [blame] | 154 | { |
| 155 | struct ext2_super_block *es; |
Theodore Ts'o | 2e6a9fe | 2005-01-05 17:45:32 -0500 | [diff] [blame] | 156 | es = (struct ext2_super_block *)buf; |
| 157 | |
| 158 | /* Distinguish between jbd and ext2/3 fs */ |
| 159 | if (blkid_le32(es->s_feature_incompat) & |
| 160 | EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) |
| 161 | return -BLKID_ERR_PARAM; |
| 162 | |
| 163 | /* Distinguish between ext3 and ext2 */ |
| 164 | if (!(blkid_le32(es->s_feature_compat) & |
| 165 | EXT3_FEATURE_COMPAT_HAS_JOURNAL)) |
| 166 | return -BLKID_ERR_PARAM; |
| 167 | |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 168 | get_ext2_info(probe->dev, buf); |
Theodore Ts'o | 2e6a9fe | 2005-01-05 17:45:32 -0500 | [diff] [blame] | 169 | |
Theodore Ts'o | ba5e384 | 2006-03-10 18:11:35 -0500 | [diff] [blame] | 170 | if ((es->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) && |
| 171 | !uuid_is_null(es->s_journal_uuid)) |
| 172 | set_uuid(probe->dev, es->s_journal_uuid, "EXT_JOURNAL"); |
| 173 | |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 174 | blkid_set_tag(probe->dev, "SEC_TYPE", "ext2", sizeof("ext2")); |
Theodore Ts'o | 2e6a9fe | 2005-01-05 17:45:32 -0500 | [diff] [blame] | 175 | |
| 176 | return 0; |
| 177 | } |
| 178 | |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 179 | static int probe_ext2(struct blkid_probe *probe, |
Theodore Ts'o | 12b3c8e | 2005-05-07 14:38:10 -0400 | [diff] [blame] | 180 | struct blkid_magic *id __BLKID_ATTR((unused)), |
| 181 | unsigned char *buf) |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 182 | { |
| 183 | struct ext2_super_block *es; |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 184 | |
| 185 | es = (struct ext2_super_block *)buf; |
| 186 | |
Theodore Ts'o | 79dd234 | 2003-02-22 17:15:20 -0500 | [diff] [blame] | 187 | /* Distinguish between jbd and ext2/3 fs */ |
Theodore Ts'o | 2e6a9fe | 2005-01-05 17:45:32 -0500 | [diff] [blame] | 188 | if (blkid_le32(es->s_feature_incompat) & |
| 189 | EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 190 | return -BLKID_ERR_PARAM; |
Karel Zak | 05a6edf | 2005-09-06 06:26:45 -0400 | [diff] [blame] | 191 | |
| 192 | /* Distinguish between ext3 and ext2 */ |
| 193 | if ((blkid_le32(es->s_feature_compat) & |
| 194 | EXT3_FEATURE_COMPAT_HAS_JOURNAL)) |
| 195 | return -BLKID_ERR_PARAM; |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 196 | |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 197 | get_ext2_info(probe->dev, buf); |
Theodore Ts'o | 79dd234 | 2003-02-22 17:15:20 -0500 | [diff] [blame] | 198 | |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 199 | return 0; |
| 200 | } |
| 201 | |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 202 | static int probe_jbd(struct blkid_probe *probe, |
Theodore Ts'o | 5443492 | 2003-12-07 01:28:50 -0500 | [diff] [blame] | 203 | struct blkid_magic *id __BLKID_ATTR((unused)), |
| 204 | unsigned char *buf) |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 205 | { |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 206 | struct ext2_super_block *es = (struct ext2_super_block *) buf; |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 207 | |
Theodore Ts'o | 76b07bb | 2003-01-27 01:09:24 -0500 | [diff] [blame] | 208 | if (!(blkid_le32(es->s_feature_incompat) & |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 209 | EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 210 | return -BLKID_ERR_PARAM; |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 211 | |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 212 | get_ext2_info(probe->dev, buf); |
Theodore Ts'o | 2e6a9fe | 2005-01-05 17:45:32 -0500 | [diff] [blame] | 213 | |
| 214 | return 0; |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 215 | } |
| 216 | |
Theodore Ts'o | 2f79e51 | 2005-09-10 21:51:20 -0400 | [diff] [blame] | 217 | #define FAT_ATTR_VOLUME_ID 0x08 |
| 218 | #define FAT_ATTR_DIR 0x10 |
| 219 | #define FAT_ATTR_LONG_NAME 0x0f |
| 220 | #define FAT_ATTR_MASK 0x3f |
| 221 | #define FAT_ENTRY_FREE 0xe5 |
| 222 | |
| 223 | static char *no_name = "NO NAME "; |
| 224 | |
| 225 | static unsigned char *search_fat_label(struct vfat_dir_entry *dir, int count) |
| 226 | { |
Matthias Andree | 12a829d | 2006-05-30 01:48:51 +0200 | [diff] [blame] | 227 | int i; |
Theodore Ts'o | 2f79e51 | 2005-09-10 21:51:20 -0400 | [diff] [blame] | 228 | |
| 229 | for (i = 0; i < count; i++) { |
| 230 | if (dir[i].name[0] == 0x00) |
| 231 | break; |
| 232 | |
| 233 | if ((dir[i].name[0] == FAT_ENTRY_FREE) || |
| 234 | (dir[i].cluster_high != 0 || dir[i].cluster_low != 0) || |
| 235 | ((dir[i].attr & FAT_ATTR_MASK) == FAT_ATTR_LONG_NAME)) |
| 236 | continue; |
| 237 | |
| 238 | if ((dir[i].attr & (FAT_ATTR_VOLUME_ID | FAT_ATTR_DIR)) == |
| 239 | FAT_ATTR_VOLUME_ID) { |
| 240 | return dir[i].name; |
| 241 | } |
| 242 | } |
| 243 | return 0; |
| 244 | } |
| 245 | |
| 246 | /* FAT label extraction from the root directory taken from Kay |
| 247 | * Sievers's volume_id library */ |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 248 | static int probe_fat(struct blkid_probe *probe, |
Theodore Ts'o | 5443492 | 2003-12-07 01:28:50 -0500 | [diff] [blame] | 249 | struct blkid_magic *id __BLKID_ATTR((unused)), |
| 250 | unsigned char *buf) |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 251 | { |
Theodore Ts'o | 038d2be | 2005-09-07 12:14:53 -0400 | [diff] [blame] | 252 | struct vfat_super_block *vs = (struct vfat_super_block *) buf; |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 253 | struct msdos_super_block *ms = (struct msdos_super_block *) buf; |
Theodore Ts'o | 2f79e51 | 2005-09-10 21:51:20 -0400 | [diff] [blame] | 254 | struct vfat_dir_entry *dir; |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 255 | char serno[10]; |
Matthias Andree | 94fa110 | 2006-05-30 15:47:12 +0200 | [diff] [blame] | 256 | const unsigned char *label = 0, *vol_label = 0, *tmp; |
Theodore Ts'o | 038d2be | 2005-09-07 12:14:53 -0400 | [diff] [blame] | 257 | unsigned char *vol_serno; |
Theodore Ts'o | 2f79e51 | 2005-09-10 21:51:20 -0400 | [diff] [blame] | 258 | int label_len = 0, maxloop = 100; |
| 259 | __u16 sector_size, dir_entries, reserved; |
| 260 | __u32 sect_count, fat_size, dir_size, cluster_count, fat_length; |
| 261 | __u32 buf_size, start_data_sect, next, root_start, root_dir_entries; |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 262 | |
Theodore Ts'o | 038d2be | 2005-09-07 12:14:53 -0400 | [diff] [blame] | 263 | /* sector size check */ |
Matthias Andree | 94fa110 | 2006-05-30 15:47:12 +0200 | [diff] [blame] | 264 | tmp = &ms->ms_sector_size; |
| 265 | sector_size = tmp[0] + tmp[1] << 8; |
Theodore Ts'o | 038d2be | 2005-09-07 12:14:53 -0400 | [diff] [blame] | 266 | if (sector_size != 0x200 && sector_size != 0x400 && |
| 267 | sector_size != 0x800 && sector_size != 0x1000) |
| 268 | return 1; |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 269 | |
Matthias Andree | 94fa110 | 2006-05-30 15:47:12 +0200 | [diff] [blame] | 270 | tmp = &ms->ms_dir_entries; |
| 271 | dir_entries = tmp[0] + tmp[1] << 8; |
Theodore Ts'o | 038d2be | 2005-09-07 12:14:53 -0400 | [diff] [blame] | 272 | reserved = blkid_le16(ms->ms_reserved); |
Matthias Andree | 94fa110 | 2006-05-30 15:47:12 +0200 | [diff] [blame] | 273 | tmp = &ms->ms_sectors; |
| 274 | sect_count = tmp[0] + tmp[1] << 8; |
Theodore Ts'o | 038d2be | 2005-09-07 12:14:53 -0400 | [diff] [blame] | 275 | if (sect_count == 0) |
| 276 | sect_count = blkid_le32(ms->ms_total_sect); |
| 277 | |
| 278 | fat_length = blkid_le16(ms->ms_fat_length); |
| 279 | if (fat_length == 0) |
| 280 | fat_length = blkid_le32(vs->vs_fat32_length); |
| 281 | |
| 282 | fat_size = fat_length * ms->ms_fats; |
| 283 | dir_size = ((dir_entries * sizeof(struct vfat_dir_entry)) + |
| 284 | (sector_size-1)) / sector_size; |
| 285 | |
| 286 | cluster_count = sect_count - (reserved + fat_size + dir_size); |
| 287 | cluster_count /= ms->ms_cluster_size; |
| 288 | |
| 289 | if (cluster_count > FAT32_MAX) |
| 290 | return 1; |
| 291 | |
| 292 | if (ms->ms_fat_length) { |
Theodore Ts'o | 2f79e51 | 2005-09-10 21:51:20 -0400 | [diff] [blame] | 293 | /* the label may be an attribute in the root directory */ |
| 294 | root_start = (reserved + fat_size) * sector_size; |
| 295 | root_dir_entries = vs->vs_dir_entries[0] + |
| 296 | (vs->vs_dir_entries[1] << 8); |
| 297 | |
| 298 | buf_size = root_dir_entries * sizeof(struct vfat_dir_entry); |
| 299 | dir = (struct vfat_dir_entry *) get_buffer(probe, root_start, |
| 300 | buf_size); |
| 301 | if (dir) |
| 302 | vol_label = search_fat_label(dir, root_dir_entries); |
| 303 | |
| 304 | if (!vol_label || !memcmp(vol_label, no_name, 11)) |
| 305 | vol_label = ms->ms_label; |
Theodore Ts'o | 038d2be | 2005-09-07 12:14:53 -0400 | [diff] [blame] | 306 | vol_serno = ms->ms_serno; |
| 307 | |
Theodore Ts'o | 2f79e51 | 2005-09-10 21:51:20 -0400 | [diff] [blame] | 308 | blkid_set_tag(probe->dev, "SEC_TYPE", "msdos", |
| 309 | sizeof("msdos")); |
Theodore Ts'o | 038d2be | 2005-09-07 12:14:53 -0400 | [diff] [blame] | 310 | } else { |
Theodore Ts'o | 2f79e51 | 2005-09-10 21:51:20 -0400 | [diff] [blame] | 311 | /* Search the FAT32 root dir for the label attribute */ |
| 312 | buf_size = vs->vs_cluster_size * sector_size; |
| 313 | start_data_sect = reserved + fat_size; |
| 314 | |
| 315 | next = blkid_le32(vs->vs_root_cluster); |
| 316 | while (next && --maxloop) { |
| 317 | __u32 next_sect_off; |
| 318 | __u64 next_off, fat_entry_off; |
| 319 | int count; |
| 320 | |
| 321 | next_sect_off = (next - 2) * vs->vs_cluster_size; |
| 322 | next_off = (start_data_sect + next_sect_off) * |
| 323 | sector_size; |
| 324 | |
| 325 | dir = (struct vfat_dir_entry *) |
| 326 | get_buffer(probe, next_off, buf_size); |
| 327 | if (dir == NULL) |
| 328 | break; |
| 329 | |
| 330 | count = buf_size / sizeof(struct vfat_dir_entry); |
| 331 | |
| 332 | vol_label = search_fat_label(dir, count); |
| 333 | if (vol_label) |
| 334 | break; |
| 335 | |
| 336 | /* get FAT entry */ |
| 337 | fat_entry_off = (reserved * sector_size) + |
| 338 | (next * sizeof(__u32)); |
| 339 | buf = get_buffer(probe, fat_entry_off, buf_size); |
| 340 | if (buf == NULL) |
| 341 | break; |
| 342 | |
| 343 | /* set next cluster */ |
| 344 | next = blkid_le32(*((__u32 *) buf) & 0x0fffffff); |
| 345 | } |
| 346 | |
| 347 | if (!vol_label || !memcmp(vol_label, no_name, 11)) |
| 348 | vol_label = vs->vs_label; |
Theodore Ts'o | 038d2be | 2005-09-07 12:14:53 -0400 | [diff] [blame] | 349 | vol_serno = vs->vs_serno; |
| 350 | } |
| 351 | |
Theodore Ts'o | 2f79e51 | 2005-09-10 21:51:20 -0400 | [diff] [blame] | 352 | if (vol_label && memcmp(vol_label, no_name, 11)) { |
Theodore Ts'o | 45a3fa8 | 2005-09-10 15:46:57 -0400 | [diff] [blame] | 353 | label = vol_label; |
| 354 | label_len = figure_label_len(vol_label, 11); |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 355 | } |
| 356 | |
| 357 | /* We can't just print them as %04X, because they are unaligned */ |
Theodore Ts'o | 038d2be | 2005-09-07 12:14:53 -0400 | [diff] [blame] | 358 | sprintf(serno, "%02X%02X-%02X%02X", vol_serno[3], vol_serno[2], |
| 359 | vol_serno[1], vol_serno[0]); |
| 360 | |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 361 | blkid_set_tag(probe->dev, "LABEL", (const char *) label, label_len); |
| 362 | blkid_set_tag(probe->dev, "UUID", serno, sizeof(serno)-1); |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 363 | |
| 364 | return 0; |
| 365 | } |
| 366 | |
Karel Zak | c4c740f | 2005-09-06 08:13:35 -0400 | [diff] [blame] | 367 | /* |
| 368 | * The FAT filesystem could be without a magic string in superblock |
| 369 | * (e.g. old floppies). This heuristic for FAT detection is inspired |
| 370 | * by http://vrfy.org/projects/volume_id/ and Linux kernel. |
| 371 | * [7-Jul-2005, Karel Zak <kzak@redhat.com>] |
| 372 | */ |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 373 | static int probe_fat_nomagic(struct blkid_probe *probe, |
Theodore Ts'o | 038d2be | 2005-09-07 12:14:53 -0400 | [diff] [blame] | 374 | struct blkid_magic *id __BLKID_ATTR((unused)), |
| 375 | unsigned char *buf) |
Karel Zak | c4c740f | 2005-09-06 08:13:35 -0400 | [diff] [blame] | 376 | { |
| 377 | struct vfat_super_block *vs; |
Karel Zak | c4c740f | 2005-09-06 08:13:35 -0400 | [diff] [blame] | 378 | |
| 379 | vs = (struct vfat_super_block *)buf; |
| 380 | |
Karel Zak | c4c740f | 2005-09-06 08:13:35 -0400 | [diff] [blame] | 381 | /* heads check */ |
| 382 | if (vs->vs_heads == 0) |
| 383 | return 1; |
| 384 | |
| 385 | /* cluster size check*/ |
| 386 | if (vs->vs_cluster_size == 0 || |
| 387 | (vs->vs_cluster_size & (vs->vs_cluster_size-1))) |
| 388 | return 1; |
| 389 | |
| 390 | /* media check */ |
| 391 | if (vs->vs_media < 0xf8 && vs->vs_media != 0xf0) |
| 392 | return 1; |
| 393 | |
| 394 | /* fat counts(Linux kernel expects at least 1 FAT table) */ |
| 395 | if (!vs->vs_fats) |
| 396 | return 1; |
| 397 | |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 398 | return probe_fat(probe, id, buf); |
Karel Zak | c4c740f | 2005-09-06 08:13:35 -0400 | [diff] [blame] | 399 | } |
| 400 | |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 401 | static int probe_xfs(struct blkid_probe *probe, |
Theodore Ts'o | 5443492 | 2003-12-07 01:28:50 -0500 | [diff] [blame] | 402 | struct blkid_magic *id __BLKID_ATTR((unused)), |
| 403 | unsigned char *buf) |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 404 | { |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 405 | struct xfs_super_block *xs; |
Theodore Ts'o | a30b944 | 2003-07-20 11:22:34 -0400 | [diff] [blame] | 406 | const char *label = 0; |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 407 | |
| 408 | xs = (struct xfs_super_block *)buf; |
| 409 | |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 410 | if (strlen(xs->xs_fname)) |
Theodore Ts'o | a30b944 | 2003-07-20 11:22:34 -0400 | [diff] [blame] | 411 | label = xs->xs_fname; |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 412 | blkid_set_tag(probe->dev, "LABEL", label, sizeof(xs->xs_fname)); |
Theodore Ts'o | ba5e384 | 2006-03-10 18:11:35 -0500 | [diff] [blame] | 413 | set_uuid(probe->dev, xs->xs_uuid, 0); |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 414 | return 0; |
| 415 | } |
| 416 | |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 417 | static int probe_reiserfs(struct blkid_probe *probe, |
Theodore Ts'o | 79dd234 | 2003-02-22 17:15:20 -0500 | [diff] [blame] | 418 | struct blkid_magic *id, unsigned char *buf) |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 419 | { |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 420 | struct reiserfs_super_block *rs = (struct reiserfs_super_block *) buf; |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 421 | unsigned int blocksize; |
Theodore Ts'o | a30b944 | 2003-07-20 11:22:34 -0400 | [diff] [blame] | 422 | const char *label = 0; |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 423 | |
Theodore Ts'o | 76b07bb | 2003-01-27 01:09:24 -0500 | [diff] [blame] | 424 | blocksize = blkid_le16(rs->rs_blocksize); |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 425 | |
| 426 | /* If the superblock is inside the journal, we have the wrong one */ |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 427 | if (id->bim_kboff/(blocksize>>10) > blkid_le32(rs->rs_journal_block)) |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 428 | return -BLKID_ERR_BIG; |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 429 | |
| 430 | /* LABEL/UUID are only valid for later versions of Reiserfs v3.6. */ |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 431 | if (id->bim_magic[6] == '2' || id->bim_magic[6] == '3') { |
Theodore Ts'o | a30b944 | 2003-07-20 11:22:34 -0400 | [diff] [blame] | 432 | if (strlen(rs->rs_label)) |
| 433 | label = rs->rs_label; |
Theodore Ts'o | ba5e384 | 2006-03-10 18:11:35 -0500 | [diff] [blame] | 434 | set_uuid(probe->dev, rs->rs_uuid, 0); |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 435 | } |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 436 | blkid_set_tag(probe->dev, "LABEL", label, sizeof(rs->rs_label)); |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 437 | |
| 438 | return 0; |
| 439 | } |
| 440 | |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 441 | static int probe_reiserfs4(struct blkid_probe *probe, |
| 442 | struct blkid_magic *id __BLKID_ATTR((unused)), |
| 443 | unsigned char *buf) |
Theodore Ts'o | bb626bc | 2005-09-10 11:48:38 -0400 | [diff] [blame] | 444 | { |
| 445 | struct reiser4_super_block *rs4 = (struct reiser4_super_block *) buf; |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 446 | const unsigned char *label = 0; |
Theodore Ts'o | bb626bc | 2005-09-10 11:48:38 -0400 | [diff] [blame] | 447 | |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 448 | if (strlen((char *) rs4->rs4_label)) |
Theodore Ts'o | bb626bc | 2005-09-10 11:48:38 -0400 | [diff] [blame] | 449 | label = rs4->rs4_label; |
Theodore Ts'o | ba5e384 | 2006-03-10 18:11:35 -0500 | [diff] [blame] | 450 | set_uuid(probe->dev, rs4->rs4_uuid, 0); |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 451 | blkid_set_tag(probe->dev, "LABEL", (const char *) label, |
| 452 | sizeof(rs4->rs4_label)); |
Theodore Ts'o | bb626bc | 2005-09-10 11:48:38 -0400 | [diff] [blame] | 453 | |
| 454 | return 0; |
| 455 | } |
| 456 | |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 457 | static int probe_jfs(struct blkid_probe *probe, |
Theodore Ts'o | 5443492 | 2003-12-07 01:28:50 -0500 | [diff] [blame] | 458 | struct blkid_magic *id __BLKID_ATTR((unused)), |
| 459 | unsigned char *buf) |
Theodore Ts'o | 09a2ef8 | 2003-04-03 00:04:28 -0500 | [diff] [blame] | 460 | { |
| 461 | struct jfs_super_block *js; |
Theodore Ts'o | a30b944 | 2003-07-20 11:22:34 -0400 | [diff] [blame] | 462 | const char *label = 0; |
Theodore Ts'o | 09a2ef8 | 2003-04-03 00:04:28 -0500 | [diff] [blame] | 463 | |
| 464 | js = (struct jfs_super_block *)buf; |
| 465 | |
Theodore Ts'o | 48e6e81 | 2003-07-06 00:36:48 -0400 | [diff] [blame] | 466 | if (strlen((char *) js->js_label)) |
Theodore Ts'o | a30b944 | 2003-07-20 11:22:34 -0400 | [diff] [blame] | 467 | label = (char *) js->js_label; |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 468 | blkid_set_tag(probe->dev, "LABEL", label, sizeof(js->js_label)); |
Theodore Ts'o | ba5e384 | 2006-03-10 18:11:35 -0500 | [diff] [blame] | 469 | set_uuid(probe->dev, js->js_uuid, 0); |
Theodore Ts'o | 09a2ef8 | 2003-04-03 00:04:28 -0500 | [diff] [blame] | 470 | return 0; |
| 471 | } |
| 472 | |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 473 | static int probe_romfs(struct blkid_probe *probe, |
Theodore Ts'o | 5443492 | 2003-12-07 01:28:50 -0500 | [diff] [blame] | 474 | struct blkid_magic *id __BLKID_ATTR((unused)), |
| 475 | unsigned char *buf) |
Theodore Ts'o | 09a2ef8 | 2003-04-03 00:04:28 -0500 | [diff] [blame] | 476 | { |
| 477 | struct romfs_super_block *ros; |
Theodore Ts'o | a30b944 | 2003-07-20 11:22:34 -0400 | [diff] [blame] | 478 | const char *label = 0; |
Theodore Ts'o | 09a2ef8 | 2003-04-03 00:04:28 -0500 | [diff] [blame] | 479 | |
| 480 | ros = (struct romfs_super_block *)buf; |
| 481 | |
Theodore Ts'o | a30b944 | 2003-07-20 11:22:34 -0400 | [diff] [blame] | 482 | if (strlen((char *) ros->ros_volume)) |
| 483 | label = (char *) ros->ros_volume; |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 484 | blkid_set_tag(probe->dev, "LABEL", label, 0); |
Theodore Ts'o | 7369f0c | 2005-01-10 23:58:11 -0500 | [diff] [blame] | 485 | return 0; |
| 486 | } |
| 487 | |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 488 | static int probe_cramfs(struct blkid_probe *probe, |
| 489 | struct blkid_magic *id __BLKID_ATTR((unused)), |
| 490 | unsigned char *buf) |
Theodore Ts'o | 4c4e3f7 | 2005-05-05 18:06:04 -0400 | [diff] [blame] | 491 | { |
| 492 | struct cramfs_super_block *csb; |
| 493 | const char *label = 0; |
| 494 | |
| 495 | csb = (struct cramfs_super_block *)buf; |
| 496 | |
| 497 | if (strlen((char *) csb->name)) |
| 498 | label = (char *) csb->name; |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 499 | blkid_set_tag(probe->dev, "LABEL", label, 0); |
Theodore Ts'o | 4c4e3f7 | 2005-05-05 18:06:04 -0400 | [diff] [blame] | 500 | return 0; |
| 501 | } |
| 502 | |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 503 | static int probe_swap0(struct blkid_probe *probe, |
Theodore Ts'o | 7369f0c | 2005-01-10 23:58:11 -0500 | [diff] [blame] | 504 | struct blkid_magic *id __BLKID_ATTR((unused)), |
| 505 | unsigned char *buf __BLKID_ATTR((unused))) |
| 506 | { |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 507 | blkid_set_tag(probe->dev, "UUID", 0, 0); |
| 508 | blkid_set_tag(probe->dev, "LABEL", 0, 0); |
Theodore Ts'o | 7369f0c | 2005-01-10 23:58:11 -0500 | [diff] [blame] | 509 | return 0; |
| 510 | } |
| 511 | |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 512 | static int probe_swap1(struct blkid_probe *probe, |
Theodore Ts'o | 7369f0c | 2005-01-10 23:58:11 -0500 | [diff] [blame] | 513 | struct blkid_magic *id __BLKID_ATTR((unused)), |
| 514 | unsigned char *buf __BLKID_ATTR((unused))) |
| 515 | { |
| 516 | struct swap_id_block *sws; |
Theodore Ts'o | 7369f0c | 2005-01-10 23:58:11 -0500 | [diff] [blame] | 517 | |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 518 | probe_swap0(probe, id, buf); |
Theodore Ts'o | 7369f0c | 2005-01-10 23:58:11 -0500 | [diff] [blame] | 519 | /* |
| 520 | * Version 1 swap headers are always located at offset of 1024 |
| 521 | * bytes, although the swap signature itself is located at the |
| 522 | * end of the page (which may vary depending on hardware |
| 523 | * pagesize). |
| 524 | */ |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 525 | sws = (struct swap_id_block *) get_buffer(probe, 1024, 1024); |
| 526 | if (!sws) |
Theodore Ts'o | 7369f0c | 2005-01-10 23:58:11 -0500 | [diff] [blame] | 527 | return 1; |
Theodore Ts'o | 7369f0c | 2005-01-10 23:58:11 -0500 | [diff] [blame] | 528 | |
| 529 | /* arbitrary sanity check.. is there any garbage down there? */ |
| 530 | if (sws->sws_pad[32] == 0 && sws->sws_pad[33] == 0) { |
| 531 | if (sws->sws_volume[0]) |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 532 | blkid_set_tag(probe->dev, "LABEL", sws->sws_volume, |
Theodore Ts'o | 7369f0c | 2005-01-10 23:58:11 -0500 | [diff] [blame] | 533 | sizeof(sws->sws_volume)); |
| 534 | if (sws->sws_uuid[0]) |
Theodore Ts'o | ba5e384 | 2006-03-10 18:11:35 -0500 | [diff] [blame] | 535 | set_uuid(probe->dev, sws->sws_uuid, 0); |
Theodore Ts'o | 7369f0c | 2005-01-10 23:58:11 -0500 | [diff] [blame] | 536 | } |
Theodore Ts'o | 09a2ef8 | 2003-04-03 00:04:28 -0500 | [diff] [blame] | 537 | return 0; |
| 538 | } |
| 539 | |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 540 | static int probe_iso9660(struct blkid_probe *probe, |
Theodore Ts'o | 45a3fa8 | 2005-09-10 15:46:57 -0400 | [diff] [blame] | 541 | struct blkid_magic *id __BLKID_ATTR((unused)), |
| 542 | unsigned char *buf) |
| 543 | { |
| 544 | struct iso_volume_descriptor *iso; |
| 545 | const unsigned char *label; |
| 546 | |
| 547 | iso = (struct iso_volume_descriptor *) buf; |
Theodore Ts'o | 45a3fa8 | 2005-09-10 15:46:57 -0400 | [diff] [blame] | 548 | label = iso->volume_id; |
| 549 | |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 550 | blkid_set_tag(probe->dev, "LABEL", (const char *) label, |
| 551 | figure_label_len(label, 32)); |
Theodore Ts'o | 45a3fa8 | 2005-09-10 15:46:57 -0400 | [diff] [blame] | 552 | return 0; |
| 553 | } |
| 554 | |
| 555 | |
Theodore Ts'o | 5443492 | 2003-12-07 01:28:50 -0500 | [diff] [blame] | 556 | static const char |
Theodore Ts'o | 3de5bf6 | 2003-07-22 01:06:36 -0400 | [diff] [blame] | 557 | *udf_magic[] = { "BEA01", "BOOT2", "CD001", "CDW02", "NSR02", |
| 558 | "NSR03", "TEA01", 0 }; |
| 559 | |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 560 | static int probe_udf(struct blkid_probe *probe, |
| 561 | struct blkid_magic *id __BLKID_ATTR((unused)), |
Theodore Ts'o | 5443492 | 2003-12-07 01:28:50 -0500 | [diff] [blame] | 562 | unsigned char *buf __BLKID_ATTR((unused))) |
Theodore Ts'o | 3de5bf6 | 2003-07-22 01:06:36 -0400 | [diff] [blame] | 563 | { |
| 564 | int j, bs; |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 565 | struct iso_volume_descriptor *isosb; |
Theodore Ts'o | 5443492 | 2003-12-07 01:28:50 -0500 | [diff] [blame] | 566 | const char ** m; |
Theodore Ts'o | 3de5bf6 | 2003-07-22 01:06:36 -0400 | [diff] [blame] | 567 | |
| 568 | /* determine the block size by scanning in 2K increments |
| 569 | (block sizes larger than 2K will be null padded) */ |
| 570 | for (bs = 1; bs < 16; bs++) { |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 571 | isosb = (struct iso_volume_descriptor *) |
| 572 | get_buffer(probe, bs*2048+32768, sizeof(isosb)); |
| 573 | if (!isosb) |
Theodore Ts'o | 3de5bf6 | 2003-07-22 01:06:36 -0400 | [diff] [blame] | 574 | return 1; |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 575 | if (isosb->vd_id[0]) |
Theodore Ts'o | 3de5bf6 | 2003-07-22 01:06:36 -0400 | [diff] [blame] | 576 | break; |
| 577 | } |
| 578 | |
| 579 | /* Scan up to another 64 blocks looking for additional VSD's */ |
| 580 | for (j = 1; j < 64; j++) { |
| 581 | if (j > 1) { |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 582 | isosb = (struct iso_volume_descriptor *) |
| 583 | get_buffer(probe, j*bs*2048+32768, |
| 584 | sizeof(isosb)); |
| 585 | if (!isosb) |
Theodore Ts'o | 3de5bf6 | 2003-07-22 01:06:36 -0400 | [diff] [blame] | 586 | return 1; |
| 587 | } |
| 588 | /* If we find NSR0x then call it udf: |
| 589 | NSR01 for UDF 1.00 |
| 590 | NSR02 for UDF 1.50 |
| 591 | NSR03 for UDF 2.00 */ |
Theodore Ts'o | 49487b7 | 2006-05-14 17:29:00 -0400 | [diff] [blame] | 592 | if (!memcmp(isosb->vd_id, "NSR0", 4)) |
Theodore Ts'o | 3de5bf6 | 2003-07-22 01:06:36 -0400 | [diff] [blame] | 593 | return 0; |
| 594 | for (m = udf_magic; *m; m++) |
Theodore Ts'o | 49487b7 | 2006-05-14 17:29:00 -0400 | [diff] [blame] | 595 | if (!memcmp(*m, isosb->vd_id, 5)) |
Theodore Ts'o | 3de5bf6 | 2003-07-22 01:06:36 -0400 | [diff] [blame] | 596 | break; |
| 597 | if (*m == 0) |
| 598 | return 1; |
| 599 | } |
| 600 | return 1; |
| 601 | } |
| 602 | |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 603 | static int probe_ocfs(struct blkid_probe *probe, |
Theodore Ts'o | 9387c28 | 2004-03-04 19:59:58 -0500 | [diff] [blame] | 604 | struct blkid_magic *id __BLKID_ATTR((unused)), |
| 605 | unsigned char *buf) |
| 606 | { |
| 607 | struct ocfs_volume_header ovh; |
| 608 | struct ocfs_volume_label ovl; |
Theodore Ts'o | 3838f7d | 2004-11-30 19:05:38 -0500 | [diff] [blame] | 609 | __u32 major; |
Theodore Ts'o | 9387c28 | 2004-03-04 19:59:58 -0500 | [diff] [blame] | 610 | |
| 611 | memcpy(&ovh, buf, sizeof(ovh)); |
| 612 | memcpy(&ovl, buf+512, sizeof(ovl)); |
| 613 | |
| 614 | major = ocfsmajor(ovh); |
| 615 | if (major == 1) |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 616 | blkid_set_tag(probe->dev,"SEC_TYPE","ocfs1",sizeof("ocfs1")); |
Theodore Ts'o | 9387c28 | 2004-03-04 19:59:58 -0500 | [diff] [blame] | 617 | else if (major >= 9) |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 618 | blkid_set_tag(probe->dev,"SEC_TYPE","ntocfs",sizeof("ntocfs")); |
Theodore Ts'o | 9387c28 | 2004-03-04 19:59:58 -0500 | [diff] [blame] | 619 | |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 620 | blkid_set_tag(probe->dev, "LABEL", ovl.label, ocfslabellen(ovl)); |
| 621 | blkid_set_tag(probe->dev, "MOUNT", ovh.mount, ocfsmountlen(ovh)); |
Theodore Ts'o | ba5e384 | 2006-03-10 18:11:35 -0500 | [diff] [blame] | 622 | set_uuid(probe->dev, ovl.vol_id, 0); |
Theodore Ts'o | 9387c28 | 2004-03-04 19:59:58 -0500 | [diff] [blame] | 623 | return 0; |
| 624 | } |
| 625 | |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 626 | static int probe_ocfs2(struct blkid_probe *probe, |
Theodore Ts'o | 2c92375 | 2005-01-21 17:57:56 -0500 | [diff] [blame] | 627 | struct blkid_magic *id __BLKID_ATTR((unused)), |
| 628 | unsigned char *buf) |
Theodore Ts'o | 414846b | 2004-09-17 21:37:49 -0400 | [diff] [blame] | 629 | { |
| 630 | struct ocfs2_super_block *osb; |
| 631 | |
| 632 | osb = (struct ocfs2_super_block *)buf; |
| 633 | |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 634 | blkid_set_tag(probe->dev, "LABEL", osb->s_label, sizeof(osb->s_label)); |
Theodore Ts'o | ba5e384 | 2006-03-10 18:11:35 -0500 | [diff] [blame] | 635 | set_uuid(probe->dev, osb->s_uuid, 0); |
Theodore Ts'o | 414846b | 2004-09-17 21:37:49 -0400 | [diff] [blame] | 636 | return 0; |
| 637 | } |
| 638 | |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 639 | static int probe_oracleasm(struct blkid_probe *probe, |
Theodore Ts'o | 2c92375 | 2005-01-21 17:57:56 -0500 | [diff] [blame] | 640 | struct blkid_magic *id __BLKID_ATTR((unused)), |
| 641 | unsigned char *buf) |
| 642 | { |
| 643 | struct oracle_asm_disk_label *dl; |
| 644 | |
| 645 | dl = (struct oracle_asm_disk_label *)buf; |
| 646 | |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 647 | blkid_set_tag(probe->dev, "LABEL", dl->dl_id, sizeof(dl->dl_id)); |
Theodore Ts'o | 2c92375 | 2005-01-21 17:57:56 -0500 | [diff] [blame] | 648 | return 0; |
| 649 | } |
| 650 | |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 651 | /* |
| 652 | * BLKID_BLK_OFFS is at least as large as the highest bim_kboff defined |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 653 | * in the type_array table below + bim_kbalign. |
| 654 | * |
| 655 | * When probing for a lot of magics, we handle everything in 1kB buffers so |
| 656 | * that we don't have to worry about reading each combination of block sizes. |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 657 | */ |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 658 | #define BLKID_BLK_OFFS 64 /* currently reiserfs */ |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 659 | |
| 660 | /* |
| 661 | * Various filesystem magics that we can check for. Note that kboff and |
| 662 | * sboff are in kilobytes and bytes respectively. All magics are in |
| 663 | * byte strings so we don't worry about endian issues. |
| 664 | */ |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 665 | static struct blkid_magic type_array[] = { |
| 666 | /* type kboff sboff len magic probe */ |
Theodore Ts'o | 2c92375 | 2005-01-21 17:57:56 -0500 | [diff] [blame] | 667 | { "oracleasm", 0, 32, 8, "ORCLDISK", probe_oracleasm }, |
Theodore Ts'o | 9d0f461 | 2005-01-25 03:26:10 -0500 | [diff] [blame] | 668 | { "ntfs", 0, 3, 8, "NTFS ", 0 }, |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 669 | { "jbd", 1, 0x38, 2, "\123\357", probe_jbd }, |
Theodore Ts'o | 2e6a9fe | 2005-01-05 17:45:32 -0500 | [diff] [blame] | 670 | { "ext3", 1, 0x38, 2, "\123\357", probe_ext3 }, |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 671 | { "ext2", 1, 0x38, 2, "\123\357", probe_ext2 }, |
| 672 | { "reiserfs", 8, 0x34, 8, "ReIsErFs", probe_reiserfs }, |
| 673 | { "reiserfs", 64, 0x34, 9, "ReIsEr2Fs", probe_reiserfs }, |
| 674 | { "reiserfs", 64, 0x34, 9, "ReIsEr3Fs", probe_reiserfs }, |
| 675 | { "reiserfs", 64, 0x34, 8, "ReIsErFs", probe_reiserfs }, |
| 676 | { "reiserfs", 8, 20, 8, "ReIsErFs", probe_reiserfs }, |
Theodore Ts'o | bb626bc | 2005-09-10 11:48:38 -0400 | [diff] [blame] | 677 | { "reiser4", 64, 0, 7, "ReIsEr4", probe_reiserfs4 }, |
Theodore Ts'o | 038d2be | 2005-09-07 12:14:53 -0400 | [diff] [blame] | 678 | { "vfat", 0, 0x52, 5, "MSWIN", probe_fat }, |
| 679 | { "vfat", 0, 0x52, 8, "FAT32 ", probe_fat }, |
| 680 | { "vfat", 0, 0x36, 5, "MSDOS", probe_fat }, |
| 681 | { "vfat", 0, 0x36, 8, "FAT16 ", probe_fat }, |
| 682 | { "vfat", 0, 0x36, 8, "FAT12 ", probe_fat }, |
| 683 | { "vfat", 0, 0, 2, "\353\220", probe_fat_nomagic }, |
| 684 | { "vfat", 0, 0, 1, "\351", probe_fat_nomagic }, |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 685 | { "minix", 1, 0x10, 2, "\177\023", 0 }, |
| 686 | { "minix", 1, 0x10, 2, "\217\023", 0 }, |
| 687 | { "minix", 1, 0x10, 2, "\150\044", 0 }, |
| 688 | { "minix", 1, 0x10, 2, "\170\044", 0 }, |
| 689 | { "vxfs", 1, 0, 4, "\365\374\001\245", 0 }, |
| 690 | { "xfs", 0, 0, 4, "XFSB", probe_xfs }, |
Theodore Ts'o | 09a2ef8 | 2003-04-03 00:04:28 -0500 | [diff] [blame] | 691 | { "romfs", 0, 0, 8, "-rom1fs-", probe_romfs }, |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 692 | { "bfs", 0, 0, 4, "\316\372\173\033", 0 }, |
Theodore Ts'o | 4c4e3f7 | 2005-05-05 18:06:04 -0400 | [diff] [blame] | 693 | { "cramfs", 0, 0, 4, "E=\315\050", probe_cramfs }, |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 694 | { "qnx4", 0, 4, 6, "QNX4FS", 0 }, |
Theodore Ts'o | 3de5bf6 | 2003-07-22 01:06:36 -0400 | [diff] [blame] | 695 | { "udf", 32, 1, 5, "BEA01", probe_udf }, |
| 696 | { "udf", 32, 1, 5, "BOOT2", probe_udf }, |
| 697 | { "udf", 32, 1, 5, "CD001", probe_udf }, |
| 698 | { "udf", 32, 1, 5, "CDW02", probe_udf }, |
| 699 | { "udf", 32, 1, 5, "NSR02", probe_udf }, |
| 700 | { "udf", 32, 1, 5, "NSR03", probe_udf }, |
| 701 | { "udf", 32, 1, 5, "TEA01", probe_udf }, |
Theodore Ts'o | 45a3fa8 | 2005-09-10 15:46:57 -0400 | [diff] [blame] | 702 | { "iso9660", 32, 1, 5, "CD001", probe_iso9660 }, |
| 703 | { "iso9660", 32, 9, 5, "CDROM", probe_iso9660 }, |
Theodore Ts'o | 09a2ef8 | 2003-04-03 00:04:28 -0500 | [diff] [blame] | 704 | { "jfs", 32, 0, 4, "JFS1", probe_jfs }, |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 705 | { "hfs", 1, 0, 2, "BD", 0 }, |
| 706 | { "ufs", 8, 0x55c, 4, "T\031\001\000", 0 }, |
| 707 | { "hpfs", 8, 0, 4, "I\350\225\371", 0 }, |
| 708 | { "sysv", 0, 0x3f8, 4, "\020~\030\375", 0 }, |
Theodore Ts'o | 7369f0c | 2005-01-10 23:58:11 -0500 | [diff] [blame] | 709 | { "swap", 0, 0xff6, 10, "SWAP-SPACE", probe_swap0 }, |
| 710 | { "swap", 0, 0xff6, 10, "SWAPSPACE2", probe_swap1 }, |
Karel Zak | abaa112 | 2005-09-06 06:42:49 -0400 | [diff] [blame] | 711 | { "swsuspend", 0, 0xff6, 9, "S1SUSPEND", probe_swap1 }, |
| 712 | { "swsuspend", 0, 0xff6, 9, "S2SUSPEND", probe_swap1 }, |
Theodore Ts'o | 7369f0c | 2005-01-10 23:58:11 -0500 | [diff] [blame] | 713 | { "swap", 0, 0x1ff6, 10, "SWAP-SPACE", probe_swap0 }, |
| 714 | { "swap", 0, 0x1ff6, 10, "SWAPSPACE2", probe_swap1 }, |
Karel Zak | abaa112 | 2005-09-06 06:42:49 -0400 | [diff] [blame] | 715 | { "swsuspend", 0, 0x1ff6, 9, "S1SUSPEND", probe_swap1 }, |
| 716 | { "swsuspend", 0, 0x1ff6, 9, "S2SUSPEND", probe_swap1 }, |
Theodore Ts'o | 7369f0c | 2005-01-10 23:58:11 -0500 | [diff] [blame] | 717 | { "swap", 0, 0x3ff6, 10, "SWAP-SPACE", probe_swap0 }, |
| 718 | { "swap", 0, 0x3ff6, 10, "SWAPSPACE2", probe_swap1 }, |
Karel Zak | abaa112 | 2005-09-06 06:42:49 -0400 | [diff] [blame] | 719 | { "swsuspend", 0, 0x3ff6, 9, "S1SUSPEND", probe_swap1 }, |
| 720 | { "swsuspend", 0, 0x3ff6, 9, "S2SUSPEND", probe_swap1 }, |
Theodore Ts'o | 7369f0c | 2005-01-10 23:58:11 -0500 | [diff] [blame] | 721 | { "swap", 0, 0x7ff6, 10, "SWAP-SPACE", probe_swap0 }, |
| 722 | { "swap", 0, 0x7ff6, 10, "SWAPSPACE2", probe_swap1 }, |
Karel Zak | abaa112 | 2005-09-06 06:42:49 -0400 | [diff] [blame] | 723 | { "swsuspend", 0, 0x7ff6, 9, "S1SUSPEND", probe_swap1 }, |
| 724 | { "swsuspend", 0, 0x7ff6, 9, "S2SUSPEND", probe_swap1 }, |
Theodore Ts'o | 7369f0c | 2005-01-10 23:58:11 -0500 | [diff] [blame] | 725 | { "swap", 0, 0xfff6, 10, "SWAP-SPACE", probe_swap0 }, |
| 726 | { "swap", 0, 0xfff6, 10, "SWAPSPACE2", probe_swap1 }, |
Karel Zak | abaa112 | 2005-09-06 06:42:49 -0400 | [diff] [blame] | 727 | { "swsuspend", 0, 0xfff6, 9, "S1SUSPEND", probe_swap1 }, |
| 728 | { "swsuspend", 0, 0xfff6, 9, "S2SUSPEND", probe_swap1 }, |
Theodore Ts'o | 2c92375 | 2005-01-21 17:57:56 -0500 | [diff] [blame] | 729 | { "ocfs", 0, 8, 9, "OracleCFS", probe_ocfs }, |
| 730 | { "ocfs2", 1, 0, 6, "OCFSV2", probe_ocfs2 }, |
| 731 | { "ocfs2", 2, 0, 6, "OCFSV2", probe_ocfs2 }, |
| 732 | { "ocfs2", 4, 0, 6, "OCFSV2", probe_ocfs2 }, |
| 733 | { "ocfs2", 8, 0, 6, "OCFSV2", probe_ocfs2 }, |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 734 | { NULL, 0, 0, 0, NULL, NULL } |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 735 | }; |
| 736 | |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 737 | /* |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 738 | * Verify that the data in dev is consistent with what is on the actual |
| 739 | * block device (using the devname field only). Normally this will be |
| 740 | * called when finding items in the cache, but for long running processes |
| 741 | * is also desirable to revalidate an item before use. |
| 742 | * |
| 743 | * If we are unable to revalidate the data, we return the old data and |
| 744 | * do not set the BLKID_BID_FL_VERIFIED flag on it. |
| 745 | */ |
Theodore Ts'o | 18d1296 | 2005-01-27 19:51:47 -0500 | [diff] [blame] | 746 | blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev) |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 747 | { |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 748 | struct blkid_magic *id; |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 749 | struct blkid_probe probe; |
Theodore Ts'o | ba5e384 | 2006-03-10 18:11:35 -0500 | [diff] [blame] | 750 | blkid_tag_iterate iter; |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 751 | unsigned char *buf; |
Theodore Ts'o | ba5e384 | 2006-03-10 18:11:35 -0500 | [diff] [blame] | 752 | const char *type, *value; |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 753 | struct stat st; |
Theodore Ts'o | 7ce0806 | 2004-04-19 21:42:18 -0400 | [diff] [blame] | 754 | time_t diff, now; |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 755 | int idx; |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 756 | |
| 757 | if (!dev) |
| 758 | return NULL; |
| 759 | |
Theodore Ts'o | 7ce0806 | 2004-04-19 21:42:18 -0400 | [diff] [blame] | 760 | now = time(0); |
| 761 | diff = now - dev->bid_time; |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 762 | |
Theodore Ts'o | e324b25 | 2006-03-12 23:25:15 -0500 | [diff] [blame] | 763 | if ((now > dev->bid_time) && (diff > 0) && |
| 764 | ((diff < BLKID_PROBE_MIN) || |
| 765 | (dev->bid_flags & BLKID_BID_FL_VERIFIED && |
| 766 | diff < BLKID_PROBE_INTERVAL))) |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 767 | return dev; |
| 768 | |
Theodore Ts'o | f0a22d0 | 2003-02-22 13:19:53 -0500 | [diff] [blame] | 769 | DBG(DEBUG_PROBE, |
Matthias Andree | 12a829d | 2006-05-30 01:48:51 +0200 | [diff] [blame] | 770 | printf("need to revalidate %s (time since last check %llu)\n", |
| 771 | dev->bid_name, (unsigned long long)diff)); |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 772 | |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 773 | if (((probe.fd = open(dev->bid_name, O_RDONLY)) < 0) || |
| 774 | (fstat(probe.fd, &st) < 0)) { |
Theodore Ts'o | 292811f | 2006-03-25 01:42:02 -0500 | [diff] [blame] | 775 | if (probe.fd >= 0) close(probe.fd); |
Theodore Ts'o | ce72b86 | 2003-02-14 01:31:45 -0500 | [diff] [blame] | 776 | if (errno == ENXIO || errno == ENODEV || errno == ENOENT) { |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 777 | blkid_free_dev(dev); |
| 778 | return NULL; |
| 779 | } |
| 780 | /* We don't have read permission, just return cache data. */ |
Theodore Ts'o | f0a22d0 | 2003-02-22 13:19:53 -0500 | [diff] [blame] | 781 | DBG(DEBUG_PROBE, |
| 782 | printf("returning unverified data for %s\n", |
| 783 | dev->bid_name)); |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 784 | return dev; |
| 785 | } |
| 786 | |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 787 | probe.cache = cache; |
| 788 | probe.dev = dev; |
| 789 | probe.sbbuf = 0; |
| 790 | probe.buf = 0; |
| 791 | probe.buf_max = 0; |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 792 | |
| 793 | /* |
| 794 | * Iterate over the type array. If we already know the type, |
| 795 | * then try that first. If it doesn't work, then blow away |
| 796 | * the type information, and try again. |
| 797 | * |
| 798 | */ |
| 799 | try_again: |
| 800 | type = 0; |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 801 | if (!dev->bid_type || !strcmp(dev->bid_type, "mdraid")) { |
| 802 | uuid_t uuid; |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 803 | |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 804 | if (check_mdraid(probe.fd, uuid) == 0) { |
Theodore Ts'o | ba5e384 | 2006-03-10 18:11:35 -0500 | [diff] [blame] | 805 | set_uuid(dev, uuid, 0); |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 806 | type = "mdraid"; |
| 807 | goto found_type; |
| 808 | } |
| 809 | } |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 810 | for (id = type_array; id->bim_type; id++) { |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 811 | if (dev->bid_type && |
| 812 | strcmp(id->bim_type, dev->bid_type)) |
| 813 | continue; |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 814 | |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 815 | idx = id->bim_kboff + (id->bim_sboff >> 10); |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 816 | buf = get_buffer(&probe, idx << 10, 1024); |
| 817 | if (!buf) |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 818 | continue; |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 819 | |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 820 | if (memcmp(id->bim_magic, buf + (id->bim_sboff&0x3ff), |
| 821 | id->bim_len)) |
| 822 | continue; |
| 823 | |
| 824 | if ((id->bim_probe == NULL) || |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 825 | (id->bim_probe(&probe, id, buf) == 0)) { |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 826 | type = id->bim_type; |
| 827 | goto found_type; |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 828 | } |
| 829 | } |
| 830 | |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 831 | if (!id->bim_type && dev->bid_type) { |
| 832 | /* |
Theodore Ts'o | ba5e384 | 2006-03-10 18:11:35 -0500 | [diff] [blame] | 833 | * Zap the device filesystem information and try again |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 834 | */ |
Theodore Ts'o | ba5e384 | 2006-03-10 18:11:35 -0500 | [diff] [blame] | 835 | iter = blkid_tag_iterate_begin(dev); |
| 836 | while (blkid_tag_next(iter, &type, &value) == 0) |
| 837 | blkid_set_tag(dev, type, 0, 0); |
| 838 | blkid_tag_iterate_end(iter); |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 839 | goto try_again; |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 840 | } |
| 841 | |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 842 | if (!dev->bid_type) { |
Theodore Ts'o | 292811f | 2006-03-25 01:42:02 -0500 | [diff] [blame] | 843 | if (probe.fd >= 0) close(probe.fd); |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 844 | blkid_free_dev(dev); |
| 845 | return NULL; |
| 846 | } |
| 847 | |
| 848 | found_type: |
| 849 | if (dev && type) { |
| 850 | dev->bid_devno = st.st_rdev; |
| 851 | dev->bid_time = time(0); |
| 852 | dev->bid_flags |= BLKID_BID_FL_VERIFIED; |
Theodore Ts'o | ce72b86 | 2003-02-14 01:31:45 -0500 | [diff] [blame] | 853 | cache->bic_flags |= BLKID_BIC_FL_CHANGED; |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 854 | |
Theodore Ts'o | 79dd234 | 2003-02-22 17:15:20 -0500 | [diff] [blame] | 855 | blkid_set_tag(dev, "TYPE", type, 0); |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 856 | |
Theodore Ts'o | 12b3c8e | 2005-05-07 14:38:10 -0400 | [diff] [blame] | 857 | DBG(DEBUG_PROBE, printf("%s: devno 0x%04llx, type %s\n", |
Matthias Andree | 12a829d | 2006-05-30 01:48:51 +0200 | [diff] [blame] | 858 | dev->bid_name, (long long)st.st_rdev, type)); |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 859 | } |
| 860 | |
Theodore Ts'o | ca74985 | 2005-09-10 21:07:23 -0400 | [diff] [blame] | 861 | if (probe.sbbuf) |
| 862 | free(probe.sbbuf); |
| 863 | if (probe.buf) |
| 864 | free(probe.buf); |
| 865 | close(probe.fd); |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 866 | |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 867 | return dev; |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 868 | } |
| 869 | |
Theodore Ts'o | 78e2edf | 2003-07-21 19:42:19 -0400 | [diff] [blame] | 870 | int blkid_known_fstype(const char *fstype) |
| 871 | { |
| 872 | struct blkid_magic *id; |
| 873 | |
| 874 | for (id = type_array; id->bim_type; id++) { |
| 875 | if (strcmp(fstype, id->bim_type) == 0) |
| 876 | return 1; |
| 877 | } |
| 878 | return 0; |
| 879 | } |
| 880 | |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 881 | #ifdef TEST_PROGRAM |
| 882 | int main(int argc, char **argv) |
| 883 | { |
Theodore Ts'o | 7a603aa | 2003-01-26 01:54:39 -0500 | [diff] [blame] | 884 | blkid_dev dev; |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 885 | blkid_cache cache; |
Theodore Ts'o | 79dd234 | 2003-02-22 17:15:20 -0500 | [diff] [blame] | 886 | int ret; |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 887 | |
| 888 | if (argc != 2) { |
| 889 | fprintf(stderr, "Usage: %s device\n" |
| 890 | "Probe a single device to determine type\n", argv[0]); |
| 891 | exit(1); |
| 892 | } |
Theodore Ts'o | 79dd234 | 2003-02-22 17:15:20 -0500 | [diff] [blame] | 893 | if ((ret = blkid_get_cache(&cache, "/dev/null")) != 0) { |
| 894 | fprintf(stderr, "%s: error creating cache (%d)\n", |
| 895 | argv[0], ret); |
| 896 | exit(1); |
| 897 | } |
Theodore Ts'o | 98999c3 | 2003-02-16 00:47:07 -0500 | [diff] [blame] | 898 | dev = blkid_get_dev(cache, argv[1], BLKID_DEV_NORMAL); |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 899 | if (!dev) { |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 900 | printf("%s: %s has an unsupported type\n", argv[0], argv[1]); |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 901 | return (1); |
| 902 | } |
Theodore Ts'o | 1e5630a | 2005-09-10 15:55:14 -0400 | [diff] [blame] | 903 | printf("TYPE='%s'\n", dev->bid_type ? dev->bid_type : "(null)"); |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 904 | if (dev->bid_label) |
Theodore Ts'o | 1e5630a | 2005-09-10 15:55:14 -0400 | [diff] [blame] | 905 | printf("LABEL='%s'\n", dev->bid_label); |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 906 | if (dev->bid_uuid) |
Theodore Ts'o | 1e5630a | 2005-09-10 15:55:14 -0400 | [diff] [blame] | 907 | printf("UUID='%s'\n", dev->bid_uuid); |
Theodore Ts'o | 50b380b | 2003-02-12 23:51:21 -0500 | [diff] [blame] | 908 | |
| 909 | blkid_free_dev(dev); |
Theodore Ts'o | e12f2ae | 2003-01-23 16:45:16 -0500 | [diff] [blame] | 910 | return (0); |
| 911 | } |
| 912 | #endif |