320 lines
11 KiB
Diff
320 lines
11 KiB
Diff
diff -uNr util-linux-2.12/mount/get_label_uuid.c ../patch/util-linux-2.12/mount/get_label_uuid.c
|
|
--- util-linux-2.12/mount/get_label_uuid.c 2002-11-26 12:18:01.000000000 +0100
|
|
+++ ../patch/util-linux-2.12/mount/get_label_uuid.c 2003-10-20 18:27:56.000000000 +0200
|
|
@@ -43,7 +43,139 @@
|
|
#endif
|
|
}
|
|
|
|
-/* for now, only ext2, ext3, xfs, ocfs are supported */
|
|
+/* Remove trailing spaces */
|
|
+static void remtrailspc(char *label) {
|
|
+ char *c;
|
|
+
|
|
+ c = strchr(label, 0)-1;
|
|
+ while (c >= label && *c == ' ')
|
|
+ *(c--) = 0;
|
|
+}
|
|
+
|
|
+static int handle_fat_dirent(struct fat_dirent *dirent, char **label) {
|
|
+ size_t namesize;
|
|
+
|
|
+ /* end-of-directory marker */
|
|
+ if (!dirent->s_filename[0])
|
|
+ return -1;
|
|
+
|
|
+ /* valid volume label */
|
|
+ if ((dirent->s_attr == 0x08 || dirent->s_attr == 0x28) && dirent->s_filename[0] != 0xe5) {
|
|
+
|
|
+ /* sanity check */
|
|
+ if (dirent->s_size[0] || dirent->s_size[1] || dirent->s_size[2] || dirent->s_size[3] ||
|
|
+ dirent->s_cluster[0] || dirent->s_cluster[1])
|
|
+ return -1;
|
|
+
|
|
+ namesize = sizeof(dirent->s_filename);
|
|
+ if (!(*label = calloc(namesize + 1, 1)))
|
|
+ return -1;
|
|
+ memcpy(*label, dirent->s_filename, namesize);
|
|
+ (*label)[namesize] = 0;
|
|
+ remtrailspc(*label);
|
|
+
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+static int read_volume_label_fat(int fd, struct fat_super_block *fatsb, char **label) {
|
|
+ unsigned i, m;
|
|
+ off_t o;
|
|
+
|
|
+ m = assemble2le(fatsb->s_dirents); /* root directory entries */
|
|
+
|
|
+ o = (off_t) assemble2le(fatsb->s_ssec) * /* bytes per sector */
|
|
+ ((off_t) assemble2le(fatsb->s_rsecs) + /* reserved sectors */
|
|
+ (off_t) assemble2le(fatsb->s_spfat) * /* sectors per fat */
|
|
+ (off_t) fatsb->s_nfats); /* number of fats */
|
|
+
|
|
+ for (i = 0; i < m; i++) {
|
|
+ struct fat_dirent dirent;
|
|
+ int rv;
|
|
+
|
|
+ if (lseek(fd, o, SEEK_SET) != o ||
|
|
+ read(fd, &dirent, sizeof(dirent)) != sizeof(dirent))
|
|
+ return -1;
|
|
+
|
|
+ if ((rv = handle_fat_dirent(&dirent, label)) != 1)
|
|
+ return rv;
|
|
+
|
|
+ o += sizeof(dirent);
|
|
+ }
|
|
+
|
|
+ return -1;
|
|
+}
|
|
+
|
|
+static int read_volume_label_fat32(int fd, struct fat32_super_block *fat32sb, char **label) {
|
|
+ unsigned c;
|
|
+ off_t fo, b, o;
|
|
+ int i, ifat;
|
|
+ size_t m, cs;
|
|
+
|
|
+ ifat = fat32sb->s_mirror[0] & 128 ? (fat32sb->s_mirror[0] & 0xF) : 0;
|
|
+
|
|
+ if (ifat >= fat32sb->s_nfats)
|
|
+ return -1;
|
|
+
|
|
+ fo = (off_t) assemble2le(fat32sb->s_ssec) * /* bytes per sector */
|
|
+ ((off_t) assemble2le(fat32sb->s_rsecs) + /* reserved sectors */
|
|
+ (off_t) assemble4le(fat32sb->s_spfat) * /* sectors per fat */
|
|
+ (off_t) ifat); /* number of FAT used */
|
|
+
|
|
+ b = (off_t) assemble2le(fat32sb->s_ssec) * /* bytes per sector */
|
|
+ ((off_t) assemble2le(fat32sb->s_rsecs) + /* reserved sectors */
|
|
+ (off_t) assemble4le(fat32sb->s_spfat) * /* sectors per fat */
|
|
+ (off_t) fat32sb->s_nfats); /* number of FATs */
|
|
+
|
|
+ c = assemble4le(fat32sb->s_rcluster) & 0x0fffffffL;
|
|
+ if (c < 2 || c >= 0x0ffffff0)
|
|
+ return -1;
|
|
+
|
|
+ m = cs = assemble2le(fat32sb->s_ssec) * (size_t) fat32sb->s_scluster;
|
|
+ o = b + (off_t) cs*(c-2);
|
|
+
|
|
+ for (i = 0; i < 0xFFFF; i++) { /* safety against DoS attack */
|
|
+ struct fat_dirent dirent;
|
|
+ int rv;
|
|
+
|
|
+ if (lseek(fd, o, SEEK_SET) != o ||
|
|
+ read(fd, &dirent, sizeof(dirent)) != sizeof(dirent))
|
|
+ return -1;
|
|
+
|
|
+ if ((rv = handle_fat_dirent(&dirent, label)) != 1)
|
|
+ return rv;
|
|
+
|
|
+ if (m > sizeof(dirent)) {
|
|
+ m -= sizeof(dirent);
|
|
+ o += sizeof(dirent);
|
|
+ } else {
|
|
+ off_t d;
|
|
+
|
|
+ /* next cluster */
|
|
+
|
|
+ d = fo+4*c;
|
|
+ if (lseek(fd, d, SEEK_SET) != d ||
|
|
+ read(fd, &c, 4) != 4)
|
|
+ return -1;
|
|
+
|
|
+ c = assemble4le((char*) &c) & 0x0fffffffL;
|
|
+ if (c < 2 || c >= 0x0ffffff0) {
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ m = cs;
|
|
+ o = b + cs*(c-2);
|
|
+ }
|
|
+ }
|
|
+
|
|
+
|
|
+ return -1;
|
|
+}
|
|
+
|
|
+
|
|
+/* for now, only ext2, ext3, xfs, ocfs, fat, fat32 are supported */
|
|
int
|
|
get_label_uuid(const char *device, char **label, char *uuid) {
|
|
int fd;
|
|
@@ -54,8 +186,10 @@
|
|
struct jfs_super_block jfssb;
|
|
struct ocfs_volume_header ovh; /* Oracle */
|
|
struct ocfs_volume_label olbl;
|
|
+ struct fat_super_block fatsb;
|
|
+ struct fat32_super_block fat32sb;
|
|
|
|
- fd = open(device, O_RDONLY);
|
|
+ fd = open(device, O_RDONLY);
|
|
if (fd < 0)
|
|
return rv;
|
|
|
|
@@ -111,7 +245,87 @@
|
|
memcpy(*label, jfssb.s_label, namesize);
|
|
}
|
|
rv = 0;
|
|
- }
|
|
+ } else if (lseek(fd, 0, SEEK_SET) == 0
|
|
+ && read(fd, (char*) &fat32sb, sizeof(fat32sb)) == sizeof(fat32sb)
|
|
+ && fat32sb.s_sig[0] == 0x55
|
|
+ && fat32sb.s_sig[1] == 0xAA
|
|
+ && (fat32sb.s_media & 0xF0) == 0xF0
|
|
+ && (fat32sb.s_spfat_old[0] == 0)
|
|
+ && (fat32sb.s_spfat_old[1] == 0)
|
|
+ && fat32sb.s_extsig == 0x29
|
|
+ && (memcmp(fat32sb.s_fs, "FAT32 ", 8) == 0)) {
|
|
+
|
|
+ *label = NULL;
|
|
+
|
|
+ /* If no root directory entry volume name was found use the one from the boot sector */
|
|
+ if (read_volume_label_fat32(fd, &fat32sb, label) != 0) {
|
|
+ if (memcmp(fat32sb.s_label, "NO NAME ", 11) != 0 &&
|
|
+ memcmp(fat32sb.s_label, " ", 11) != 0 &&
|
|
+ memcmp(fat32sb.s_label, "\0\0\0\0\0\0\0\0", 8) != 0) {
|
|
+
|
|
+ namesize = sizeof(fat32sb.s_label);
|
|
+ if ((*label = calloc(namesize + 1, 1)) != NULL) {
|
|
+ memcpy(*label, fat32sb.s_label, namesize);
|
|
+ (*label)[namesize] = 0;
|
|
+ remtrailspc(*label);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (*label) {
|
|
+
|
|
+ /* Set UUID from serial */
|
|
+ uuid[0] = fat32sb.s_serial[3];
|
|
+ uuid[1] = fat32sb.s_serial[2];
|
|
+ uuid[2] = fat32sb.s_serial[1];
|
|
+ uuid[3] = fat32sb.s_serial[0];
|
|
+ memset(uuid+4, 0, 12);
|
|
+
|
|
+ rv = 0;
|
|
+ }
|
|
+ } else if (lseek(fd, 0, SEEK_SET) == 0
|
|
+ && read(fd, (char*) &fatsb, sizeof(fatsb)) == sizeof(fatsb)
|
|
+ && fatsb.s_sig[0] == 0x55
|
|
+ && fatsb.s_sig[1] == 0xAA
|
|
+ && (fatsb.s_media & 0xF0) == 0xF0
|
|
+ && fatsb.s_extsig == 0x29
|
|
+ && (memcmp(fatsb.s_fs, "FAT12 ", 8) == 0
|
|
+ || memcmp(fatsb.s_fs, "FAT16 ", 8) == 0
|
|
+ || memcmp(fatsb.s_fs, "FAT ", 8) == 0
|
|
+ || memcmp(fatsb.s_fs, "\0\0\0\0\0\0\0\0", 8) == 0)
|
|
+ && memcmp(fatsb.s_fs2, "FAT32 ", 8) != 0) {
|
|
+
|
|
+ *label = NULL;
|
|
+
|
|
+ if (read_volume_label_fat(fd, &fatsb, label) != 0) {
|
|
+
|
|
+ /* If no root directory entry volume name was found use the one from the boot sector */
|
|
+ if (memcmp(fatsb.s_label, "NO NAME ", 11) != 0 &&
|
|
+ memcmp(fatsb.s_label, " ", 11) != 0 &&
|
|
+ memcmp(fatsb.s_label, "\0\0\0\0\0\0\0\0", 8) != 0) {
|
|
+
|
|
+ namesize = sizeof(fatsb.s_label);
|
|
+ if ((*label = calloc(namesize + 1, 1)) != NULL) {
|
|
+ memcpy(*label, fatsb.s_label, namesize);
|
|
+ (*label)[namesize] = 0;
|
|
+ remtrailspc(*label);
|
|
+ }
|
|
+
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (*label) {
|
|
+
|
|
+ /* Set UUID from serial */
|
|
+ uuid[0] = fatsb.s_serial[3];
|
|
+ uuid[1] = fatsb.s_serial[2];
|
|
+ uuid[2] = fatsb.s_serial[1];
|
|
+ uuid[3] = fatsb.s_serial[0];
|
|
+ memset(uuid+4, 0, 12);
|
|
+
|
|
+ rv = 0;
|
|
+ }
|
|
+ }
|
|
|
|
close(fd);
|
|
return rv;
|
|
diff -uNr util-linux-2.12/mount/linux_fs.h ../patch/util-linux-2.12/mount/linux_fs.h
|
|
--- util-linux-2.12/mount/linux_fs.h 2003-07-05 22:16:32.000000000 +0200
|
|
+++ ../patch/util-linux-2.12/mount/linux_fs.h 2003-10-20 18:07:06.000000000 +0200
|
|
@@ -122,13 +122,65 @@
|
|
u_char s_dummy[3];
|
|
u_char s_os[8]; /* "MSDOS5.0" or "MSWIN4.0" or "MSWIN4.1" */
|
|
/* mtools-3.9.4 writes "MTOOL394" */
|
|
- u_char s_dummy2[32];
|
|
+ u_char s_ssec[2]; /* bytes per sector */
|
|
+ u_char s_scluster; /* sectors per cluster */
|
|
+ u_char s_rsecs[2]; /* reserved sectors */
|
|
+ u_char s_nfats; /* number of FATs */
|
|
+ u_char s_dirents[2]; /* maximum root directory entries */
|
|
+ u_char s_nsecs[2]; /* total number of sectors */
|
|
+ u_char s_media; /* media type, upper nibble is 0xF */
|
|
+ u_char s_spfat[2]; /* sectors per fat */
|
|
+
|
|
+ u_char s_dummy2[14];
|
|
+ u_char s_extsig; /* extended signature */
|
|
+ u_char s_serial[4]; /* serial number */
|
|
u_char s_label[11]; /* for DOS? */
|
|
- u_char s_fs[8]; /* "FAT12 " or "FAT16 " or all zero */
|
|
+ u_char s_fs[8]; /* "FAT12 " or "FAT16 " or all zero */
|
|
/* OS/2 BM has "FAT " here. */
|
|
- u_char s_dummy3[9];
|
|
- u_char s_label2[11]; /* for Windows? */
|
|
- u_char s_fs2[8]; /* garbage or "FAT32 " */
|
|
+
|
|
+ u_char s_dummy3[20];
|
|
+ u_char s_fs2[8]; /* "FAT32 " */
|
|
+
|
|
+ u_char s_dummy4[420];
|
|
+ u_char s_sig[2]; /* 55 AA */
|
|
+};
|
|
+
|
|
+struct fat32_super_block {
|
|
+ u_char s_dummy[3];
|
|
+ u_char s_os[8]; /* "MSDOS5.0" or "MSWIN4.0" or "MSWIN4.1" */
|
|
+ /* mtools-3.9.4 writes "MTOOL394" */
|
|
+
|
|
+ u_char s_ssec[2]; /* bytes per sector */
|
|
+ u_char s_scluster; /* sectors per cluster */
|
|
+ u_char s_rsecs[2]; /* reserved sectors */
|
|
+ u_char s_nfats; /* number of FATs */
|
|
+ u_char s_dirents[2]; /* maximum root directory entries */
|
|
+ u_char s_nsecs[2]; /* total number of sectors */
|
|
+ u_char s_media; /* media type, upper nibble is 0xF */
|
|
+ u_char s_spfat_old[2]; /* sectors per fat */
|
|
+
|
|
+ u_char s_dummy2[12];
|
|
+ u_char s_spfat[4]; /* sectors per FAT */
|
|
+ u_char s_mirror[2]; /* mirror flag */
|
|
+ u_char s_version[2]; /* fs version */
|
|
+ u_char s_rcluster[4]; /* root directory cluster */
|
|
+
|
|
+ u_char s_dummy3[18];
|
|
+ u_char s_extsig; /* extended signature 0x29 */
|
|
+ u_char s_serial[4]; /* serial number */
|
|
+ u_char s_label[11]; /* label */
|
|
+ u_char s_fs[8]; /* filesystem type "FAT32 " */
|
|
+
|
|
+ u_char s_dummy4[420];
|
|
+ u_char s_sig[2]; /* 55 AA */
|
|
+};
|
|
+
|
|
+struct fat_dirent {
|
|
+ u_char s_filename[11]; /* Filename with extension */
|
|
+ u_char s_attr; /* File attribute flags */
|
|
+ u_char s_dummy[14];
|
|
+ u_char s_cluster[2]; /* Starting cluster */
|
|
+ u_char s_size[4]; /* File size */
|
|
};
|
|
|
|
#define XFS_SUPER_MAGIC "XFSB"
|