diff --git a/ChangeLog b/ChangeLog index 537de3a94..4bb6bcb5d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-12-05 Natalia Portillo + + * DiscImageChef.sln: + Added generating XML metadata for file systems. + 2015-11-30 Natalia Portillo * .gitignore: diff --git a/DiscImageChef.Filesystems/AmigaDOS.cs b/DiscImageChef.Filesystems/AmigaDOS.cs index 034f9b705..a8b9a011e 100644 --- a/DiscImageChef.Filesystems/AmigaDOS.cs +++ b/DiscImageChef.Filesystems/AmigaDOS.cs @@ -232,6 +232,7 @@ namespace DiscImageChef.Plugins BootBlock bootBlk = new BootBlock(); RootBlock rootBlk = new RootBlock(); + xmlFSType = new Schemas.FileSystemType(); BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian; @@ -293,27 +294,35 @@ namespace DiscImageChef.Plugins { case 0: sbInformation.Append("Amiga Original File System"); + xmlFSType.Type = "Amiga OFS"; break; case 1: sbInformation.Append("Amiga Fast File System"); + xmlFSType.Type = "Amiga FFS"; break; case 2: sbInformation.Append("Amiga Original File System with international characters"); + xmlFSType.Type = "Amiga OFS"; break; case 3: sbInformation.Append("Amiga Fast File System with international characters"); + xmlFSType.Type = "Amiga FFS"; break; case 4: sbInformation.Append("Amiga Original File System with directory cache"); + xmlFSType.Type = "Amiga OFS"; break; case 5: sbInformation.Append("Amiga Fast File System with directory cache"); + xmlFSType.Type = "Amiga FFS"; break; case 6: sbInformation.Append("Amiga Original File System with long filenames"); + xmlFSType.Type = "Amiga OFS"; break; case 7: sbInformation.Append("Amiga Fast File System with long filenames"); + xmlFSType.Type = "Amiga FFS"; break; } @@ -323,7 +332,10 @@ namespace DiscImageChef.Plugins sbInformation.AppendLine(); if ((bootBlk.diskType & 0xFF) == 6 || (bootBlk.diskType & 0xFF) == 7) + { sbInformation.AppendLine("AFFS v2, following information may be completely incorrect or garbage."); + xmlFSType.Type = "Amiga FFS2"; + } sbInformation.AppendFormat("Volume name: {0}", rootBlk.diskName).AppendLine(); @@ -342,10 +354,9 @@ namespace DiscImageChef.Plugins information = sbInformation.ToString(); - /*xmlFSType = new Schemas.FileSystemType(); xmlFSType.CreationDate = DateHandlers.AmigaToDateTime(rootBlk.cDays, rootBlk.cMins, rootBlk.cTicks); xmlFSType.ModificationDate = DateHandlers.AmigaToDateTime(rootBlk.vDays, rootBlk.vMins, rootBlk.vTicks); -*/ + xmlFSType.Dirty = rootBlk.bitmapFlag != 0xFFFFFFFF; } static UInt32 AmigaChecksum(byte[] data) diff --git a/DiscImageChef.Filesystems/AppleHFS.cs b/DiscImageChef.Filesystems/AppleHFS.cs index c8eafea4c..28d41f040 100644 --- a/DiscImageChef.Filesystems/AppleHFS.cs +++ b/DiscImageChef.Filesystems/AppleHFS.cs @@ -359,6 +359,21 @@ namespace DiscImageChef.Plugins sb.AppendLine("Volume is not bootable."); information = sb.ToString(); + + xmlFSType = new Schemas.FileSystemType(); + xmlFSType.BackupDate = DateHandlers.MacToDateTime(MDB.drVolBkUp); + xmlFSType.Bootable = BB.signature == HFSBB_MAGIC; + xmlFSType.Clusters = MDB.drNmAlBlks; + xmlFSType.ClusterSize = (int)MDB.drAlBlkSiz; + xmlFSType.CreationDate = DateHandlers.MacToDateTime(MDB.drCrDate); + xmlFSType.Dirty = (MDB.drAtrb & 0x100) != 0x100; + xmlFSType.Files = MDB.drFilCnt; + xmlFSType.FreeClusters = MDB.drFreeBks; + xmlFSType.ModificationDate = DateHandlers.MacToDateTime(MDB.drLsMod); + xmlFSType.Type = "HFS"; + xmlFSType.VolumeName = MDB.drVN; + if (MDB.drFndrInfo6 != 0 && MDB.drFndrInfo7 != 0) + xmlFSType.VolumeSerial = String.Format("{0:X8}{1:x8}", MDB.drFndrInfo6, MDB.drFndrInfo7); return; } diff --git a/DiscImageChef.Filesystems/AppleHFSPlus.cs b/DiscImageChef.Filesystems/AppleHFSPlus.cs index dd6a81a1d..b4c9a2f55 100644 --- a/DiscImageChef.Filesystems/AppleHFSPlus.cs +++ b/DiscImageChef.Filesystems/AppleHFSPlus.cs @@ -256,6 +256,24 @@ namespace DiscImageChef.Plugins sb.AppendFormat("CNID of bootable Mac OS 8 or 9 directory: {0}", HPVH.drFndrInfo3).AppendLine(); sb.AppendFormat("CNID of bootable Mac OS X directory: {0}", HPVH.drFndrInfo5).AppendLine(); sb.AppendFormat("Mac OS X Volume ID: {0:X8}{1:X8}", HPVH.drFndrInfo6, HPVH.drFndrInfo7).AppendLine(); + + xmlFSType = new Schemas.FileSystemType(); + xmlFSType.BackupDate = DateHandlers.MacToDateTime(HPVH.backupDate); + if(HPVH.drFndrInfo0 != 0 || HPVH.drFndrInfo3 != 0 || HPVH.drFndrInfo5 != 0) + xmlFSType.Bootable = true; + xmlFSType.Clusters = HPVH.totalBlocks; + xmlFSType.ClusterSize = (int)HPVH.blockSize; + xmlFSType.CreationDate = DateHandlers.MacToDateTime(HPVH.createDate); + xmlFSType.Dirty = (HPVH.attributes & 0x100) != 0x100; + xmlFSType.Files = HPVH.fileCount; + xmlFSType.FreeClusters = HPVH.freeBlocks; + xmlFSType.ModificationDate = DateHandlers.MacToDateTime(HPVH.modifyDate); + if(HPVH.signature == 0x482B) + xmlFSType.Type = "HFS+"; + if(HPVH.signature == 0x4858) + xmlFSType.Type = "HFSX"; + if (HPVH.drFndrInfo6 != 0 && HPVH.drFndrInfo7 != 0) + xmlFSType.VolumeSerial = String.Format("{0:X8}{1:x8}", HPVH.drFndrInfo6, HPVH.drFndrInfo7); } else { diff --git a/DiscImageChef.Filesystems/AppleMFS.cs b/DiscImageChef.Filesystems/AppleMFS.cs index e91a9b75d..53b2a1150 100644 --- a/DiscImageChef.Filesystems/AppleMFS.cs +++ b/DiscImageChef.Filesystems/AppleMFS.cs @@ -195,6 +195,17 @@ namespace DiscImageChef.Plugins sb.AppendLine("Volume is not bootable."); information = sb.ToString(); + + xmlFSType = new Schemas.FileSystemType(); + xmlFSType.BackupDate = DateHandlers.MacToDateTime(MDB.drLsBkUp); + xmlFSType.Bootable = BB.signature == MFSBB_MAGIC; + xmlFSType.Clusters = MDB.drNmAlBlks; + xmlFSType.ClusterSize = (int)MDB.drAlBlkSiz; + xmlFSType.CreationDate = DateHandlers.MacToDateTime(MDB.drCrDate); + xmlFSType.Files = MDB.drNmFls; + xmlFSType.FreeClusters = MDB.drFreeBks; + xmlFSType.Type = "MFS"; + xmlFSType.VolumeName = MDB.drVN; return; } diff --git a/DiscImageChef.Filesystems/BFS.cs b/DiscImageChef.Filesystems/BFS.cs index 4d8f0a2aa..4658aea2a 100644 --- a/DiscImageChef.Filesystems/BFS.cs +++ b/DiscImageChef.Filesystems/BFS.cs @@ -219,6 +219,14 @@ namespace DiscImageChef.Plugins besb.indices_ag, besb.indices_len, besb.indices_len * besb.block_size).AppendLine(); information = sb.ToString(); + + xmlFSType = new Schemas.FileSystemType(); + xmlFSType.Clusters = besb.num_blocks; + xmlFSType.ClusterSize = (int)besb.block_size; + xmlFSType.Dirty = besb.flags == BEFS_DIRTY; + xmlFSType.FreeClusters = besb.num_blocks - besb.used_blocks; + xmlFSType.Type = "BeFS"; + xmlFSType.VolumeName = besb.name; } struct BeSuperBlock diff --git a/DiscImageChef.Filesystems/ChangeLog b/DiscImageChef.Filesystems/ChangeLog index 55f729cd8..97b9cf4a3 100644 --- a/DiscImageChef.Filesystems/ChangeLog +++ b/DiscImageChef.Filesystems/ChangeLog @@ -1,3 +1,30 @@ +2015-12-05 Natalia Portillo + + * FAT.cs: + * FFS.cs: + * ODS.cs: + * BFS.cs: + * HPFS.cs: + * NTFS.cs: + * SysV.cs: + * Opera.cs: + * extFS.cs: + * LisaFS.cs: + * ProDOS.cs: + * Plugin.cs: + * ext2FS.cs: + * SolarFS.cs: + * ISO9660.cs: + * MinixFS.cs: + * UNIXBFS.cs: + * AppleHFS.cs: + * AppleMFS.cs: + * AmigaDOS.cs: + * PCEngine.cs: + * AppleHFSPlus.cs: + * DiscImageChef.Filesystems.csproj: + Added generating XML metadata for file systems. + 2015-12-04 Natalia Portillo * AmigaDOS.cs: diff --git a/DiscImageChef.Filesystems/DiscImageChef.Filesystems.csproj b/DiscImageChef.Filesystems/DiscImageChef.Filesystems.csproj index 5efafd91a..cf0c7f801 100644 --- a/DiscImageChef.Filesystems/DiscImageChef.Filesystems.csproj +++ b/DiscImageChef.Filesystems/DiscImageChef.Filesystems.csproj @@ -84,5 +84,9 @@ {CCAA7AFE-C094-4D82-A66D-630DE8A3F545} DiscImageChef.Console + + {9F213318-5CB8-4066-A757-074489C9F818} + DiscImageChef.Metadata + \ No newline at end of file diff --git a/DiscImageChef.Filesystems/FAT.cs b/DiscImageChef.Filesystems/FAT.cs index 9eaefac2f..19e079cc1 100644 --- a/DiscImageChef.Filesystems/FAT.cs +++ b/DiscImageChef.Filesystems/FAT.cs @@ -177,6 +177,7 @@ namespace DiscImageChef.Plugins information = ""; StringBuilder sb = new StringBuilder(); + xmlFSType = new Schemas.FileSystemType(); byte[] dosString; // Space-padded bool isFAT32 = false; @@ -217,17 +218,22 @@ namespace DiscImageChef.Plugins if (fat32_signature == "FAT32 ") { sb.AppendLine("Microsoft FAT32"); // Seems easy, check reading + xmlFSType.Type = "FAT32"; isFAT32 = true; } else if ((first_fat_entry & 0xFFFFFFF0) == 0xFFFFFFF0) // Seems to be FAT16 { if ((first_fat_entry & 0xFF) == media_descriptor) + { sb.AppendLine("Microsoft FAT16"); // It MUST be FAT16, or... maybe not :S + xmlFSType.Type = "FAT16"; + } } else if ((first_fat_entry & 0x00FFFFF0) == 0x00FFFFF0) { //if((first_fat_entry & 0xFF) == media_descriptor) // Pre DOS<4 does not implement this, TOS does and is != sb.AppendLine("Microsoft FAT12"); // It MUST be FAT12, or... maybe not :S + xmlFSType.Type = "FAT12"; } else return; @@ -288,13 +294,20 @@ namespace DiscImageChef.Plugins sb.AppendFormat("OEM Name: {0}", BPB.OEMName).AppendLine(); sb.AppendFormat("{0} bytes per sector.", BPB.bps).AppendLine(); sb.AppendFormat("{0} sectors per cluster.", BPB.spc).AppendLine(); + xmlFSType.ClusterSize = BPB.bps * BPB.spc; sb.AppendFormat("{0} sectors reserved between BPB and FAT.", BPB.rsectors).AppendLine(); sb.AppendFormat("{0} FATs.", BPB.fats_no).AppendLine(); sb.AppendFormat("{0} entries on root directory.", BPB.root_ent).AppendLine(); if (BPB.sectors == 0) + { sb.AppendFormat("{0} sectors on volume ({1} bytes).", BPB.big_sectors, BPB.big_sectors * BPB.bps).AppendLine(); + xmlFSType.Clusters = BPB.big_sectors / BPB.spc; + } else + { sb.AppendFormat("{0} sectors on volume ({1} bytes).", BPB.sectors, BPB.sectors * BPB.bps).AppendLine(); + xmlFSType.Clusters = BPB.sectors / BPB.spc; + } if ((BPB.media & 0xF0) == 0xF0) sb.AppendFormat("Media format: 0x{0:X2}", BPB.media).AppendLine(); if (fat32_signature == "FAT32 ") @@ -312,20 +325,24 @@ namespace DiscImageChef.Plugins sb.AppendFormat("Sector of backup FAT32 parameter block: {0}", FAT32PB.backup_sector).AppendLine(); sb.AppendFormat("Drive number: 0x{0:X2}", FAT32PB.drive_no).AppendLine(); sb.AppendFormat("Volume Serial Number: 0x{0:X8}", FAT32PB.serial_no).AppendLine(); + xmlFSType.VolumeSerial = String.Format("{0:X8}", FAT32PB.serial_no); if ((FAT32PB.nt_flags & 0x01) == 0x01) { sb.AppendLine("Volume should be checked on next mount."); if ((EPB.nt_flags & 0x02) == 0x02) sb.AppendLine("Disk surface should be checked also."); + xmlFSType.Dirty = true; } sb.AppendFormat("Volume label: {0}", EPB.volume_label).AppendLine(); + xmlFSType.VolumeName = EPB.volume_label; sb.AppendFormat("Filesystem type: {0}", EPB.fs_type).AppendLine(); } else if (EPB.signature == 0x28 || EPB.signature == 0x29) { sb.AppendFormat("Drive number: 0x{0:X2}", EPB.drive_no).AppendLine(); sb.AppendFormat("Volume Serial Number: 0x{0:X8}", EPB.serial_no).AppendLine(); + xmlFSType.VolumeSerial = String.Format("{0:X8}", EPB.serial_no); if (EPB.signature == 0x29) { if ((EPB.nt_flags & 0x01) == 0x01) @@ -333,9 +350,11 @@ namespace DiscImageChef.Plugins sb.AppendLine("Volume should be checked on next mount."); if ((EPB.nt_flags & 0x02) == 0x02) sb.AppendLine("Disk surface should be checked also."); + xmlFSType.Dirty = true; } sb.AppendFormat("Volume label: {0}", EPB.volume_label).AppendLine(); + xmlFSType.VolumeName = EPB.volume_label; sb.AppendFormat("Filesystem type: {0}", EPB.fs_type).AppendLine(); } } diff --git a/DiscImageChef.Filesystems/FFS.cs b/DiscImageChef.Filesystems/FFS.cs index 9100d1040..0e6eca214 100644 --- a/DiscImageChef.Filesystems/FFS.cs +++ b/DiscImageChef.Filesystems/FFS.cs @@ -179,23 +179,30 @@ namespace DiscImageChef.Plugins return; } + xmlFSType = new Schemas.FileSystemType(); + switch (magic) { case UFS_MAGIC: sbInformation.AppendLine("UFS filesystem"); + xmlFSType.Type = "UFS"; break; case UFS_MAGIC_BW: sbInformation.AppendLine("BorderWare UFS filesystem"); + xmlFSType.Type = "UFS"; break; case UFS2_MAGIC: sbInformation.AppendLine("UFS2 filesystem"); + xmlFSType.Type = "UFS2"; break; case UFS_CIGAM: sbInformation.AppendLine("Big-endian UFS filesystem"); + xmlFSType.Type = "UFS"; break; case UFS_BAD_MAGIC: sbInformation.AppendLine("Incompletely initialized UFS filesystem"); sbInformation.AppendLine("BEWARE!!! Following information may be completely wrong!"); + xmlFSType.Type = "UFS"; break; } @@ -589,6 +596,8 @@ namespace DiscImageChef.Plugins sbInformation.AppendFormat("Cylinder group offset in cylinder: {0}", ufs_sb.fs_cgoffset).AppendLine(); sbInformation.AppendFormat("Volume last written on {0}", DateHandlers.UNIXUnsignedToDateTime(ufs_sb.fs_time_t)).AppendLine(); sbInformation.AppendFormat("{0} blocks in volume ({1} bytes)", ufs_sb.fs_size, ufs_sb.fs_size * ufs_sb.fs_bsize).AppendLine(); + xmlFSType.Clusters = ufs_sb.fs_size; + xmlFSType.ClusterSize = (int)ufs_sb.fs_bsize; sbInformation.AppendFormat("{0} data blocks in volume ({1} bytes)", ufs_sb.fs_dsize, ufs_sb.fs_dsize * ufs_sb.fs_bsize).AppendLine(); sbInformation.AppendFormat("{0} cylinder groups in volume", ufs_sb.fs_ncg).AppendLine(); sbInformation.AppendFormat("{0} bytes in a basic block", ufs_sb.fs_bsize).AppendLine(); @@ -620,7 +629,10 @@ namespace DiscImageChef.Plugins sbInformation.AppendFormat("Hardware sector interleave: {0}", ufs_sb.fs_interleave).AppendLine(); sbInformation.AppendFormat("Sector 0 skew: {0}/track", ufs_sb.fs_trackskew).AppendLine(); if (!fs_type_43bsd && ufs_sb.fs_id_1 > 0 && ufs_sb.fs_id_2 > 0) + { sbInformation.AppendFormat("Volume ID: 0x{0:X8}{1:X8}", ufs_sb.fs_id_1, ufs_sb.fs_id_2).AppendLine(); + xmlFSType.VolumeSerial = String.Format("{0:X8}{1:x8}", ufs_sb.fs_id_1, ufs_sb.fs_id_2); + } else if (fs_type_43bsd && ufs_sb.fs_headswitch_43bsd > 0 && ufs_sb.fs_trkseek_43bsd > 0) { sbInformation.AppendFormat("{0} µsec for head switch", ufs_sb.fs_headswitch_43bsd).AppendLine(); @@ -638,10 +650,14 @@ namespace DiscImageChef.Plugins sbInformation.AppendFormat("{0} blocks per group", ufs_sb.fs_fpg / ufs_sb.fs_frag).AppendLine(); sbInformation.AppendFormat("{0} directories", ufs_sb.fs_cstotal_ndir).AppendLine(); sbInformation.AppendFormat("{0} free blocks ({1} bytes)", ufs_sb.fs_cstotal_nbfree, ufs_sb.fs_cstotal_nbfree * ufs_sb.fs_bsize).AppendLine(); + xmlFSType.FreeClusters = ufs_sb.fs_cstotal_nbfree; sbInformation.AppendFormat("{0} free inodes", ufs_sb.fs_cstotal_nifree).AppendLine(); sbInformation.AppendFormat("{0} free frags", ufs_sb.fs_cstotal_nffree).AppendLine(); if (ufs_sb.fs_fmod == 1) + { sbInformation.AppendLine("Superblock is under modification"); + xmlFSType.Dirty = true; + } if (ufs_sb.fs_clean == 1) sbInformation.AppendLine("Volume is clean"); if (ufs_sb.fs_ronly == 1) @@ -656,17 +672,22 @@ namespace DiscImageChef.Plugins { sbInformation.AppendFormat("Volume last mounted on \"{0}\"", ufs_sb.fs_fsmnt_ufs2).AppendLine(); sbInformation.AppendFormat("Volume name: \"{0}\"", ufs_sb.fs_volname_ufs2).AppendLine(); + xmlFSType.VolumeName = ufs_sb.fs_volname_ufs2; sbInformation.AppendFormat("Volume ID: 0x{0:X16}", ufs_sb.fs_swuid_ufs2).AppendLine(); + xmlFSType.VolumeSerial = String.Format("{0:X16}", ufs_sb.fs_swuid_ufs2); sbInformation.AppendFormat("Last searched cylinder group: {0}", ufs_sb.fs_cgrotor_ufs2).AppendLine(); sbInformation.AppendFormat("{0} contiguously allocated directories", ufs_sb.fs_contigdirs_ufs2).AppendLine(); sbInformation.AppendFormat("Standard superblock LBA: {0}", ufs_sb.fs_sblockloc_ufs2).AppendLine(); sbInformation.AppendFormat("{0} directories", ufs_sb.fs_cstotal_ndir_ufs2).AppendLine(); sbInformation.AppendFormat("{0} free blocks ({1} bytes)", ufs_sb.fs_cstotal_nbfree_ufs2, ufs_sb.fs_cstotal_nbfree_ufs2 * ufs_sb.fs_bsize).AppendLine(); + xmlFSType.FreeClusters = (long)ufs_sb.fs_cstotal_nbfree_ufs2; sbInformation.AppendFormat("{0} free inodes", ufs_sb.fs_cstotal_nifree_ufs2).AppendLine(); sbInformation.AppendFormat("{0} free frags", ufs_sb.fs_cstotal_nffree_ufs2).AppendLine(); sbInformation.AppendFormat("{0} free clusters", ufs_sb.fs_cstotal_numclusters_ufs2).AppendLine(); sbInformation.AppendFormat("Volume last written on {0}", DateHandlers.UNIXUnsignedToDateTime(ufs_sb.fs_time_sec_ufs2)).AppendLine(); + xmlFSType.ModificationDate = DateHandlers.UNIXUnsignedToDateTime(ufs_sb.fs_time_sec_ufs2); sbInformation.AppendFormat("{0} blocks ({1} bytes)", ufs_sb.fs_size_ufs2, ufs_sb.fs_size_ufs2 * ufs_sb.fs_bsize).AppendLine(); + xmlFSType.Clusters = (long)ufs_sb.fs_dsize_ufs2; sbInformation.AppendFormat("{0} data blocks ({1} bytes)", ufs_sb.fs_dsize_ufs2, ufs_sb.fs_dsize_ufs2 * ufs_sb.fs_bsize).AppendLine(); sbInformation.AppendFormat("Cylinder group summary area LBA: {0}", ufs_sb.fs_csaddr_ufs2).AppendLine(); sbInformation.AppendFormat("{0} blocks pending of being freed", ufs_sb.fs_pendingblocks_ufs2).AppendLine(); diff --git a/DiscImageChef.Filesystems/HPFS.cs b/DiscImageChef.Filesystems/HPFS.cs index 3bcf53fd6..5282b0c77 100644 --- a/DiscImageChef.Filesystems/HPFS.cs +++ b/DiscImageChef.Filesystems/HPFS.cs @@ -247,6 +247,14 @@ namespace DiscImageChef.Plugins sb.AppendLine("Unknown flag 0x40 on flags2 is active"); if ((hpfs_sp.flags2 & 0x80) == 0x80) sb.AppendLine("Unknown flag 0x80 on flags2 is active"); + + xmlFSType = new Schemas.FileSystemType(); + xmlFSType.Dirty |= (hpfs_sp.flags1 & 0x01) == 0x01; + xmlFSType.Clusters = hpfs_bpb.big_sectors / hpfs_bpb.spc; + xmlFSType.ClusterSize = hpfs_bpb.bps * hpfs_bpb.spc; + xmlFSType.Type = "HPFS"; + xmlFSType.VolumeName = hpfs_bpb.volume_label; + xmlFSType.VolumeSerial = String.Format("{0:X8}", hpfs_bpb.serial_no); information = sb.ToString(); } diff --git a/DiscImageChef.Filesystems/ISO9660.cs b/DiscImageChef.Filesystems/ISO9660.cs index cde961896..eca650a07 100644 --- a/DiscImageChef.Filesystems/ISO9660.cs +++ b/DiscImageChef.Filesystems/ISO9660.cs @@ -874,6 +874,13 @@ namespace DiscImageChef.Plugins ISOMetadata.AppendFormat("Volume has always been effective.").AppendLine(); } + xmlFSType = new Schemas.FileSystemType(); + xmlFSType.Type = "ISO9660"; + if (Joliet) + { + xmlFSType.SystemIdentifier = decodedJolietVD.SystemIdentifier; + } + information = ISOMetadata.ToString(); } diff --git a/DiscImageChef.Filesystems/LisaFS.cs b/DiscImageChef.Filesystems/LisaFS.cs index 4af640ac0..00cdc2974 100644 --- a/DiscImageChef.Filesystems/LisaFS.cs +++ b/DiscImageChef.Filesystems/LisaFS.cs @@ -386,6 +386,18 @@ namespace DiscImageChef.Plugins information = sb.ToString(); + xmlFSType = new Schemas.FileSystemType(); + xmlFSType.BackupDate = mddf.dtvb; + xmlFSType.Clusters = mddf.vol_size; + xmlFSType.ClusterSize = mddf.clustersize * mddf.datasize; + xmlFSType.CreationDate = mddf.dtvc; + xmlFSType.Dirty = mddf.vol_left_mounted != 0; + xmlFSType.Files = mddf.filecount; + xmlFSType.FreeClusters = mddf.freecount; + xmlFSType.Type = "LisaFS"; + xmlFSType.VolumeName = mddf.volname; + xmlFSType.VolumeSerial = String.Format("{0:X16}", mddf.volid); + return; } } diff --git a/DiscImageChef.Filesystems/MinixFS.cs b/DiscImageChef.Filesystems/MinixFS.cs index 60a56d89a..1932a0db6 100644 --- a/DiscImageChef.Filesystems/MinixFS.cs +++ b/DiscImageChef.Filesystems/MinixFS.cs @@ -107,12 +107,16 @@ namespace DiscImageChef.Plugins magic = BigEndianBitConverter.ToUInt16(minix_sb_sector, 0x018); + xmlFSType = new Schemas.FileSystemType(); + if (magic == MINIX3_MAGIC || magic == MINIX3_CIGAM) { filenamesize = 60; minixVersion = "Minix V3 filesystem"; BigEndianBitConverter.IsLittleEndian = magic != MINIX3_CIGAM; + xmlFSType.Type = "Minix V3"; + minix3 = true; } else @@ -125,41 +129,49 @@ namespace DiscImageChef.Plugins filenamesize = 14; minixVersion = "Minix V1 filesystem"; BigEndianBitConverter.IsLittleEndian = true; + xmlFSType.Type = "Minix V1"; break; case MINIX_MAGIC2: filenamesize = 30; minixVersion = "Minix V1 filesystem"; BigEndianBitConverter.IsLittleEndian = true; + xmlFSType.Type = "Minix V1"; break; case MINIX2_MAGIC: filenamesize = 14; minixVersion = "Minix V2 filesystem"; BigEndianBitConverter.IsLittleEndian = true; + xmlFSType.Type = "Minix V2"; break; case MINIX2_MAGIC2: filenamesize = 30; minixVersion = "Minix V2 filesystem"; BigEndianBitConverter.IsLittleEndian = true; + xmlFSType.Type = "Minix V2"; break; case MINIX_CIGAM: filenamesize = 14; minixVersion = "Minix V1 filesystem"; BigEndianBitConverter.IsLittleEndian = false; + xmlFSType.Type = "Minix V1"; break; case MINIX_CIGAM2: filenamesize = 30; minixVersion = "Minix V1 filesystem"; BigEndianBitConverter.IsLittleEndian = false; + xmlFSType.Type = "Minix V1"; break; case MINIX2_CIGAM: filenamesize = 14; minixVersion = "Minix V2 filesystem"; BigEndianBitConverter.IsLittleEndian = false; + xmlFSType.Type = "Minix V2"; break; case MINIX2_CIGAM2: filenamesize = 30; minixVersion = "Minix V2 filesystem"; BigEndianBitConverter.IsLittleEndian = false; + xmlFSType.Type = "Minix V2"; break; default: return; @@ -195,6 +207,8 @@ namespace DiscImageChef.Plugins //sb.AppendFormat("log2 of blocks/zone: {0}", mnx_sb.s_log_zone_size).AppendLine(); // Apparently 0 sb.AppendFormat("{0} bytes maximum per file", mnx_sb.s_max_size).AppendLine(); sb.AppendFormat("On-disk filesystem version: {0}", mnx_sb.s_disk_version).AppendLine(); + + xmlFSType.ClusterSize = mnx_sb.s_blocksize; } else { @@ -224,6 +238,7 @@ namespace DiscImageChef.Plugins //sb.AppendFormat("log2 of blocks/zone: {0}", mnx_sb.s_log_zone_size).AppendLine(); // Apparently 0 sb.AppendFormat("{0} bytes maximum per file", mnx_sb.s_max_size).AppendLine(); sb.AppendFormat("Filesystem state: {0:X4}", mnx_sb.s_state).AppendLine(); + xmlFSType.ClusterSize = 1024; } information = sb.ToString(); } diff --git a/DiscImageChef.Filesystems/NTFS.cs b/DiscImageChef.Filesystems/NTFS.cs index e0ce26dd8..eb122ac80 100644 --- a/DiscImageChef.Filesystems/NTFS.cs +++ b/DiscImageChef.Filesystems/NTFS.cs @@ -166,6 +166,12 @@ namespace DiscImageChef.Plugins sb.AppendFormat("Volume serial number: {0:X16}", ntfs_bb.serial_no).AppendLine(); // sb.AppendFormat("Signature 2: 0x{0:X4}", ntfs_bb.signature2).AppendLine(); + + xmlFSType = new Schemas.FileSystemType(); + xmlFSType.ClusterSize = ntfs_bb.spc * ntfs_bb.bps; + xmlFSType.Clusters = ntfs_bb.sectors / ntfs_bb.spc; + xmlFSType.VolumeSerial = String.Format("{0:X16}", ntfs_bb.serial_no); + xmlFSType.Type = "NTFS"; information = sb.ToString(); } diff --git a/DiscImageChef.Filesystems/ODS.cs b/DiscImageChef.Filesystems/ODS.cs index 933cd7251..8cc49a186 100644 --- a/DiscImageChef.Filesystems/ODS.cs +++ b/DiscImageChef.Filesystems/ODS.cs @@ -257,6 +257,15 @@ namespace DiscImageChef.Plugins sb.AppendFormat("File protection: 0x{0:X4}", homeblock.fileprot).AppendLine(); sb.AppendFormat("Record protection: 0x{0:X4}", homeblock.recprot).AppendLine(); + xmlFSType = new Schemas.FileSystemType(); + xmlFSType.Type = "FILES-11"; + xmlFSType.ClusterSize = homeblock.cluster * 512; + xmlFSType.VolumeName = homeblock.volname; + xmlFSType.VolumeSerial = String.Format("{0:X8}", homeblock.serialnum); + xmlFSType.CreationDate = DateHandlers.VMSToDateTime(homeblock.credate); + if (homeblock.revdate > 0) + xmlFSType.ModificationDate = DateHandlers.VMSToDateTime(homeblock.revdate); + information = sb.ToString(); } diff --git a/DiscImageChef.Filesystems/Opera.cs b/DiscImageChef.Filesystems/Opera.cs index a8f2fbeac..c1c63c6ac 100644 --- a/DiscImageChef.Filesystems/Opera.cs +++ b/DiscImageChef.Filesystems/Opera.cs @@ -131,6 +131,12 @@ namespace DiscImageChef.Plugins SuperBlockMetadata.AppendFormat("Last root directory copy: {0}", sb.last_root_copy).AppendLine(); information = SuperBlockMetadata.ToString(); + + xmlFSType = new Schemas.FileSystemType(); + xmlFSType.Type = "Opera"; + xmlFSType.VolumeName = sb.volume_label; + xmlFSType.ClusterSize = sb.block_size; + xmlFSType.Clusters = sb.block_count; } struct OperaSuperBlock diff --git a/DiscImageChef.Filesystems/PCEngine.cs b/DiscImageChef.Filesystems/PCEngine.cs index f691a54e1..fffab0fc6 100644 --- a/DiscImageChef.Filesystems/PCEngine.cs +++ b/DiscImageChef.Filesystems/PCEngine.cs @@ -66,6 +66,8 @@ namespace DiscImageChef.Plugins public override void GetInformation(ImagePlugins.ImagePlugin imagePlugin, ulong partitionStart, ulong partitionEnd, out string information) { information = ""; + xmlFSType = new Schemas.FileSystemType(); + xmlFSType.Type = "PC Engine filesystem"; } } } \ No newline at end of file diff --git a/DiscImageChef.Filesystems/Plugin.cs b/DiscImageChef.Filesystems/Plugin.cs index fcd05187e..1f793c7d3 100644 --- a/DiscImageChef.Filesystems/Plugin.cs +++ b/DiscImageChef.Filesystems/Plugin.cs @@ -49,6 +49,15 @@ namespace DiscImageChef.Plugins public string Name; /// Plugin UUID. public Guid PluginUUID; + internal Schemas.FileSystemType xmlFSType; + + public Schemas.FileSystemType XmlFSType + { + get + { + return xmlFSType; + } + } protected Plugin() { diff --git a/DiscImageChef.Filesystems/ProDOS.cs b/DiscImageChef.Filesystems/ProDOS.cs index 8a79d7cc3..6004c7bf1 100644 --- a/DiscImageChef.Filesystems/ProDOS.cs +++ b/DiscImageChef.Filesystems/ProDOS.cs @@ -217,6 +217,13 @@ namespace DiscImageChef.Plugins information = sbInformation.ToString(); + xmlFSType = new Schemas.FileSystemType(); + xmlFSType.VolumeName = rootDirectoryKeyBlock.header.volume_name; + xmlFSType.CreationDate = rootDirectoryKeyBlock.header.creation_time; + xmlFSType.Files = rootDirectoryKeyBlock.header.file_count; + xmlFSType.Clusters = rootDirectoryKeyBlock.header.total_blocks; + xmlFSType.Type = "ProDOS"; + return; } diff --git a/DiscImageChef.Filesystems/SolarFS.cs b/DiscImageChef.Filesystems/SolarFS.cs index 80aae8117..13f83e93b 100644 --- a/DiscImageChef.Filesystems/SolarFS.cs +++ b/DiscImageChef.Filesystems/SolarFS.cs @@ -149,6 +149,12 @@ namespace DiscImageChef.Plugins sb.AppendFormat("{0} sectors per track", BPB.sptrk).AppendLine(); sb.AppendFormat("Volume name: {0}", BPB.vol_name).AppendLine(); + xmlFSType = new Schemas.FileSystemType(); + xmlFSType.Type = "SolarFS"; + xmlFSType.Clusters = BPB.sectors; + xmlFSType.ClusterSize = BPB.bps; + xmlFSType.VolumeName = BPB.vol_name; + information = sb.ToString(); } diff --git a/DiscImageChef.Filesystems/SysV.cs b/DiscImageChef.Filesystems/SysV.cs index 57427929a..e3debbbbf 100644 --- a/DiscImageChef.Filesystems/SysV.cs +++ b/DiscImageChef.Filesystems/SysV.cs @@ -262,6 +262,8 @@ namespace DiscImageChef.Plugins if (!sys7th && !sysv && !coherent && !xenix) return; + xmlFSType = new Schemas.FileSystemType(); + if (xenix) { byte[] xenix_strings = new byte[6]; @@ -293,18 +295,22 @@ namespace DiscImageChef.Plugins UInt32 bs = 512; sb.AppendLine("XENIX filesystem"); + xmlFSType.Type = "XENIX fs"; switch (xnx_sb.s_type) { case 1: sb.AppendLine("512 bytes per block"); + xmlFSType.ClusterSize = 512; break; case 2: sb.AppendLine("1024 bytes per block"); bs = 1024; + xmlFSType.ClusterSize = 1024; break; case 3: sb.AppendLine("2048 bytes per block"); bs = 2048; + xmlFSType.ClusterSize = 2048; break; default: sb.AppendFormat("Unknown s_type value: 0x{0:X8}", xnx_sb.s_type).AppendLine(); @@ -337,12 +343,17 @@ namespace DiscImageChef.Plugins if (xnx_sb.s_ronly > 0) sb.AppendLine("Volume is mounted read-only"); sb.AppendFormat("Superblock last updated on {0}", DateHandlers.UNIXUnsignedToDateTime(xnx_sb.s_time)).AppendLine(); + xmlFSType.ModificationDate = DateHandlers.UNIXUnsignedToDateTime(xnx_sb.s_time); sb.AppendFormat("Volume name: {0}", xnx_sb.s_fname).AppendLine(); + xmlFSType.VolumeName = xnx_sb.s_fname; sb.AppendFormat("Pack name: {0}", xnx_sb.s_fpack).AppendLine(); if (xnx_sb.s_clean == 0x46) sb.AppendLine("Volume is clean"); else + { sb.AppendLine("Volume is dirty"); + xmlFSType.Dirty = true; + } } if (sysv) @@ -411,21 +422,30 @@ namespace DiscImageChef.Plugins UInt32 bs = 512; if (sysvr4) + { sb.AppendLine("System V Release 4 filesystem"); + xmlFSType.Type = "SVR4 fs"; + } else + { sb.AppendLine("System V Release 2 filesystem"); + xmlFSType.Type = "SVR2 fs"; + } switch (sysv_sb.s_type) { case 1: sb.AppendLine("512 bytes per block"); + xmlFSType.ClusterSize = 512; break; case 2: sb.AppendLine("1024 bytes per block"); bs = 1024; + xmlFSType.ClusterSize = 1024; break; case 3: sb.AppendLine("2048 bytes per block"); bs = 2048; + xmlFSType.ClusterSize = 2048; break; default: sb.AppendFormat("Unknown s_type value: 0x{0:X8}", sysv_sb.s_type).AppendLine(); @@ -458,12 +478,17 @@ namespace DiscImageChef.Plugins if (sysv_sb.s_ronly > 0) sb.AppendLine("Volume is mounted read-only"); sb.AppendFormat("Superblock last updated on {0}", DateHandlers.UNIXUnsignedToDateTime(sysv_sb.s_time)).AppendLine(); + xmlFSType.ModificationDate = DateHandlers.UNIXUnsignedToDateTime(sysv_sb.s_time); sb.AppendFormat("Volume name: {0}", sysv_sb.s_fname).AppendLine(); + xmlFSType.VolumeName = sysv_sb.s_fname; sb.AppendFormat("Pack name: {0}", sysv_sb.s_fpack).AppendLine(); if (sysv_sb.s_state == (0x7C269D38 - sysv_sb.s_time)) sb.AppendLine("Volume is clean"); else + { sb.AppendLine("Volume is dirty"); + xmlFSType.Dirty = true; + } } if (coherent) @@ -490,6 +515,9 @@ namespace DiscImageChef.Plugins Array.Copy(sb_sector, 0x1EE, coh_strings, 0, 6); coh_sb.s_fpack = StringHandlers.CToString(coh_strings); + xmlFSType.Type = "Coherent fs"; + xmlFSType.ClusterSize = 512; + sb.AppendLine("Coherent UNIX filesystem"); if (imagePlugin.GetSectorSize() != 512) sb.AppendFormat("WARNING: Filesystem indicates {0} bytes/block while device indicates {1} bytes/sector", 512, 2048).AppendLine(); @@ -508,7 +536,9 @@ namespace DiscImageChef.Plugins if (coh_sb.s_ronly > 0) sb.AppendLine("Volume is mounted read-only"); sb.AppendFormat("Superblock last updated on {0}", DateHandlers.UNIXUnsignedToDateTime(coh_sb.s_time)).AppendLine(); + xmlFSType.ModificationDate = DateHandlers.UNIXUnsignedToDateTime(coh_sb.s_time); sb.AppendFormat("Volume name: {0}", coh_sb.s_fname).AppendLine(); + xmlFSType.VolumeName = coh_sb.s_fname; sb.AppendFormat("Pack name: {0}", coh_sb.s_fpack).AppendLine(); } @@ -536,6 +566,8 @@ namespace DiscImageChef.Plugins Array.Copy(sb_sector, 0x1B2, sys7_strings, 0, 6); v7_sb.s_fpack = StringHandlers.CToString(sys7_strings); + xmlFSType.Type = "UNIX 7th Edition fs"; + xmlFSType.ClusterSize = 512; sb.AppendLine("UNIX 7th Edition filesystem"); if (imagePlugin.GetSectorSize() != 512) sb.AppendFormat("WARNING: Filesystem indicates {0} bytes/block while device indicates {1} bytes/sector", 512, 2048).AppendLine(); @@ -554,7 +586,9 @@ namespace DiscImageChef.Plugins if (v7_sb.s_ronly > 0) sb.AppendLine("Volume is mounted read-only"); sb.AppendFormat("Superblock last updated on {0}", DateHandlers.UNIXUnsignedToDateTime(v7_sb.s_time)).AppendLine(); + xmlFSType.ModificationDate = DateHandlers.UNIXUnsignedToDateTime(v7_sb.s_time); sb.AppendFormat("Volume name: {0}", v7_sb.s_fname).AppendLine(); + xmlFSType.VolumeName = v7_sb.s_fname; sb.AppendFormat("Pack name: {0}", v7_sb.s_fpack).AppendLine(); } diff --git a/DiscImageChef.Filesystems/UNIXBFS.cs b/DiscImageChef.Filesystems/UNIXBFS.cs index d15804cee..6e080b635 100644 --- a/DiscImageChef.Filesystems/UNIXBFS.cs +++ b/DiscImageChef.Filesystems/UNIXBFS.cs @@ -105,6 +105,10 @@ namespace DiscImageChef.Plugins sb.AppendFormat("Filesystem name: {0}", bfs_sb.s_fsname).AppendLine(); sb.AppendFormat("Volume name: {0}", bfs_sb.s_volume).AppendLine(); + xmlFSType = new Schemas.FileSystemType(); + xmlFSType.Type = "BFS"; + xmlFSType.VolumeName = bfs_sb.s_volume; + information = sb.ToString(); } diff --git a/DiscImageChef.Filesystems/ext2FS.cs b/DiscImageChef.Filesystems/ext2FS.cs index 792cb18b6..6953dfa43 100644 --- a/DiscImageChef.Filesystems/ext2FS.cs +++ b/DiscImageChef.Filesystems/ext2FS.cs @@ -225,9 +225,12 @@ namespace DiscImageChef.Plugins Array.Copy(sb_sector, 0x1D8, forstrings, 0, 64); supblk.mount_options = StringHandlers.CToString(forstrings); + xmlFSType = new Schemas.FileSystemType(); + if (supblk.magic == ext2OldFSMagic) { sb.AppendLine("ext2 (old) filesystem"); + xmlFSType.Type = "ext2"; } else if (supblk.magic == ext2FSMagic) { @@ -250,11 +253,20 @@ namespace DiscImageChef.Plugins new_ext2 |= !ext3 && !ext4; if (new_ext2) + { sb.AppendLine("ext2 filesystem"); + xmlFSType.Type = "ext2"; + } if (ext3) + { sb.AppendLine("ext3 filesystem"); + xmlFSType.Type = "ext3"; + } if (ext4) + { sb.AppendLine("ext4 filesystem"); + xmlFSType.Type = "ext4"; + } } else { @@ -286,7 +298,10 @@ namespace DiscImageChef.Plugins } if (supblk.mkfs_t > 0) + { sb.AppendFormat("Volume was created on {0} for {1}", DateHandlers.UNIXUnsignedToDateTime(supblk.mkfs_t), ext_os).AppendLine(); + xmlFSType.CreationDate = DateHandlers.UNIXUnsignedToDateTime(supblk.mkfs_t); + } else sb.AppendFormat("Volume was created for {0}", ext_os).AppendLine(); @@ -343,6 +358,8 @@ namespace DiscImageChef.Plugins supblk.block_size = 1024; sb.AppendFormat("Volume has {0} blocks of {1} bytes, for a total of {2} bytes", blocks, 1024<<(int)supblk.block_size, blocks * (ulong)(1024<<(int)supblk.block_size)).AppendLine(); + xmlFSType.Clusters = (long)blocks; + xmlFSType.ClusterSize = 1024 << (int)supblk.block_size; if (supblk.mount_t > 0 || supblk.mount_c > 0) { if (supblk.mount_t > 0) @@ -381,14 +398,19 @@ namespace DiscImageChef.Plugins } if (supblk.write_t > 0) + { sb.AppendFormat("Last written on {0}", DateHandlers.UNIXUnsignedToDateTime(supblk.write_t)).AppendLine(); + xmlFSType.ModificationDate = DateHandlers.UNIXUnsignedToDateTime(supblk.write_t); + } else sb.AppendLine("Volume has never been written"); + xmlFSType.Dirty = true; switch (supblk.state) { case EXT2_VALID_FS: sb.AppendLine("Volume is clean"); + xmlFSType.Dirty = false; break; case EXT2_ERROR_FS: sb.AppendLine("Volume is dirty"); @@ -424,12 +446,16 @@ namespace DiscImageChef.Plugins sb.AppendFormat("Filesystem revision: {0}.{1}", supblk.revision, supblk.minor_revision).AppendLine(); if (supblk.uuid != Guid.Empty) + { sb.AppendFormat("Volume UUID: {0}", supblk.uuid).AppendLine(); + xmlFSType.VolumeSerial = supblk.uuid.ToString(); + } if (supblk.kbytes_written > 0) sb.AppendFormat("{0} KiB has been written on volume", supblk.kbytes_written).AppendLine(); sb.AppendFormat("{0} reserved and {1} free blocks", reserved, free).AppendLine(); + xmlFSType.FreeClusters = (long)free; sb.AppendFormat("{0} inodes with {1} free inodes ({2}%)", supblk.inodes, supblk.free_inodes, supblk.free_inodes * 100 / supblk.inodes).AppendLine(); if (supblk.first_inode > 0) sb.AppendFormat("First inode is {0}", supblk.first_inode).AppendLine(); diff --git a/DiscImageChef.Filesystems/extFS.cs b/DiscImageChef.Filesystems/extFS.cs index 4854f2f69..03dca307c 100644 --- a/DiscImageChef.Filesystems/extFS.cs +++ b/DiscImageChef.Filesystems/extFS.cs @@ -92,6 +92,11 @@ namespace DiscImageChef.Plugins sb.AppendFormat("Log zone size: {0}", ext_sb.logzonesize); sb.AppendFormat("Max zone size: {0}", ext_sb.maxsize); + xmlFSType = new Schemas.FileSystemType(); + xmlFSType.Type = "ext"; + xmlFSType.FreeClusters = ext_sb.freecountblk; + xmlFSType.ClusterSize = 1024; + information = sb.ToString(); } diff --git a/DiscImageChef.Metadata/ChangeLog b/DiscImageChef.Metadata/ChangeLog new file mode 100644 index 000000000..b26b327cc --- /dev/null +++ b/DiscImageChef.Metadata/ChangeLog @@ -0,0 +1,5 @@ +2015-12-05 Natalia Portillo + + * DiscImageChef.Metadata.csproj: + Added generating XML metadata for file systems. + diff --git a/DiscImageChef.Metadata/DiscImageChef.Metadata.csproj b/DiscImageChef.Metadata/DiscImageChef.Metadata.csproj index 5250a19db..0fae6cecd 100644 --- a/DiscImageChef.Metadata/DiscImageChef.Metadata.csproj +++ b/DiscImageChef.Metadata/DiscImageChef.Metadata.csproj @@ -9,7 +9,7 @@ Library DiscImageChef.Metadata DiscImageChef.Metadata - v4.5 + 2.2 true @@ -31,10 +31,13 @@ + - + + cicm.cs + \ No newline at end of file diff --git a/DiscImageChef.sln b/DiscImageChef.sln index 861fe4243..72cbcdc40 100644 --- a/DiscImageChef.sln +++ b/DiscImageChef.sln @@ -27,6 +27,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DiscImageChef.Interop", "Di EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DiscImageChef.Console", "DiscImageChef.Console\DiscImageChef.Console.csproj", "{CCAA7AFE-C094-4D82-A66D-630DE8A3F545}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DiscImageChef.Metadata", "DiscImageChef.Metadata\DiscImageChef.Metadata.csproj", "{9F213318-5CB8-4066-A757-074489C9F818}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x86 = Debug|x86 @@ -59,6 +61,10 @@ Global {9183F2E0-A879-4F23-9EE3-C6908F1332B2}.Debug|x86.Build.0 = Debug|Any CPU {9183F2E0-A879-4F23-9EE3-C6908F1332B2}.Release|x86.ActiveCfg = Release|Any CPU {9183F2E0-A879-4F23-9EE3-C6908F1332B2}.Release|x86.Build.0 = Release|Any CPU + {9F213318-5CB8-4066-A757-074489C9F818}.Debug|x86.ActiveCfg = Debug|Any CPU + {9F213318-5CB8-4066-A757-074489C9F818}.Debug|x86.Build.0 = Debug|Any CPU + {9F213318-5CB8-4066-A757-074489C9F818}.Release|x86.ActiveCfg = Release|Any CPU + {9F213318-5CB8-4066-A757-074489C9F818}.Release|x86.Build.0 = Release|Any CPU {CC48B324-A532-4A45-87A6-6F91F7141E8D}.Debug|x86.ActiveCfg = Debug|Any CPU {CC48B324-A532-4A45-87A6-6F91F7141E8D}.Debug|x86.Build.0 = Debug|Any CPU {CC48B324-A532-4A45-87A6-6F91F7141E8D}.Release|x86.ActiveCfg = Release|Any CPU