How to use fstab-sync?

Kay Sievers kay.sievers at vrfy.org
Tue Aug 17 19:27:44 PDT 2004


On Tue, Aug 17, 2004 at 02:42:50PM +0200, Kay Sievers wrote:
> On Tue, 2004-08-17 at 14:24 +0200, Thomas Gufler wrote:
> > Am Dienstag, 17. August 2004 11:40 schrieb Kay Sievers:
> > > On Tue, 2004-08-17 at 11:30 +0200, David Zeuthen wrote:
> > > > On Tue, 2004-08-17 at 10:44 +0200, Thomas Gufler wrote:
> > > > > Hi,
> > > > >
> > > > > thanks for your answer. I made the symlink and now fstab-sync works.
> > > > >
> > > > > Now I am faced with an other (small) problem:
> > > > > fstab-sync adds an entry for my usbstick with msdos as file system
> > > > > type. But with msdos as type the length of the filename is limited to 8
> > > > > (+3 extension) characters. So the filenames look like this:
> > > > > semina~1.sxw
> > > > > However if I mount my usbstick with vfat as type I get the full file
> > > > > name (e.g. SeminararbeitS2.sxw)
> > > > > IMHO it would be better if fstab-sync also use vfat as type.
> > > >
> > > > Right. I'm also facing this problem; I've put in a small hack such that
> > > > volume_id returns vfat even though it is probed as msdos and now it
> > > > EWORKSME. Kay, any comments?
> > >
> > > If volume_id returns msdos we can't be sure, that its's really vfat. But
> > > the kernel can mount it anyhow as vfat. I think it's better to do the
> > > trick it in fstab-sync itself. Thomas, you can reformat it with
> > > mfks.vfat too :)
> > 
> > Yes, I can, but that way I end with a volume.fstype msdos. 
> > What I did: mkfs.vfat /dev/sda1 (do I need an options ?)
> > When I look now in the hal-device-manager I get a device "Volume (msdos)" 
> > and volume.fstype string msdos.
> 
> Yes, you are right, sorry for the confusion.
> 
> > After that I reformated the usbstick with Windows XP (choose file system: 
> > FAT32) and in h-d-m I get device "NO NAME" and volume.fstype vfat. 
> 
> Only FAT32 is vfat in volume_id, will see what I can do...
> 
> I will have a look at volume_id if we can clearly see what we have, not
> only looking at the signature. Stay tuned!

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.

'NO NAME' is handled as an empty label now.

XP stores the label not in the superblock (That's why Thomas got the 'NO NAME').
It creates a special entry in the root directory with the name and ignores
the superblock if it finds the directory entry. If we find such a label, we
do the same now.

Note:
If you change the FAT label with a _simple_ tools, but have a ATTR_LABEL in
the root dir, HAL will ignore it and read the label from the directory.

David, it would be nice if you can check it with your bad floppy :)

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 -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 02:04:00 -0000
@@ -83,6 +83,9 @@
 	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 -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 02:04:01 -0000
@@ -501,132 +501,243 @@
 	return 0;
 }
 
+#define FAT12_MAX			0xff5
+#define FAT16_MAX			0xfff5
+#define FAT_ATTR_VOLUME			0x08
 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;
 
+	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__)) *dir;
+
+	__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;
+	__u8 *label = NULL;
+	int i;
+
 	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;
+	/* trust only cluster_count, not the format */
+	if (strncmp(vs->type.fat32.magic, "MSWIN", 5) == 0)
+		goto valid;
 
-found:
-	set_label_raw(id, vs->label, 11);
-	set_label_string(id, vs->label, 11);
-	set_uuid(id, vs->serno, 4);
+	if (strncmp(vs->type.fat32.magic, "FAT32   ", 8) == 0)
+		goto valid;
 
-	id->type_id = VOLUME_ID_FILESYSTEM;
-	id->format_id = VOLUME_ID_VFAT;
-	id->format = "vfat";
+	if (strncmp(vs->type.fat.magic, "FAT16   ", 8) == 0)
+		goto valid;
 
-	return 0;
-}
+	if (strncmp(vs->type.fat.magic, "MSDOS", 5) == 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;
-
-	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
+	 * Bad, no signature. 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:
+	dbg("sectors_per_cluster 0x%x", vs->sectors_per_cluster);
+
+	sector_size = le16_to_cpu(vs->sector_size);
+	dbg("sector_size 0x%x", sector_size);
+
+	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 * 32) + (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 = get_buffer(id, root_start,
+			 root_dir_entries * sizeof(struct vfat_dir_entry));
+	if (buf == NULL)
+		goto found;
+	dir = (struct msdos_dir_slot*) buf;
+
+	for (i = 0; i <= root_dir_entries; i++) {
+		dbg("found name %s", dir[i].name);
+		if (dir[i].attr == FAT_ATTR_VOLUME) {
+			dbg("found ATTR_VOLUME id root dir");
+			label = dir[i].name;
+			break;
+		}
+	}
+
+	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:
+	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;
+	/* 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.
+	 */
+	root_dir_entries = vs->sectors_per_cluster * sector_size / 32;
+
 
+	/* the label may be a attribute in the root directory */
+	dbg("root dir start 0x%x", root_start);
+
+	buf = get_buffer(id, root_start,
+			 vs->sectors_per_cluster * sector_size);
+	if (buf == NULL)
+		goto found;
+
+	dir = (struct msdos_dir_slot*) buf;
+
+	for (i = 0; i <= root_dir_entries; i++) {
+		dbg("found name %s", dir[i].name);
+		if (dir[i].attr == FAT_ATTR_VOLUME) {
+			dbg("found ATTR_VOLUME id root dir");
+			label = dir[i].name;
+			break;
+		}
+	}
+
+	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 +1647,6 @@
 	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 +1675,6 @@
 		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 -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 02:04:01 -0000
@@ -21,7 +21,7 @@
 #ifndef _VOLUME_ID_H_
 #define _VOLUME_ID_H_
 
-#define VOLUME_ID_VERSION		010
+#define VOLUME_ID_VERSION		011
 
 #define VOLUME_ID_LABEL_SIZE		64
 #define VOLUME_ID_UUID_SIZE		16
@@ -45,7 +45,6 @@
 	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 @@
 	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