static void g_label_iso9660_taste(struct g_consumer *cp, char *label, size_t size) { struct g_provider *pp; char *sector, *volume; int i; g_topology_assert_not(); pp = cp->provider; label[0] = '\0'; if ((ISO9660_OFFSET % pp->sectorsize) != 0) return; sector = (char *)g_read_data(cp, ISO9660_OFFSET, pp->sectorsize, NULL); if (sector == NULL) return; if (bcmp(sector, ISO9660_MAGIC, sizeof(ISO9660_MAGIC) - 1) != 0) { g_free(sector); return; } G_LABEL_DEBUG(1, "ISO9660 file system detected on %s.", pp->name); volume = sector + 0x28; bzero(label, size); strlcpy(label, volume, MIN(size, VOLUME_LEN)); g_free(sector); for (i = size - 1; i > 0; i--) { if (label[i] == '\0') continue; else if (label[i] == ' ') label[i] = '\0'; else break; } }
void g_waitidle(void) { g_topology_assert_not(); mtx_lock(&g_eventlock); while (!TAILQ_EMPTY(&g_events)) msleep(&g_pending_events, &g_eventlock, PPAUSE, "g_waitidle", hz/5); mtx_unlock(&g_eventlock); curthread->td_pflags &= ~TDP_GEOM; }
static void g_label_ext2fs_taste(struct g_consumer *cp, char *label, size_t size) { struct g_provider *pp; e2sb_t *fs; char *s_volume_name; g_topology_assert_not(); pp = cp->provider; label[0] = '\0'; if ((EXT2FS_SB_OFFSET % pp->sectorsize) != 0) return; fs = (e2sb_t *)g_read_data(cp, EXT2FS_SB_OFFSET, pp->sectorsize, NULL); if (fs == NULL) return; /* Check for magic and versio n*/ if (fs->s_magic == EXT2_SUPER_MAGIC && fs->s_rev_level == EXT2_DYNAMIC_REV) { G_LABEL_DEBUG(1, "ext2fs file system detected on %s.", pp->name); } else { goto exit_free; } s_volume_name = fs->s_volume_name; /* Terminate label */ s_volume_name[sizeof(fs->s_volume_name) - 1] = '\0'; if (s_volume_name[0] == '/') s_volume_name += 1; /* Check for volume label */ if (s_volume_name[0] == '\0') goto exit_free; strlcpy(label, s_volume_name, size); exit_free: g_free(fs); }
static void g_label_reiserfs_taste(struct g_consumer *cp, char *label, size_t size) { struct g_provider *pp; reiserfs_sb_t *fs; g_topology_assert_not(); pp = cp->provider; label[0] = '\0'; /* Try old format */ fs = g_label_reiserfs_read_super(cp, REISERFS_OLD_DISK_OFFSET); if (fs == NULL) { /* Try new format */ fs = g_label_reiserfs_read_super(cp, REISERFS_NEW_DISK_OFFSET); } if (fs == NULL) return; /* Check version */ if (fs->s_version == 2) { G_LABEL_DEBUG(1, "reiserfs file system detected on %s.", pp->name); } else { goto exit_free; } /* Check for volume label */ if (fs->s_volume_name[0] == '\0') goto exit_free; /* Terminate label */ fs->s_volume_name[sizeof(fs->s_volume_name) - 1] = '\0'; strlcpy(label, fs->s_volume_name, size); exit_free: g_free(fs); }
static void g_label_msdosfs_taste(struct g_consumer *cp, char *label, size_t size) { struct g_provider *pp; FAT_BSBPB *pfat_bsbpb; FAT32_BSBPB *pfat32_bsbpb; FAT_DES *pfat_entry; uint8_t *sector0, *sector; g_topology_assert_not(); pp = cp->provider; sector0 = NULL; sector = NULL; bzero(label, size); /* Check if the sector size of the medium is a valid FAT sector size. */ switch(pp->sectorsize) { case 512: case 1024: case 2048: case 4096: break; default: G_LABEL_DEBUG(1, "MSDOSFS: %s: sector size %d not compatible.", pp->name, pp->sectorsize); return; } /* Load 1st sector with boot sector and boot parameter block. */ sector0 = (uint8_t *)g_read_data(cp, 0, pp->sectorsize, NULL); if (sector0 == NULL) return; /* Check for the FAT boot sector signature. */ if (sector0[510] != 0x55 || sector0[511] != 0xaa) { G_LABEL_DEBUG(1, "MSDOSFS: %s: no FAT signature found.", pp->name); goto error; } /* * Test if this is really a FAT volume and determine the FAT type. */ pfat_bsbpb = (FAT_BSBPB *)sector0; pfat32_bsbpb = (FAT32_BSBPB *)sector0; if (UINT16BYTES(pfat_bsbpb->BPB_FATSz16) != 0) { /* * If the BPB_FATSz16 field is not zero and the string "FAT" is * at the right place, this should be a FAT12 or FAT16 volume. */ if (strncmp(pfat_bsbpb->BS_FilSysType, "FAT", 3) != 0) { G_LABEL_DEBUG(1, "MSDOSFS: %s: FAT12/16 volume not valid.", pp->name); goto error; } G_LABEL_DEBUG(1, "MSDOSFS: %s: FAT12/FAT16 volume detected.", pp->name); /* A volume with no name should have "NO NAME " as label. */ if (strncmp(pfat_bsbpb->BS_VolLab, LABEL_NO_NAME, sizeof(pfat_bsbpb->BS_VolLab)) == 0) { G_LABEL_DEBUG(1, "MSDOSFS: %s: FAT12/16 volume has no name.", pp->name); goto error; } strlcpy(label, pfat_bsbpb->BS_VolLab, MIN(size, sizeof(pfat_bsbpb->BS_VolLab) + 1)); } else if (UINT32BYTES(pfat32_bsbpb->BPB_FATSz32) != 0) { uint32_t fat_FirstDataSector, fat_BytesPerSector, offset; /* * If the BPB_FATSz32 field is not zero and the string "FAT" is * at the right place, this should be a FAT32 volume. */ if (strncmp(pfat32_bsbpb->BS_FilSysType, "FAT", 3) != 0) { G_LABEL_DEBUG(1, "MSDOSFS: %s: FAT32 volume not valid.", pp->name); goto error; } G_LABEL_DEBUG(1, "MSDOSFS: %s: FAT32 volume detected.", pp->name); /* * If the volume label is not "NO NAME " we're done. */ if (strncmp(pfat32_bsbpb->BS_VolLab, LABEL_NO_NAME, sizeof(pfat32_bsbpb->BS_VolLab)) != 0) { strlcpy(label, pfat32_bsbpb->BS_VolLab, MIN(size, sizeof(pfat32_bsbpb->BS_VolLab) + 1)); goto endofchecks; } /* * If the volume label "NO NAME " is in the boot sector, the * label of FAT32 volumes may be stored as a special entry in * the root directory. */ fat_FirstDataSector = UINT16BYTES(pfat32_bsbpb->BPB_RsvdSecCnt) + (pfat32_bsbpb->BPB_NumFATs * UINT32BYTES(pfat32_bsbpb->BPB_FATSz32)); fat_BytesPerSector = UINT16BYTES(pfat32_bsbpb->BPB_BytsPerSec); G_LABEL_DEBUG(2, "MSDOSFS: FAT_FirstDataSector=0x%x, FAT_BytesPerSector=%d", fat_FirstDataSector, fat_BytesPerSector); for (offset = fat_BytesPerSector * fat_FirstDataSector;; offset += fat_BytesPerSector) { sector = (uint8_t *)g_read_data(cp, offset, fat_BytesPerSector, NULL); if (sector == NULL) goto error; pfat_entry = (FAT_DES *)sector; do { /* No more entries available. */ if (pfat_entry->DIR_Name[0] == 0) { G_LABEL_DEBUG(1, "MSDOSFS: %s: " "FAT32 volume has no name.", pp->name); goto error; } /* Skip empty or long name entries. */ if (pfat_entry->DIR_Name[0] == 0xe5 || (pfat_entry->DIR_Attr & FAT_DES_ATTR_LONG_NAME) == FAT_DES_ATTR_LONG_NAME) { continue; } /* * The name of the entry is the volume label if * ATTR_VOLUME_ID is set. */ if (pfat_entry->DIR_Attr & FAT_DES_ATTR_VOLUME_ID) { strlcpy(label, pfat_entry->DIR_Name, MIN(size, sizeof(pfat_entry->DIR_Name) + 1)); goto endofchecks; } } while((uint8_t *)(++pfat_entry) < (uint8_t *)(sector + fat_BytesPerSector)); g_free(sector); } } else { G_LABEL_DEBUG(1, "MSDOSFS: %s: no FAT volume detected.", pp->name); goto error; } endofchecks: g_label_rtrim(label, size); error: if (sector0 != NULL) g_free(sector0); if (sector != NULL) g_free(sector); }
static void g_label_ufs_taste_common(struct g_consumer *cp, char *label, size_t size, int what) { struct g_provider *pp; int sb, superblock; struct fs *fs; g_topology_assert_not(); pp = cp->provider; label[0] = '\0'; if (SBLOCKSIZE % cp->provider->sectorsize != 0) return; /* * Walk through the standard places that superblocks hide and look * for UFS magic. If we find magic, then check that the size in the * superblock corresponds to the size of the underlying provider. * Finally, look for a volume label and create an appropriate * provider based on that. */ for (sb = 0; (superblock = superblocks[sb]) != -1; sb++) { /* * Take care not to issue an invalid I/O request. The offset of * the superblock candidate must be multiples of the provider's * sector size, otherwise an FFS can't exist on the provider * anyway. */ if (superblock % cp->provider->sectorsize != 0) continue; fs = (struct fs *)g_read_data(cp, superblock, SBLOCKSIZE, NULL); if (fs == NULL) continue; /* Check for magic */ if (fs->fs_magic == FS_UFS1_MAGIC && fs->fs_fsize > 0) { /* Valid UFS1. */ } else if (fs->fs_magic == FS_UFS2_MAGIC && fs->fs_fsize > 0) { /* Valid UFS2. */ } else { g_free(fs); continue; } if (fs->fs_sblockloc != superblock || fs->fs_ncg < 1 || fs->fs_bsize < MINBSIZE || fs->fs_bsize < sizeof(struct fs)) { g_free(fs); continue; } G_LABEL_DEBUG(1, "%s file system detected on %s.", fs->fs_magic == FS_UFS1_MAGIC ? "UFS1" : "UFS2", pp->name); switch (what) { case G_LABEL_UFS_VOLUME: /* Check for volume label */ if (fs->fs_volname[0] == '\0') { g_free(fs); continue; } strlcpy(label, fs->fs_volname, size); break; case G_LABEL_UFS_ID: if (fs->fs_id[0] == 0 && fs->fs_id[1] == 0) { g_free(fs); continue; } snprintf(label, size, "%08x%08x", fs->fs_id[0], fs->fs_id[1]); break; } g_free(fs); break; } }
static void g_label_ntfs_taste(struct g_consumer *cp, char *label, size_t size) { struct g_provider *pp; struct bootfile *bf; struct filerec *fr; struct attr *atr; off_t voloff; char *filerecp, *ap; char mftrecsz, vnchar; int recsize, j; g_topology_assert_not(); label[0] = '\0'; pp = cp->provider; filerecp = NULL; bf = (struct bootfile *)g_read_data(cp, 0, pp->sectorsize, NULL); if (bf == NULL || strncmp(bf->bf_sysid, "NTFS ", 8) != 0) goto done; mftrecsz = (char)bf->bf_mftrecsz; recsize = (mftrecsz > 0) ? (mftrecsz * bf->bf_bps * bf->bf_spc) : (1 << -mftrecsz); if (recsize % pp->sectorsize != 0) goto done; voloff = bf->bf_mftcn * bf->bf_spc * bf->bf_bps + recsize * NTFS_VOLUMEINO; if (voloff % pp->sectorsize != 0) goto done; filerecp = g_read_data(cp, voloff, recsize, NULL); if (filerecp == NULL) goto done; fr = (struct filerec *)filerecp; if (fr->fr_fixup.fh_magic != NTFS_FILEMAGIC) goto done; for (ap = filerecp + fr->fr_attroff; atr = (struct attr *)ap, atr->a_hdr.a_type != -1; ap += atr->a_hdr.reclen) { if (atr->a_hdr.a_type == NTFS_A_VOLUMENAME) { if(atr->a_r.a_datalen >= size *2){ label[0] = 0; goto done; } /* *UNICODE to ASCII. * Should we need to use iconv(9)? */ for (j = 0; j < atr->a_r.a_datalen; j++) { vnchar = *(ap + atr->a_r.a_dataoff + j); if (j & 1) { if (vnchar) { label[0] = 0; goto done; } } else { label[j / 2] = vnchar; } } label[j / 2] = 0; break; } } done: if (bf != NULL) g_free(bf); if (filerecp != NULL) g_free(filerecp); }