How to use fstab-sync?

Kay Sievers kay.sievers at vrfy.org
Wed Aug 18 11:24:56 PDT 2004


On Wed, Aug 18, 2004 at 11:25:50AM +0200, David Zeuthen wrote:
> On Wed, 2004-08-18 at 04:27 +0200, Kay Sievers wrote:
> > Here we go, but it would be nice if someone can test it, before we merge
> > it. I've removed the msdos format completely, we have only vfat now.
> > 
> > We also have a fssubtyp now, which can be 'fat12', 'fat16' or 'fat32'
> > for vfat.
> 
> Just curious, who would use that?

Oh, it may be nice to print something like this in a property window:
  Format: vfat(FAT32)

> > David, it would be nice if you can check it with your bad floppy :)
> > 
> 
> This breaks my good floppy; I'll mail you the image offlist.

Should work again :)

> > diff -u -r1.54 block_class_device.c
> 
> Please use the -p option when generating patches, it makes it a lot
> easier to spot which functions changes apply to.

Yes, done.

Thanks,
Kay
-------------- next part --------------
Index: hald/linux/block_class_device.c
===================================================================
RCS file: /cvs/hal/hal/hald/linux/block_class_device.c,v
retrieving revision 1.54
diff -u -p -r1.54 block_class_device.c
--- hald/linux/block_class_device.c	16 Aug 2004 18:52:39 -0000	1.54
+++ hald/linux/block_class_device.c	18 Aug 2004 18:16:19 -0000
@@ -83,6 +83,9 @@ set_volume_id_values(HalDevice *d, struc
 	char *product;
 
 	hal_device_property_set_string (d, "volume.fstype", vid->format);
+	if (vid->format_subtype != NULL)
+		hal_device_property_set_string (d, "volume.fssubtype",
+						vid->format_subtype);
 	hal_device_property_set_string (d, "volume.uuid", vid->uuid);
 	hal_device_property_set_string (d, "volume.label", vid->label);
 
Index: hald/linux/volume_id/volume_id.c
===================================================================
RCS file: /cvs/hal/hal/hald/linux/volume_id/volume_id.c,v
retrieving revision 1.22
diff -u -p -r1.22 volume_id.c
--- hald/linux/volume_id/volume_id.c	17 Aug 2004 09:53:44 -0000	1.22
+++ hald/linux/volume_id/volume_id.c	18 Aug 2004 18:16:20 -0000
@@ -501,132 +501,265 @@ static int probe_jfs(struct volume_id *i
 	return 0;
 }
 
+#define FAT12_MAX			0xff5
+#define FAT16_MAX			0xfff5
+#define FAT_ATTR_VOLUME			0x08
+struct vfat_dir_entry {
+	__u8	name[11];
+	__u8	attr;
+	__u16	time_creat;
+	__u16	date_creat;
+	__u16	time_acc;
+	__u16	date_acc;
+	__u16	cluster_high;
+	__u16	time_write;
+	__u16	date_write;
+	__u16	cluster_low;
+	__u32	size;
+} __attribute__((__packed__));
+
+static  char *_search_label_in_dir_block(const __u8 *buf, __u16 size)
+{
+	struct vfat_dir_entry *dir;
+	int i;
+	__u16 count;
+
+	dir = (struct vfat_dir_entry*) buf;
+	count = size / sizeof(struct vfat_dir_entry);
+	dbg("expected entries 0x%x", count);
+
+	for (i = 0; i <= count; i++) {
+		/* end marker */
+		if (dir[i].attr == 0x00) {
+			dbg("end of dir");
+			return NULL;
+		}
+
+		/* empty entry */
+		if (dir[i].attr == 0xe5)
+			continue;
+
+		if (dir[i].attr == FAT_ATTR_VOLUME) {
+			dbg("found ATTR_VOLUME id root dir");
+			return dir[i].name;
+		}
+
+		dbg("skip dir entry");
+	}
+
+	return NULL;
+}
+
 static int probe_vfat(struct volume_id *id, __u64 off)
 {
 	struct vfat_super_block {
-		__u8	ignored[3];
+		__u8	boot_jump[3];
 		__u8	sysid[8];
-		__u8	sector_size[2];
-		__u8	cluster_size;
+		__u16	sector_size;
+		__u8	sectors_per_cluster;
 		__u16	reserved;
 		__u8	fats;
-		__u8	dir_entries[2];
-		__u8	sectors[2];
+		__u16	dir_entries;
+		__u16	sectors;
 		__u8	media;
 		__u16	fat_length;
 		__u16	secs_track;
 		__u16	heads;
 		__u32	hidden;
 		__u32	total_sect;
-		__u32	fat32_length;
-		__u16	flags;
-		__u8	version[2];
-		__u32	root_cluster;
-		__u16	insfo_sector;
-		__u16	backup_boot;
-		__u16	reserved2[6];
-		__u8	unknown[3];
-		__u8	serno[4];
-		__u8	label[11];
-		__u8	magic[8];
-		__u8	dummy2[164];
-		__u8	pmagic[2];
+		union {
+			struct fat_super_block {
+				__u8	unknown[3];
+				__u8	serno[4];
+				__u8	label[11];
+				__u8	magic[8];
+				__u8	dummy2[192];
+				__u8	pmagic[2];
+			} __attribute__((__packed__)) fat;
+			struct fat32_super_block {
+				__u32	fat32_length;
+				__u16	flags;
+				__u8	version[2];
+				__u32	root_cluster;
+				__u16	insfo_sector;
+				__u16	backup_boot;
+				__u16	reserved2[6];
+				__u8	unknown[3];
+				__u8	serno[4];
+				__u8	label[11];
+				__u8	magic[8];
+				__u8	dummy2[164];
+				__u8	pmagic[2];
+			} __attribute__((__packed__)) fat32;
+		} __attribute__((__packed__)) type;
 	} __attribute__((__packed__)) *vs;
 
+	__u16 sector_size;
+	__u16 dir_entries;
+	__u32 sect_count;
+	__u16 reserved;
+	__u16 fat_size;
+	__u32 root_cluster;
+	__u32 dir_size;
+	__u32 cluster_count;
+	__u32 fat_length;
+	__u64 root_start;
+	__u32 start_data_sect;
+	__u32 root_cluster_sect_off;
+	__u16 root_dir_entries;
+	__u8 *buf;
+	__u32 buf_size;
+	__u8 *label = NULL;
+
 	vs = (struct vfat_super_block *) get_buffer(id, off, 0x200);
 	if (vs == NULL)
 		return -1;
 
-	if (strncmp(vs->magic, "MSWIN", 5) == 0)
-		goto found;
-	if (strncmp(vs->magic, "FAT32   ", 8) == 0)
-		goto found;
-	return -1;
+	sector_size = le16_to_cpu(vs->sector_size);
 
-found:
-	set_label_raw(id, vs->label, 11);
-	set_label_string(id, vs->label, 11);
-	set_uuid(id, vs->serno, 4);
+	/* believe only that's fat, don't trust the version
+	 * the cluster_count will tell us
+	 */
+	if (strncmp(vs->type.fat32.magic, "MSWIN", 5) == 0)
+		goto valid;
 
-	id->type_id = VOLUME_ID_FILESYSTEM;
-	id->format_id = VOLUME_ID_VFAT;
-	id->format = "vfat";
+	if (strncmp(vs->type.fat32.magic, "FAT32   ", 8) == 0)
+		goto valid;
 
-	return 0;
-}
+	if (strncmp(vs->type.fat.magic, "FAT16   ", 8) == 0)
+		goto valid;
 
-static int probe_msdos(struct volume_id *id, __u64 off)
-{
-	struct msdos_super_block {
-		__u8	boot_jump[3];
-		__u8	sysid[8];
-		__u16	sector_size;
-		__u8	cluster_size;
-		__u16	reserved;
-		__u8	fats;
-		__u8	dir_entries[2];
-		__u8	sectors[2];
-		__u8	media;
-		__u16	fat_length;
-		__u16	secs_track;
-		__u16	heads;
-		__u32	hidden;
-		__u32	total_sect;
-		__u8	unknown[3];
-		__u8	serno[4];
-		__u8	label[11];
-		__u8	magic[8];
-		__u8	dummy2[192];
-		__u8	pmagic[2];
-	} __attribute__((__packed__)) *ms;
+	if (strncmp(vs->type.fat.magic, "MSDOS", 5) == 0)
+		goto valid;
 
-	unsigned int	sector_size;
-
-	ms = (struct msdos_super_block *) get_buffer(id, off, 0x200);
-	if (ms == NULL)
-		return -1;
+	if (strncmp(vs->type.fat.magic, "FAT12   ", 8) == 0)
+		goto valid;
 
-	if (strncmp(ms->magic, "MSDOS", 5) == 0)
-		goto found;
-	if (strncmp(ms->magic, "FAT16   ", 8) == 0)
-		goto found;
-	if (strncmp(ms->magic, "FAT12   ", 8) == 0)
-		goto found;
 	/*
-	 * Bad, not finished. There are old floppies out there without a magic,
- 	 * so we check for well known values and guess if it's a msdos volume
+	 * There are old floppies out there without a magic, so we check
+	 * for well known values and guess if it's a fat volume
 	 */
 
 	/* boot jump address check */
-	if ((ms->boot_jump[0] != 0xeb || ms->boot_jump[2] != 0x90) &&
-	     ms->boot_jump[0] != 0xe9)
+	if ((vs->boot_jump[0] != 0xeb || vs->boot_jump[2] != 0x90) &&
+	     vs->boot_jump[0] != 0xe9)
 		return -1;
+
 	/* heads check */
-	if (ms->heads == 0)
+	if (vs->heads == 0)
 		return -1;
+
 	/* sector size check */
-	sector_size = le16_to_cpu(ms->sector_size);
 	if (sector_size != 0x200 && sector_size != 0x400 &&
 	    sector_size != 0x800 && sector_size != 0x1000)
 		return -1;
+
 	/* cluster size check*/	
-	if (ms->cluster_size == 0 || (ms->cluster_size & (ms->cluster_size-1)))
+	if (vs->sectors_per_cluster == 0 ||
+	    (vs->sectors_per_cluster & (vs->sectors_per_cluster-1)))
 		return -1;
+
 	/* media check */
-	if (ms->media < 0xf8 && ms->media != 0xf0)
+	if (vs->media < 0xf8 && vs->media != 0xf0)
 		return -1;
+
 	/* fat count*/
-	if (ms->fats != 2)
+	if (vs->fats != 2)
 		return -1;
 
-found:
-	set_label_raw(id, ms->label, 11);
-	set_label_string(id, ms->label, 11);
-	set_uuid(id, ms->serno, 4);
+valid:
+	sector_size = le16_to_cpu(vs->sector_size);
+	dbg("sector_size 0x%x", sector_size);
+	dbg("sectors_per_cluster 0x%x", vs->sectors_per_cluster);
+
+	dir_entries = le16_to_cpu(vs->dir_entries);
+	reserved = le16_to_cpu(vs->reserved);
+	dbg("reserved 0x%x", reserved);
+
+	sect_count = le16_to_cpu(vs->sectors);
+	if (sect_count == 0)
+		sect_count = vs->total_sect;
+	dbg("sect_count 0x%x", sect_count);
+
+	fat_length = le16_to_cpu(vs->fat_length);
+	if (fat_length == 0)
+		fat_length = le32_to_cpu(vs->type.fat32.fat32_length);
+	dbg("fat_length 0x%x", fat_length);
+
+	fat_size = fat_length * vs->fats;
+	dir_size = ((dir_entries * sizeof(struct vfat_dir_entry)) +
+			(sector_size-1)) / sector_size;
+	dbg("dir_size 0x%x", dir_size);
+
+	cluster_count = sect_count - (reserved + fat_size + dir_size);
+	cluster_count /= vs->sectors_per_cluster;
+	dbg("cluster_count 0x%x", cluster_count);
+
+	if (cluster_count < FAT12_MAX) {
+		id->format_subtype = "FAT12";
+	} else if (cluster_count < FAT16_MAX) {
+		id->format_subtype = "FAT16";
+	} else {
+		id->format_subtype = "FAT32";
+		goto fat32;
+	}
+
+	/* the label may be a attribute in the root directory */
+	root_start = (reserved + fat_size)* sector_size;
+	root_dir_entries = le16_to_cpu(vs->dir_entries);
+	dbg("root dir start 0x%x", root_start);
+
+	buf_size = root_dir_entries * sizeof(struct vfat_dir_entry);
+	buf = get_buffer(id, root_start, buf_size);
+	if (buf == NULL)
+		goto found;
+
+	label = _search_label_in_dir_block(buf, buf_size);
+
+	if (label != NULL && strncmp(label, "NO NAME    ", 11) != 0) {
+		set_label_raw(id, label, 11);
+		set_label_string(id, label, 11);
+	} else if (strncmp(vs->type.fat.label, "NO NAME    ", 11) != 0) {
+		set_label_raw(id, vs->type.fat.label, 11);
+		set_label_string(id, vs->type.fat.label, 11);
+	}
+	set_uuid(id, vs->type.fat.serno, 4);
+	goto found;
+
+fat32:
+	/* the label may be a attribute in the root directory */
+	root_cluster = le32_to_cpu(vs->type.fat32.root_cluster);
+	root_cluster_sect_off = (root_cluster - 2) * vs->sectors_per_cluster;
+	start_data_sect = reserved + fat_size + dir_size;
+	dbg("data area 0x%llx", (__u64) start_data_sect * sector_size);
+	root_start = (start_data_sect + root_cluster_sect_off) * sector_size;
+	dbg("root dir start 0x%x", root_start);
+
+	/* FIXME: on FAT32 the root dir is a cluster chain like any other
+	 * directory or a file, so we need to follow the chain, as the
+	 * label may be anywhere in the root directory. For now it's only
+	 * the first cluster.
+	 */
+	buf_size = vs->sectors_per_cluster * sector_size;
+	buf = get_buffer(id, root_start, buf_size);
+	if (buf == NULL)
+		goto found;
 
+	label = _search_label_in_dir_block(buf, buf_size);
+
+	if (label != NULL && strncmp(label, "NO NAME    ", 11) != 0) {
+		set_label_raw(id, label, 11);
+		set_label_string(id, label, 11);
+	} else if (strncmp(vs->type.fat32.label, "NO NAME    ", 11) == 0) {
+		set_label_raw(id, vs->type.fat32.label, 11);
+		set_label_string(id, vs->type.fat32.label, 11);
+	}
+	set_uuid(id, vs->type.fat32.serno, 4);
+
+found:
 	id->type_id = VOLUME_ID_FILESYSTEM;
-	id->format_id = VOLUME_ID_MSDOS;
-	id->format = "msdos";
+	id->format_id = VOLUME_ID_VFAT;
+	id->format = "vfat";
 
 	return 0;
 }
@@ -1536,9 +1669,6 @@ int volume_id_probe(struct volume_id *id
 	case VOLUME_ID_VFAT:
 		rc = probe_vfat(id, off);
 		break;
-	case VOLUME_ID_MSDOS:
-		rc = probe_msdos(id, off);
-		break;
 	case VOLUME_ID_UDF:
 		rc = probe_udf(id, off);
 		break;
@@ -1567,9 +1697,6 @@ int volume_id_probe(struct volume_id *id
 		rc = probe_vfat(id, off);
 		if (rc == 0)
 			break;
-		rc = probe_msdos(id, off);
-		if (rc == 0)
-			break;
 		rc = probe_msdos_part_table(id, off);
 		if (rc == 0)
 			break;
Index: hald/linux/volume_id/volume_id.h
===================================================================
RCS file: /cvs/hal/hal/hald/linux/volume_id/volume_id.h,v
retrieving revision 1.10
diff -u -p -r1.10 volume_id.h
--- hald/linux/volume_id/volume_id.h	17 Aug 2004 09:29:24 -0000	1.10
+++ hald/linux/volume_id/volume_id.h	18 Aug 2004 18:16:20 -0000
@@ -21,7 +21,7 @@
 #ifndef _VOLUME_ID_H_
 #define _VOLUME_ID_H_
 
-#define VOLUME_ID_VERSION		010
+#define VOLUME_ID_VERSION		012
 
 #define VOLUME_ID_LABEL_SIZE		64
 #define VOLUME_ID_UUID_SIZE		16
@@ -45,7 +45,6 @@ enum volume_id_format {
 	VOLUME_ID_REISERFS,
 	VOLUME_ID_XFS,
 	VOLUME_ID_JFS,
-	VOLUME_ID_MSDOS,
 	VOLUME_ID_VFAT,
 	VOLUME_ID_UDF,
 	VOLUME_ID_ISO9660,
@@ -71,6 +70,7 @@ struct volume_id {
 	enum		volume_id_type type_id;
 	enum		volume_id_format format_id;
 	char		*format;
+	char		*format_subtype;
 	struct volume_id_partition *partitions;
 	unsigned int	partition_count;
 	int		fd;
-------------- next part --------------
_______________________________________________
hal mailing list
hal at freedesktop.org
http://freedesktop.org/mailman/listinfo/hal


More information about the Hal mailing list