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