diff --git a/DiscImageChef.Filesystems/ISO9660/Dir.cs b/DiscImageChef.Filesystems/ISO9660/Dir.cs index cc4adac58..409e5e776 100644 --- a/DiscImageChef.Filesystems/ISO9660/Dir.cs +++ b/DiscImageChef.Filesystems/ISO9660/Dir.cs @@ -49,11 +49,15 @@ namespace DiscImageChef.Filesystems.ISO9660 public Errno ReadDir(string path, out List contents) { contents = null; - if(!mounted) return Errno.AccessDenied; - if(string.IsNullOrWhiteSpace(path) || path == "/") + if(!mounted) + return Errno.AccessDenied; + + if(string.IsNullOrWhiteSpace(path) || + path == "/") { contents = GetFilenames(rootDirectoryCache); + return Errno.NoError; } @@ -64,17 +68,23 @@ namespace DiscImageChef.Filesystems.ISO9660 if(directoryCache.TryGetValue(cutPath, out Dictionary currentDirectory)) { contents = currentDirectory.Keys.ToList(); + return Errno.NoError; } - string[] pieces = cutPath.Split(new[] {'/'}, StringSplitOptions.RemoveEmptyEntries); + string[] pieces = cutPath.Split(new[] + { + '/' + }, StringSplitOptions.RemoveEmptyEntries); KeyValuePair entry = rootDirectoryCache.FirstOrDefault(t => t.Key.ToLower(CultureInfo.CurrentUICulture) == pieces[0]); - if(string.IsNullOrEmpty(entry.Key)) return Errno.NoSuchFile; + if(string.IsNullOrEmpty(entry.Key)) + return Errno.NoSuchFile; - if(!entry.Value.Flags.HasFlag(FileFlags.Directory)) return Errno.NotDirectory; + if(!entry.Value.Flags.HasFlag(FileFlags.Directory)) + return Errno.NotDirectory; string currentPath = pieces[0]; @@ -84,18 +94,24 @@ namespace DiscImageChef.Filesystems.ISO9660 { entry = currentDirectory.FirstOrDefault(t => t.Key.ToLower(CultureInfo.CurrentUICulture) == pieces[p]); - if(string.IsNullOrEmpty(entry.Key)) return Errno.NoSuchFile; + if(string.IsNullOrEmpty(entry.Key)) + return Errno.NoSuchFile; - if(!entry.Value.Flags.HasFlag(FileFlags.Directory)) return Errno.NotDirectory; + if(!entry.Value.Flags.HasFlag(FileFlags.Directory)) + return Errno.NotDirectory; currentPath = p == 0 ? pieces[0] : $"{currentPath}/{pieces[p]}"; - if(directoryCache.TryGetValue(currentPath, out currentDirectory)) continue; + if(directoryCache.TryGetValue(currentPath, out currentDirectory)) + continue; - if(entry.Value.Extents.Count == 0) return Errno.InvalidArgument; + if(entry.Value.Extents.Count == 0) + return Errno.InvalidArgument; uint dirSizeInSectors = entry.Value.Extents[0].size / 2048; - if(entry.Value.Size % 2048 > 0) dirSizeInSectors++; + + if(entry.Value.Size % 2048 > 0) + dirSizeInSectors++; currentDirectory = cdi ? DecodeCdiDirectory(entry.Value.Extents[0].extent, dirSizeInSectors, @@ -118,19 +134,20 @@ namespace DiscImageChef.Filesystems.ISO9660 } contents = GetFilenames(currentDirectory); + return Errno.NoError; } List GetFilenames(Dictionary dirents) { List contents = new List(); + foreach(DecodedDirectoryEntry entry in dirents.Values) switch(@namespace) { case Namespace.Normal: contents.Add(entry.Filename.EndsWith(";1", StringComparison.Ordinal) - ? entry.Filename.Substring(0, entry.Filename.Length - 2) - : entry.Filename); + ? entry.Filename.Substring(0, entry.Filename.Length - 2) : entry.Filename); break; case Namespace.Vms: @@ -138,6 +155,7 @@ namespace DiscImageChef.Filesystems.ISO9660 case Namespace.Rrip: case Namespace.Romeo: contents.Add(entry.Filename); + break; default: throw new ArgumentOutOfRangeException(); } @@ -160,46 +178,55 @@ namespace DiscImageChef.Filesystems.ISO9660 Marshal.ByteArrayToStructureBigEndian(data, entryOff, CdiDirectoryRecordSize); - if(record.length == 0) break; + if(record.length == 0) + break; // Special entries for current and parent directories, skip them if(record.name_len == 1) - if(data[entryOff + DirectoryRecordSize] == 0 || data[entryOff + DirectoryRecordSize] == 1) + if(data[entryOff + DirectoryRecordSize] == 0 || + data[entryOff + DirectoryRecordSize] == 1) { entryOff += record.length; + continue; } - DecodedDirectoryEntry entry = new DecodedDirectoryEntry + var entry = new DecodedDirectoryEntry { Size = record.size, Filename = Encoding.GetString(data, entryOff + DirectoryRecordSize, record.name_len), VolumeSequenceNumber = record.volume_sequence_number, - Timestamp = DecodeHighSierraDateTime(record.date), - XattrLength = record.xattr_len + Timestamp = DecodeHighSierraDateTime(record.date), XattrLength = record.xattr_len }; if(record.size != 0) - entry.Extents = new List<(uint extent, uint size)> {(record.start_lbn, record.size)}; + entry.Extents = new List<(uint extent, uint size)> + { + (record.start_lbn, record.size) + }; if(record.flags.HasFlag(CdiFileFlags.Hidden)) { entry.Flags |= FileFlags.Hidden; + continue; } int systemAreaStart = entryOff + record.name_len + CdiDirectoryRecordSize; - if(systemAreaStart % 2 != 0) systemAreaStart++; + if(systemAreaStart % 2 != 0) + systemAreaStart++; + entry.CdiSystemArea = Marshal.ByteArrayToStructureBigEndian(data, systemAreaStart, CdiSystemAreaSize); - if(((CdiAttributes)entry.CdiSystemArea.Value.attributes).HasFlag(CdiAttributes.Directory)) + if(entry.CdiSystemArea.Value.attributes.HasFlag(CdiAttributes.Directory)) entry.Flags |= FileFlags.Directory; - if(!((CdiAttributes)entry.CdiSystemArea.Value.attributes).HasFlag(CdiAttributes.Directory) || - !usePathTable) entries[entry.Filename] = entry; + if(!entry.CdiSystemArea.Value.attributes.HasFlag(CdiAttributes.Directory) || + !usePathTable) + entries[entry.Filename] = entry; entryOff += record.length; } @@ -225,38 +252,43 @@ namespace DiscImageChef.Filesystems.ISO9660 Marshal.ByteArrayToStructureLittleEndian(data, entryOff, HighSierraDirectoryRecordSize); - if(record.length == 0) break; + if(record.length == 0) + break; // Special entries for current and parent directories, skip them if(record.name_len == 1) - if(data[entryOff + DirectoryRecordSize] == 0 || data[entryOff + DirectoryRecordSize] == 1) + if(data[entryOff + DirectoryRecordSize] == 0 || + data[entryOff + DirectoryRecordSize] == 1) { entryOff += record.length; + continue; } - DecodedDirectoryEntry entry = new DecodedDirectoryEntry + var entry = new DecodedDirectoryEntry { - Size = record.size, - Flags = record.flags, - Interleave = record.interleave, + Size = record.size, Flags = record.flags, Interleave = record.interleave, VolumeSequenceNumber = record.volume_sequence_number, Filename = Encoding.GetString(data, entryOff + DirectoryRecordSize, record.name_len), - Timestamp = DecodeHighSierraDateTime(record.date), - XattrLength = record.xattr_len + Timestamp = DecodeHighSierraDateTime(record.date), XattrLength = record.xattr_len }; if(record.size != 0) - entry.Extents = new List<(uint extent, uint size)> {(record.extent, record.size)}; + entry.Extents = new List<(uint extent, uint size)> + { + (record.extent, record.size) + }; if(entry.Flags.HasFlag(FileFlags.Directory) && usePathTable) { entryOff += record.length; + continue; } - if(!entries.ContainsKey(entry.Filename)) entries.Add(entry.Filename, entry); + if(!entries.ContainsKey(entry.Filename)) + entries.Add(entry.Filename, entry); entryOff += record.length; } @@ -264,7 +296,8 @@ namespace DiscImageChef.Filesystems.ISO9660 entryOff = 0; } - if(useTransTbl) DecodeTransTable(entries); + if(useTransTbl) + DecodeTransTable(entries); return entries; } @@ -283,38 +316,41 @@ namespace DiscImageChef.Filesystems.ISO9660 DirectoryRecord record = Marshal.ByteArrayToStructureLittleEndian(data, entryOff, DirectoryRecordSize); - if(record.length == 0) break; + if(record.length == 0) + break; // Special entries for current and parent directories, skip them if(record.name_len == 1) - if(data[entryOff + DirectoryRecordSize] == 0 || data[entryOff + DirectoryRecordSize] == 1) + if(data[entryOff + DirectoryRecordSize] == 0 || + data[entryOff + DirectoryRecordSize] == 1) { entryOff += record.length; + continue; } - DecodedDirectoryEntry entry = new DecodedDirectoryEntry + var entry = new DecodedDirectoryEntry { - Size = record.size, - Flags = record.flags, + Size = record.size, Flags = record.flags, Filename = - joliet - ? Encoding.BigEndianUnicode.GetString(data, entryOff + DirectoryRecordSize, - record.name_len) + joliet ? Encoding.BigEndianUnicode.GetString(data, entryOff + DirectoryRecordSize, + record.name_len) : Encoding.GetString(data, entryOff + DirectoryRecordSize, record.name_len), - FileUnitSize = record.file_unit_size, - Interleave = record.interleave, + FileUnitSize = record.file_unit_size, Interleave = record.interleave, VolumeSequenceNumber = record.volume_sequence_number, - Timestamp = DecodeIsoDateTime(record.date), - XattrLength = record.xattr_len + Timestamp = DecodeIsoDateTime(record.date), XattrLength = record.xattr_len }; if(record.size != 0) - entry.Extents = new List<(uint extent, uint size)> {(record.extent, record.size)}; + entry.Extents = new List<(uint extent, uint size)> + { + (record.extent, record.size) + }; if(entry.Flags.HasFlag(FileFlags.Directory) && usePathTable) { entryOff += record.length; + continue; } @@ -365,16 +401,15 @@ namespace DiscImageChef.Filesystems.ISO9660 { Size = 0, Flags = record.flags ^ FileFlags.Associated, - FileUnitSize = 0, - Interleave = 0, - VolumeSequenceNumber = record.volume_sequence_number, - Filename = entry.Filename, - Timestamp = DecodeIsoDateTime(record.date), - XattrLength = 0 + FileUnitSize = 0, Interleave = 0, + VolumeSequenceNumber = record.volume_sequence_number, Filename = entry.Filename, + Timestamp = DecodeIsoDateTime(record.date), XattrLength = 0 }; - if(hasResourceFork) entries[entry.Filename].ResourceFork = entry; - else entries[entry.Filename].AssociatedFile = entry; + if(hasResourceFork) + entries[entry.Filename].ResourceFork = entry; + else + entries[entry.Filename].AssociatedFile = entry; } } else @@ -398,7 +433,8 @@ namespace DiscImageChef.Filesystems.ISO9660 entries[entry.Filename].Extents.Add(entry.Extents[0]); } - else entries[entry.Filename] = entry; + else + entries[entry.Filename] = entry; } entryOff += record.length; @@ -407,7 +443,8 @@ namespace DiscImageChef.Filesystems.ISO9660 entryOff = 0; } - if(useTransTbl) DecodeTransTable(entries); + if(useTransTbl) + DecodeTransTable(entries); // Relocated directories should be shown in correct place when using Rock Ridge namespace return @namespace == Namespace.Rrip @@ -422,16 +459,19 @@ namespace DiscImageChef.Filesystems.ISO9660 (e.Value.Filename.ToLower(CultureInfo.CurrentUICulture) == "trans.tbl" || e.Value.Filename.ToLower(CultureInfo.CurrentUICulture) == "trans.tbl;1")); - if(transTblEntry.Value == null) return; + if(transTblEntry.Value == null) + return; // The probability of a TRANS.TBL to be bigger than 2GiB is nil uint transTblSectors = (uint)transTblEntry.Value.Size / 2048; - if(transTblEntry.Value.Size % 2048 > 0) transTblSectors++; + + if(transTblEntry.Value.Size % 2048 > 0) + transTblSectors++; byte[] transTbl = ReadSectors(transTblEntry.Value.Extents[0].extent, transTblSectors); - MemoryStream mr = new MemoryStream(transTbl, 0, (int)transTblEntry.Value.Size, false); - StreamReader sr = new StreamReader(mr, Encoding); + var mr = new MemoryStream(transTbl, 0, (int)transTblEntry.Value.Size, false); + var sr = new StreamReader(mr, Encoding); string line = sr.ReadLine(); @@ -473,7 +513,7 @@ namespace DiscImageChef.Filesystems.ISO9660 entries.Remove(transTblEntry.Key); } - void DecodeSystemArea(byte[] data, int start, int end, ref DecodedDirectoryEntry entry, + void DecodeSystemArea(byte[] data, int start, int end, ref DecodedDirectoryEntry entry, out bool hasResourceFork) { int systemAreaOff = start; @@ -485,24 +525,27 @@ namespace DiscImageChef.Filesystems.ISO9660 { ushort systemAreaSignature = BigEndianBitConverter.ToUInt16(data, systemAreaOff); - if(BigEndianBitConverter.ToUInt16(data, systemAreaOff + 6) == XA_MAGIC) systemAreaSignature = XA_MAGIC; + if(BigEndianBitConverter.ToUInt16(data, systemAreaOff + 6) == XA_MAGIC) + systemAreaSignature = XA_MAGIC; switch(systemAreaSignature) { case APPLE_MAGIC: - byte appleLength = data[systemAreaOff + 2]; - AppleId appleId = (AppleId)data[systemAreaOff + 3]; + byte appleLength = data[systemAreaOff + 2]; + var appleId = (AppleId)data[systemAreaOff + 3]; // Old AAIP - if(appleId == AppleId.ProDOS && appleLength != 7) goto case AAIP_MAGIC; + if(appleId == AppleId.ProDOS && + appleLength != 7) + goto case AAIP_MAGIC; switch(appleId) { case AppleId.ProDOS: AppleProDOSSystemUse appleProDosSystemUse = Marshal.ByteArrayToStructureLittleEndian(data, systemAreaOff, - Marshal - .SizeOf< + Marshal. + SizeOf< AppleProDOSSystemUse >()); @@ -513,8 +556,8 @@ namespace DiscImageChef.Filesystems.ISO9660 case AppleId.HFS: AppleHFSSystemUse appleHfsSystemUse = Marshal.ByteArrayToStructureBigEndian(data, systemAreaOff, - Marshal - .SizeOf< + Marshal. + SizeOf< AppleHFSSystemUse >()); @@ -529,9 +572,10 @@ namespace DiscImageChef.Filesystems.ISO9660 } systemAreaOff += appleLength; + break; case APPLE_MAGIC_OLD: - AppleOldId appleOldId = (AppleOldId)data[systemAreaOff + 2]; + var appleOldId = (AppleOldId)data[systemAreaOff + 2]; switch(appleOldId) { @@ -539,22 +583,24 @@ namespace DiscImageChef.Filesystems.ISO9660 AppleProDOSOldSystemUse appleProDosOldSystemUse = Marshal.ByteArrayToStructureLittleEndian(data, systemAreaOff, - Marshal - .SizeOf< + Marshal. + SizeOf< AppleProDOSOldSystemUse >()); + entry.AppleProDosType = appleProDosOldSystemUse.aux_type; entry.AppleDosType = appleProDosOldSystemUse.type; systemAreaOff += Marshal.SizeOf(); + break; case AppleOldId.TypeCreator: case AppleOldId.TypeCreatorBundle: AppleHFSTypeCreatorSystemUse appleHfsTypeCreatorSystemUse = Marshal.ByteArrayToStructureBigEndian(data, systemAreaOff, - Marshal - .SizeOf< + Marshal. + SizeOf< AppleHFSTypeCreatorSystemUse >()); @@ -565,13 +611,14 @@ namespace DiscImageChef.Filesystems.ISO9660 entry.FinderInfo.fdType = appleHfsTypeCreatorSystemUse.type; systemAreaOff += Marshal.SizeOf(); + break; case AppleOldId.TypeCreatorIcon: case AppleOldId.TypeCreatorIconBundle: AppleHFSIconSystemUse appleHfsIconSystemUse = Marshal.ByteArrayToStructureBigEndian(data, systemAreaOff, - Marshal - .SizeOf< + Marshal. + SizeOf< AppleHFSIconSystemUse >()); @@ -583,12 +630,13 @@ namespace DiscImageChef.Filesystems.ISO9660 entry.AppleIcon = appleHfsIconSystemUse.icon; systemAreaOff += Marshal.SizeOf(); + break; case AppleOldId.HFS: AppleHFSOldSystemUse appleHfsSystemUse = Marshal.ByteArrayToStructureBigEndian(data, systemAreaOff, - Marshal - .SizeOf< + Marshal. + SizeOf< AppleHFSOldSystemUse >()); @@ -600,10 +648,12 @@ namespace DiscImageChef.Filesystems.ISO9660 entry.FinderInfo.fdType = appleHfsSystemUse.type; systemAreaOff += Marshal.SizeOf(); + break; default: // Cannot continue as we don't know this structure size systemAreaOff = end; + break; } @@ -613,7 +663,9 @@ namespace DiscImageChef.Filesystems.ISO9660 Marshal.SizeOf()); systemAreaOff += Marshal.SizeOf(); + break; + // All of these follow the SUSP indication of 2 bytes for signature 1 byte for length case AAIP_MAGIC: case AMIGA_MAGIC: @@ -629,20 +681,21 @@ namespace DiscImageChef.Filesystems.ISO9660 Marshal.ByteArrayToStructureBigEndian(data, systemAreaOff + Marshal.SizeOf(), - Marshal - .SizeOf()); + Marshal. + SizeOf()); protectionLength = Marshal.SizeOf(); } if(amiga.flags.HasFlag(AmigaFlags.Comment)) { - if(entry.AmigaComment is null) entry.AmigaComment = new byte[0]; + if(entry.AmigaComment is null) + entry.AmigaComment = new byte[0]; - byte[] newComment = new byte[entry.AmigaComment.Length + - data - [systemAreaOff + Marshal.SizeOf() + protectionLength] - - 1]; + byte[] newComment = new byte[(entry.AmigaComment.Length + + data + [systemAreaOff + Marshal.SizeOf() + protectionLength] + ) - 1]; Array.Copy(entry.AmigaComment, 0, newComment, 0, entry.AmigaComment.Length); @@ -654,7 +707,9 @@ namespace DiscImageChef.Filesystems.ISO9660 } systemAreaOff += amiga.length; + break; + // This merely indicates the existence of RRIP extensions, we don't need it case RRIP_MAGIC: byte rripLength = data[systemAreaOff + 2]; @@ -667,28 +722,31 @@ namespace DiscImageChef.Filesystems.ISO9660 if(pxLength == 36) entry.PosixAttributesOld = Marshal.ByteArrayToStructureLittleEndian(data, systemAreaOff, - Marshal - .SizeOf< + Marshal. + SizeOf< PosixAttributesOld >()); else if(pxLength >= 44) entry.PosixAttributes = Marshal.ByteArrayToStructureLittleEndian(data, systemAreaOff, - Marshal - .SizeOf()); systemAreaOff += pxLength; + break; case RRIP_POSIX_DEV_NO: byte pnLength = data[systemAreaOff + 2]; entry.PosixDeviceNumber = Marshal.ByteArrayToStructureLittleEndian(data, systemAreaOff, - Marshal - .SizeOf()); + systemAreaOff += pnLength; + break; case RRIP_SYMLINK: byte slLength = data[systemAreaOff + 2]; @@ -700,20 +758,28 @@ namespace DiscImageChef.Filesystems.ISO9660 SymbolicLinkComponent slc = Marshal.ByteArrayToStructureLittleEndian(data, systemAreaOff + - Marshal - .SizeOf(), - Marshal - .SizeOf< + Marshal. + SizeOf(), + Marshal. + SizeOf< SymbolicLinkComponent >()); - if(!continueSymlink || entry.SymbolicLink is null) entry.SymbolicLink = ""; + if(!continueSymlink || + entry.SymbolicLink is null) + entry.SymbolicLink = ""; - if(slc.flags.HasFlag(SymlinkComponentFlags.Root)) entry.SymbolicLink = "/"; - if(slc.flags.HasFlag(SymlinkComponentFlags.Current)) entry.SymbolicLink += "."; - if(slc.flags.HasFlag(SymlinkComponentFlags.Parent)) entry.SymbolicLink += ".."; + if(slc.flags.HasFlag(SymlinkComponentFlags.Root)) + entry.SymbolicLink = "/"; - if(!continueSymlinkComponent && !slc.flags.HasFlag(SymlinkComponentFlags.Root)) + if(slc.flags.HasFlag(SymlinkComponentFlags.Current)) + entry.SymbolicLink += "."; + + if(slc.flags.HasFlag(SymlinkComponentFlags.Parent)) + entry.SymbolicLink += ".."; + + if(!continueSymlinkComponent && + !slc.flags.HasFlag(SymlinkComponentFlags.Root)) entry.SymbolicLink += "/"; entry.SymbolicLink += slc.flags.HasFlag(SymlinkComponentFlags.Networkname) @@ -721,10 +787,10 @@ namespace DiscImageChef.Filesystems.ISO9660 : joliet ? Encoding.BigEndianUnicode.GetString(data, systemAreaOff + - Marshal - .SizeOf() + - Marshal - .SizeOf< + Marshal. + SizeOf() + + Marshal. + SizeOf< SymbolicLinkComponent >(), slc.length) : Encoding.GetString(data, @@ -737,6 +803,7 @@ namespace DiscImageChef.Filesystems.ISO9660 continueSymlinkComponent = slc.flags.HasFlag(SymlinkComponentFlags.Continue); systemAreaOff += slLength; + break; case RRIP_NAME: byte nmLength = data[systemAreaOff + 2]; @@ -744,6 +811,7 @@ namespace DiscImageChef.Filesystems.ISO9660 if(@namespace != Namespace.Rrip) { systemAreaOff += nmLength; + break; } @@ -752,9 +820,9 @@ namespace DiscImageChef.Filesystems.ISO9660 Marshal.SizeOf()); byte[] nm; + if(alternateName.flags.HasFlag(AlternateNameFlags.Networkname)) - nm = joliet - ? Encoding.BigEndianUnicode.GetBytes(Environment.MachineName) + nm = joliet ? Encoding.BigEndianUnicode.GetBytes(Environment.MachineName) : Encoding.GetBytes(Environment.MachineName); else { @@ -763,25 +831,25 @@ namespace DiscImageChef.Filesystems.ISO9660 Array.Copy(data, systemAreaOff + Marshal.SizeOf(), nm, 0, nm.Length); } - if(entry.RockRidgeAlternateName is null) entry.RockRidgeAlternateName = new byte[0]; + if(entry.RockRidgeAlternateName is null) + entry.RockRidgeAlternateName = new byte[0]; byte[] newNm = new byte[entry.RockRidgeAlternateName.Length + nm.Length]; - Array.Copy(entry.RockRidgeAlternateName, 0, newNm, 0, - entry.RockRidgeAlternateName.Length); - Array.Copy(nm, 0, newNm, entry.RockRidgeAlternateName.Length, - nm.Length); + Array.Copy(entry.RockRidgeAlternateName, 0, newNm, 0, entry.RockRidgeAlternateName.Length); + Array.Copy(nm, 0, newNm, entry.RockRidgeAlternateName.Length, nm.Length); entry.RockRidgeAlternateName = newNm; if(!alternateName.flags.HasFlag(AlternateNameFlags.Continue)) { - entry.Filename = joliet - ? Encoding.BigEndianUnicode.GetString(entry.RockRidgeAlternateName) + entry.Filename = joliet ? Encoding.BigEndianUnicode.GetString(entry.RockRidgeAlternateName) : Encoding.GetString(entry.RockRidgeAlternateName); + entry.RockRidgeAlternateName = null; } systemAreaOff += nmLength; + break; case RRIP_CHILDLINK: byte clLength = data[systemAreaOff + 2]; @@ -790,6 +858,7 @@ namespace DiscImageChef.Filesystems.ISO9660 if(@namespace != Namespace.Rrip || usePathTable) { systemAreaOff += clLength; + break; } @@ -798,13 +867,17 @@ namespace DiscImageChef.Filesystems.ISO9660 Marshal.SizeOf()); byte[] childSector = ReadSectors(cl.child_dir_lba, 1); + DirectoryRecord childRecord = Marshal.ByteArrayToStructureLittleEndian(childSector); // As per RRIP 4.1.5.1, we leave name as in previous entry, substitute location with the one in // the CL, and replace all other fields with the ones found in the first entry of the child - entry.Extents = - new List<(uint extent, uint size)> {(cl.child_dir_lba, childRecord.size)}; + entry.Extents = new List<(uint extent, uint size)> + { + (cl.child_dir_lba, childRecord.size) + }; + entry.Size = childRecord.size; entry.Flags = childRecord.flags; entry.FileUnitSize = childRecord.file_unit_size; @@ -888,6 +961,7 @@ namespace DiscImageChef.Filesystems.ISO9660 } systemAreaOff += tfLength; + break; case RRIP_SPARSE: // TODO @@ -900,13 +974,15 @@ namespace DiscImageChef.Filesystems.ISO9660 ContinuationArea ca = Marshal.ByteArrayToStructureLittleEndian(data, systemAreaOff, - Marshal - .SizeOf()); + Marshal. + SizeOf()); uint caOffSector = ca.offset / 2048; uint caOff = ca.offset % 2048; uint caLenInSectors = ca.ca_length / 2048; - if((ca.ca_length + caOff) % 2048 > 0) caLenInSectors++; + + if((ca.ca_length + caOff) % 2048 > 0) + caLenInSectors++; byte[] caData = ReadSectors(ca.block + caOffSector, caLenInSectors); @@ -914,6 +990,7 @@ namespace DiscImageChef.Filesystems.ISO9660 out hasResourceFork); systemAreaOff += ceLength; + break; case SUSP_PADDING: // Just padding, skip @@ -954,6 +1031,7 @@ namespace DiscImageChef.Filesystems.ISO9660 default: // Cannot continue as we don't know this structure size systemAreaOff = end; + break; } } @@ -964,14 +1042,19 @@ namespace DiscImageChef.Filesystems.ISO9660 IEnumerable tableEntries; List pathTableList = new List(pathTable); - if(path == "" || path == "/") tableEntries = pathTable.Where(p => p.Parent == 1 && p != pathTable[0]); + if(path == "" || + path == "/") + tableEntries = pathTable.Where(p => p.Parent == 1 && p != pathTable[0]); else { string cutPath = path.StartsWith("/", StringComparison.Ordinal) ? path.Substring(1).ToLower(CultureInfo.CurrentUICulture) : path.ToLower(CultureInfo.CurrentUICulture); - string[] pieces = cutPath.Split(new[] {'/'}, StringSplitOptions.RemoveEmptyEntries); + string[] pieces = cutPath.Split(new[] + { + '/' + }, StringSplitOptions.RemoveEmptyEntries); int currentParent = 1; int currentPiece = 0; @@ -979,11 +1062,12 @@ namespace DiscImageChef.Filesystems.ISO9660 while(currentPiece < pieces.Length) { PathTableEntryInternal currentEntry = pathTable.FirstOrDefault(p => p.Parent == currentParent && - p.Name.ToLower(CultureInfo - .CurrentUICulture) == + p.Name.ToLower(CultureInfo. + CurrentUICulture) == pieces[currentPiece]); - if(currentEntry is null) break; + if(currentEntry is null) + break; currentPiece++; currentParent = pathTableList.IndexOf(currentEntry) + 1; @@ -999,37 +1083,43 @@ namespace DiscImageChef.Filesystems.ISO9660 { PathTableEntryInternal[] tableEntries = GetPathTableEntries(path); List entries = new List(); + foreach(PathTableEntryInternal tEntry in tableEntries) { byte[] sector = ReadSectors(tEntry.Extent, 1); + CdiDirectoryRecord record = Marshal.ByteArrayToStructureBigEndian(sector, tEntry.XattrLength, CdiDirectoryRecordSize); - if(record.length == 0) break; + if(record.length == 0) + break; - DecodedDirectoryEntry entry = new DecodedDirectoryEntry + var entry = new DecodedDirectoryEntry { - Size = record.size, - Filename = tEntry.Name, + Size = record.size, Filename = tEntry.Name, VolumeSequenceNumber = record.volume_sequence_number, - Timestamp = DecodeHighSierraDateTime(record.date), - XattrLength = tEntry.XattrLength + Timestamp = DecodeHighSierraDateTime(record.date), XattrLength = tEntry.XattrLength }; if(record.size != 0) - entry.Extents = new List<(uint extent, uint size)> {(record.start_lbn, record.size)}; + entry.Extents = new List<(uint extent, uint size)> + { + (record.start_lbn, record.size) + }; - if(record.flags.HasFlag(CdiFileFlags.Hidden)) entry.Flags |= FileFlags.Hidden; + if(record.flags.HasFlag(CdiFileFlags.Hidden)) + entry.Flags |= FileFlags.Hidden; int systemAreaStart = record.name_len + CdiDirectoryRecordSize; - if(systemAreaStart % 2 != 0) systemAreaStart++; + if(systemAreaStart % 2 != 0) + systemAreaStart++; entry.CdiSystemArea = Marshal.ByteArrayToStructureBigEndian(sector, systemAreaStart, CdiSystemAreaSize); - if(((CdiAttributes)entry.CdiSystemArea.Value.attributes).HasFlag(CdiAttributes.Directory)) + if(entry.CdiSystemArea.Value.attributes.HasFlag(CdiAttributes.Directory)) entry.Flags |= FileFlags.Directory; entries.Add(entry); @@ -1042,28 +1132,32 @@ namespace DiscImageChef.Filesystems.ISO9660 { PathTableEntryInternal[] tableEntries = GetPathTableEntries(path); List entries = new List(); + foreach(PathTableEntryInternal tEntry in tableEntries) { byte[] sector = ReadSectors(tEntry.Extent, 1); + DirectoryRecord record = Marshal.ByteArrayToStructureLittleEndian(sector, tEntry.XattrLength, DirectoryRecordSize); - if(record.length == 0) break; + if(record.length == 0) + break; - DecodedDirectoryEntry entry = new DecodedDirectoryEntry + var entry = new DecodedDirectoryEntry { - Size = record.size, - Flags = record.flags, + Size = record.size, Flags = record.flags, Filename = tEntry.Name, - FileUnitSize = record.file_unit_size, - Interleave = record.interleave, - VolumeSequenceNumber = record.volume_sequence_number, - Timestamp = DecodeIsoDateTime(record.date), + FileUnitSize = record.file_unit_size, Interleave = record.interleave, + VolumeSequenceNumber = record.volume_sequence_number, Timestamp = DecodeIsoDateTime(record.date), XattrLength = tEntry.XattrLength }; - if(record.size != 0) entry.Extents = new List<(uint extent, uint size)> {(record.extent, record.size)}; + if(record.size != 0) + entry.Extents = new List<(uint extent, uint size)> + { + (record.extent, record.size) + }; int systemAreaStart = record.name_len + DirectoryRecordSize; int systemAreaLength = record.length - record.name_len - DirectoryRecordSize; @@ -1086,25 +1180,28 @@ namespace DiscImageChef.Filesystems.ISO9660 { PathTableEntryInternal[] tableEntries = GetPathTableEntries(path); List entries = new List(); + foreach(PathTableEntryInternal tEntry in tableEntries) { byte[] sector = ReadSectors(tEntry.Extent, 1); + HighSierraDirectoryRecord record = Marshal.ByteArrayToStructureLittleEndian(sector, tEntry.XattrLength, HighSierraDirectoryRecordSize); - DecodedDirectoryEntry entry = new DecodedDirectoryEntry + var entry = new DecodedDirectoryEntry { - Size = record.size, - Flags = record.flags, - Filename = tEntry.Name, + Size = record.size, Flags = record.flags, Filename = tEntry.Name, Interleave = record.interleave, VolumeSequenceNumber = record.volume_sequence_number, - Timestamp = DecodeHighSierraDateTime(record.date), - XattrLength = tEntry.XattrLength + Timestamp = DecodeHighSierraDateTime(record.date), XattrLength = tEntry.XattrLength }; - if(record.size != 0) entry.Extents = new List<(uint extent, uint size)> {(record.extent, record.size)}; + if(record.size != 0) + entry.Extents = new List<(uint extent, uint size)> + { + (record.extent, record.size) + }; entries.Add(entry); } diff --git a/DiscImageChef.Filesystems/ISO9660/File.cs b/DiscImageChef.Filesystems/ISO9660/File.cs index ab4619f39..4cb009000 100644 --- a/DiscImageChef.Filesystems/ISO9660/File.cs +++ b/DiscImageChef.Filesystems/ISO9660/File.cs @@ -47,15 +47,22 @@ namespace DiscImageChef.Filesystems.ISO9660 public Errno MapBlock(string path, long fileBlock, out long deviceBlock) { deviceBlock = 0; - if(!mounted) return Errno.AccessDenied; + + if(!mounted) + return Errno.AccessDenied; Errno err = GetFileEntry(path, out DecodedDirectoryEntry entry); - if(err != Errno.NoError) return err; - if(entry.Flags.HasFlag(FileFlags.Directory) && !debug) return Errno.IsDirectory; + if(err != Errno.NoError) + return err; + + if(entry.Flags.HasFlag(FileFlags.Directory) && + !debug) + return Errno.IsDirectory; // TODO: Multi-extents - if(entry.Extents.Count > 1) return Errno.NotImplemented; + if(entry.Extents.Count > 1) + return Errno.NotImplemented; deviceBlock = entry.Extents[0].extent + fileBlock; @@ -65,11 +72,14 @@ namespace DiscImageChef.Filesystems.ISO9660 public Errno GetAttributes(string path, out FileAttributes attributes) { attributes = new FileAttributes(); - if(!mounted) return Errno.AccessDenied; + + if(!mounted) + return Errno.AccessDenied; Errno err = Stat(path, out FileEntryInfo stat); - if(err != Errno.NoError) return err; + if(err != Errno.NoError) + return err; attributes = stat.Attributes; @@ -80,45 +90,58 @@ namespace DiscImageChef.Filesystems.ISO9660 public Errno Read(string path, long offset, long size, ref byte[] buf) { buf = null; - if(!mounted) return Errno.AccessDenied; + + if(!mounted) + return Errno.AccessDenied; Errno err = GetFileEntry(path, out DecodedDirectoryEntry entry); - if(err != Errno.NoError) return err; - if(entry.Flags.HasFlag(FileFlags.Directory) && !debug) return Errno.IsDirectory; + if(err != Errno.NoError) + return err; - if(entry.Extents is null) return Errno.InvalidArgument; + if(entry.Flags.HasFlag(FileFlags.Directory) && + !debug) + return Errno.IsDirectory; + + if(entry.Extents is null) + return Errno.InvalidArgument; if(entry.Size == 0) { buf = new byte[0]; + return Errno.NoError; } - if(offset >= (long)entry.Size) return Errno.InvalidArgument; + if(offset >= (long)entry.Size) + return Errno.InvalidArgument; - if(size + offset >= (long)entry.Size) size = (long)entry.Size - offset; + if(size + offset >= (long)entry.Size) + size = (long)entry.Size - offset; offset += entry.XattrLength; long firstSector = offset / 2048; long offsetInSector = offset % 2048; long sizeInSectors = (size + offsetInSector) / 2048; - if((size + offsetInSector) % 2048 > 0) sizeInSectors++; + + if((size + offsetInSector) % 2048 > 0) + sizeInSectors++; if(entry.Extents.Count == 1) { // No need to check mode, if we know it is CD-DA byte[] buffer = entry.CdiSystemArea != null && - ((CdiAttributes)entry.CdiSystemArea.Value.attributes).HasFlag(CdiAttributes.DigitalAudio) + entry.CdiSystemArea.Value.attributes.HasFlag(CdiAttributes.DigitalAudio) ? image.ReadSectors((ulong)(entry.Extents[0].extent + firstSector), (uint)sizeInSectors) : ReadSectors((ulong)(entry.Extents[0].extent + firstSector), (uint)sizeInSectors); buf = new byte[size]; Array.Copy(buffer, offsetInSector, buf, 0, size); } - else buf = ReadWithExtents(offset, size, entry.Extents); + else + buf = ReadWithExtents(offset, size, entry.Extents); return Errno.NoError; } @@ -126,54 +149,84 @@ namespace DiscImageChef.Filesystems.ISO9660 public Errno Stat(string path, out FileEntryInfo stat) { stat = null; - if(!mounted) return Errno.AccessDenied; + + if(!mounted) + return Errno.AccessDenied; Errno err = GetFileEntry(path, out DecodedDirectoryEntry entry); - if(err != Errno.NoError) return err; + + if(err != Errno.NoError) + return err; stat = new FileEntryInfo { - Attributes = new FileAttributes(), - Blocks = (long)(entry.Size / 2048), // TODO: XA - BlockSize = 2048, - Length = (long)entry.Size, - Inode = entry.Extents?[0].extent ?? 0, - Links = 1, + Attributes = new FileAttributes(), Blocks = (long)(entry.Size / 2048), // TODO: XA + BlockSize = 2048, Length = (long)entry.Size, + Inode = entry.Extents?[0].extent ?? 0, Links = 1, LastWriteTimeUtc = entry.Timestamp }; - if(entry.Size % 2048 > 0) stat.Blocks++; + if(entry.Size % 2048 > 0) + stat.Blocks++; - if(entry.Flags.HasFlag(FileFlags.Directory)) stat.Attributes |= FileAttributes.Directory; - if(entry.Flags.HasFlag(FileFlags.Hidden)) stat.Attributes |= FileAttributes.Hidden; + if(entry.Flags.HasFlag(FileFlags.Directory)) + stat.Attributes |= FileAttributes.Directory; + + if(entry.Flags.HasFlag(FileFlags.Hidden)) + stat.Attributes |= FileAttributes.Hidden; if(entry.FinderInfo != null) { - if(entry.FinderInfo.fdFlags.HasFlag(FinderFlags.kIsAlias)) stat.Attributes |= FileAttributes.Alias; - if(entry.FinderInfo.fdFlags.HasFlag(FinderFlags.kIsInvisible)) stat.Attributes |= FileAttributes.Hidden; + if(entry.FinderInfo.fdFlags.HasFlag(FinderFlags.kIsAlias)) + stat.Attributes |= FileAttributes.Alias; + + if(entry.FinderInfo.fdFlags.HasFlag(FinderFlags.kIsInvisible)) + stat.Attributes |= FileAttributes.Hidden; + if(entry.FinderInfo.fdFlags.HasFlag(FinderFlags.kHasBeenInited)) stat.Attributes |= FileAttributes.HasBeenInited; + if(entry.FinderInfo.fdFlags.HasFlag(FinderFlags.kHasCustomIcon)) stat.Attributes |= FileAttributes.HasCustomIcon; + if(entry.FinderInfo.fdFlags.HasFlag(FinderFlags.kHasNoINITs)) stat.Attributes |= FileAttributes.HasNoINITs; - if(entry.FinderInfo.fdFlags.HasFlag(FinderFlags.kIsOnDesk)) stat.Attributes |= FileAttributes.IsOnDesk; - if(entry.FinderInfo.fdFlags.HasFlag(FinderFlags.kIsShared)) stat.Attributes |= FileAttributes.Shared; + + if(entry.FinderInfo.fdFlags.HasFlag(FinderFlags.kIsOnDesk)) + stat.Attributes |= FileAttributes.IsOnDesk; + + if(entry.FinderInfo.fdFlags.HasFlag(FinderFlags.kIsShared)) + stat.Attributes |= FileAttributes.Shared; + if(entry.FinderInfo.fdFlags.HasFlag(FinderFlags.kIsStationery)) stat.Attributes |= FileAttributes.Stationery; - if(entry.FinderInfo.fdFlags.HasFlag(FinderFlags.kHasBundle)) stat.Attributes |= FileAttributes.Bundle; + + if(entry.FinderInfo.fdFlags.HasFlag(FinderFlags.kHasBundle)) + stat.Attributes |= FileAttributes.Bundle; } - if(entry.AppleIcon != null) stat.Attributes |= FileAttributes.HasCustomIcon; + if(entry.AppleIcon != null) + stat.Attributes |= FileAttributes.HasCustomIcon; if(entry.XA != null) { - if(entry.XA.Value.attributes.HasFlag(XaAttributes.GroupExecute)) stat.Mode |= 8; - if(entry.XA.Value.attributes.HasFlag(XaAttributes.GroupRead)) stat.Mode |= 32; - if(entry.XA.Value.attributes.HasFlag(XaAttributes.OwnerExecute)) stat.Mode |= 64; - if(entry.XA.Value.attributes.HasFlag(XaAttributes.OwnerRead)) stat.Mode |= 256; - if(entry.XA.Value.attributes.HasFlag(XaAttributes.SystemExecute)) stat.Mode |= 1; - if(entry.XA.Value.attributes.HasFlag(XaAttributes.SystemRead)) stat.Mode |= 4; + if(entry.XA.Value.attributes.HasFlag(XaAttributes.GroupExecute)) + stat.Mode |= 8; + + if(entry.XA.Value.attributes.HasFlag(XaAttributes.GroupRead)) + stat.Mode |= 32; + + if(entry.XA.Value.attributes.HasFlag(XaAttributes.OwnerExecute)) + stat.Mode |= 64; + + if(entry.XA.Value.attributes.HasFlag(XaAttributes.OwnerRead)) + stat.Mode |= 256; + + if(entry.XA.Value.attributes.HasFlag(XaAttributes.SystemExecute)) + stat.Mode |= 1; + + if(entry.XA.Value.attributes.HasFlag(XaAttributes.SystemRead)) + stat.Mode |= 4; stat.UID = entry.XA.Value.user; stat.GID = entry.XA.Value.group; @@ -183,15 +236,22 @@ namespace DiscImageChef.Filesystems.ISO9660 if(entry.PosixAttributes != null) { stat.Mode = (uint?)entry.PosixAttributes.Value.st_mode & 0x0FFF; + if(entry.PosixAttributes.Value.st_mode.HasFlag(PosixMode.Block)) stat.Attributes |= FileAttributes.BlockDevice; + if(entry.PosixAttributes.Value.st_mode.HasFlag(PosixMode.Character)) stat.Attributes |= FileAttributes.CharDevice; - if(entry.PosixAttributes.Value.st_mode.HasFlag(PosixMode.Pipe)) stat.Attributes |= FileAttributes.Pipe; + + if(entry.PosixAttributes.Value.st_mode.HasFlag(PosixMode.Pipe)) + stat.Attributes |= FileAttributes.Pipe; + if(entry.PosixAttributes.Value.st_mode.HasFlag(PosixMode.Socket)) stat.Attributes |= FileAttributes.Socket; + if(entry.PosixAttributes.Value.st_mode.HasFlag(PosixMode.Symlink)) stat.Attributes |= FileAttributes.Symlink; + stat.Links = entry.PosixAttributes.Value.st_nlink; stat.UID = entry.PosixAttributes.Value.st_uid; stat.GID = entry.PosixAttributes.Value.st_gid; @@ -200,16 +260,22 @@ namespace DiscImageChef.Filesystems.ISO9660 else if(entry.PosixAttributesOld != null) { stat.Mode = (uint?)entry.PosixAttributesOld.Value.st_mode & 0x0FFF; + if(entry.PosixAttributesOld.Value.st_mode.HasFlag(PosixMode.Block)) stat.Attributes |= FileAttributes.BlockDevice; + if(entry.PosixAttributesOld.Value.st_mode.HasFlag(PosixMode.Character)) stat.Attributes |= FileAttributes.CharDevice; + if(entry.PosixAttributesOld.Value.st_mode.HasFlag(PosixMode.Pipe)) stat.Attributes |= FileAttributes.Pipe; + if(entry.PosixAttributesOld.Value.st_mode.HasFlag(PosixMode.Socket)) stat.Attributes |= FileAttributes.Socket; + if(entry.PosixAttributesOld.Value.st_mode.HasFlag(PosixMode.Symlink)) stat.Attributes |= FileAttributes.Symlink; + stat.Links = entry.PosixAttributesOld.Value.st_nlink; stat.UID = entry.PosixAttributesOld.Value.st_uid; stat.GID = entry.PosixAttributesOld.Value.st_gid; @@ -217,15 +283,33 @@ namespace DiscImageChef.Filesystems.ISO9660 if(entry.AmigaProtection != null) { - if(entry.AmigaProtection.Value.Multiuser.HasFlag(AmigaMultiuser.GroupExec)) stat.Mode |= 8; - if(entry.AmigaProtection.Value.Multiuser.HasFlag(AmigaMultiuser.GroupRead)) stat.Mode |= 32; - if(entry.AmigaProtection.Value.Multiuser.HasFlag(AmigaMultiuser.GroupWrite)) stat.Mode |= 16; - if(entry.AmigaProtection.Value.Multiuser.HasFlag(AmigaMultiuser.OtherExec)) stat.Mode |= 1; - if(entry.AmigaProtection.Value.Multiuser.HasFlag(AmigaMultiuser.OtherRead)) stat.Mode |= 4; - if(entry.AmigaProtection.Value.Multiuser.HasFlag(AmigaMultiuser.OtherWrite)) stat.Mode |= 2; - if(entry.AmigaProtection.Value.Protection.HasFlag(AmigaAttributes.OwnerExec)) stat.Mode |= 64; - if(entry.AmigaProtection.Value.Protection.HasFlag(AmigaAttributes.OwnerRead)) stat.Mode |= 256; - if(entry.AmigaProtection.Value.Protection.HasFlag(AmigaAttributes.OwnerWrite)) stat.Mode |= 128; + if(entry.AmigaProtection.Value.Multiuser.HasFlag(AmigaMultiuser.GroupExec)) + stat.Mode |= 8; + + if(entry.AmigaProtection.Value.Multiuser.HasFlag(AmigaMultiuser.GroupRead)) + stat.Mode |= 32; + + if(entry.AmigaProtection.Value.Multiuser.HasFlag(AmigaMultiuser.GroupWrite)) + stat.Mode |= 16; + + if(entry.AmigaProtection.Value.Multiuser.HasFlag(AmigaMultiuser.OtherExec)) + stat.Mode |= 1; + + if(entry.AmigaProtection.Value.Multiuser.HasFlag(AmigaMultiuser.OtherRead)) + stat.Mode |= 4; + + if(entry.AmigaProtection.Value.Multiuser.HasFlag(AmigaMultiuser.OtherWrite)) + stat.Mode |= 2; + + if(entry.AmigaProtection.Value.Protection.HasFlag(AmigaAttributes.OwnerExec)) + stat.Mode |= 64; + + if(entry.AmigaProtection.Value.Protection.HasFlag(AmigaAttributes.OwnerRead)) + stat.Mode |= 256; + + if(entry.AmigaProtection.Value.Protection.HasFlag(AmigaAttributes.OwnerWrite)) + stat.Mode |= 128; + if(entry.AmigaProtection.Value.Protection.HasFlag(AmigaAttributes.Archive)) stat.Attributes |= FileAttributes.Archive; } @@ -234,39 +318,54 @@ namespace DiscImageChef.Filesystems.ISO9660 stat.DeviceNo = (entry.PosixDeviceNumber.Value.dev_t_high << 32) + entry.PosixDeviceNumber.Value.dev_t_low; - if(entry.RripModify != null) stat.LastWriteTimeUtc = DecodeIsoDateTime(entry.RripModify); + if(entry.RripModify != null) + stat.LastWriteTimeUtc = DecodeIsoDateTime(entry.RripModify); - if(entry.RripAccess != null) stat.AccessTimeUtc = DecodeIsoDateTime(entry.RripAccess); + if(entry.RripAccess != null) + stat.AccessTimeUtc = DecodeIsoDateTime(entry.RripAccess); if(entry.RripAttributeChange != null) stat.StatusChangeTimeUtc = DecodeIsoDateTime(entry.RripAttributeChange); - if(entry.RripBackup != null) stat.BackupTimeUtc = DecodeIsoDateTime(entry.RripBackup); + if(entry.RripBackup != null) + stat.BackupTimeUtc = DecodeIsoDateTime(entry.RripBackup); - if(entry.SymbolicLink != null) stat.Attributes |= FileAttributes.Symlink; + if(entry.SymbolicLink != null) + stat.Attributes |= FileAttributes.Symlink; - if(entry.XattrLength == 0 || cdi || highSierra) return Errno.NoError; + if(entry.XattrLength == 0 || + cdi || + highSierra) + return Errno.NoError; if(entry.CdiSystemArea != null) { stat.UID = entry.CdiSystemArea.Value.owner; stat.GID = entry.CdiSystemArea.Value.group; - if(((CdiAttributes)entry.CdiSystemArea.Value.attributes).HasFlag(CdiAttributes.GroupExecute)) + + if(entry.CdiSystemArea.Value.attributes.HasFlag(CdiAttributes.GroupExecute)) stat.Mode |= 8; - if(((CdiAttributes)entry.CdiSystemArea.Value.attributes).HasFlag(CdiAttributes.GroupRead)) + + if(entry.CdiSystemArea.Value.attributes.HasFlag(CdiAttributes.GroupRead)) stat.Mode |= 32; - if(((CdiAttributes)entry.CdiSystemArea.Value.attributes).HasFlag(CdiAttributes.OtherExecute)) + + if(entry.CdiSystemArea.Value.attributes.HasFlag(CdiAttributes.OtherExecute)) stat.Mode |= 1; - if(((CdiAttributes)entry.CdiSystemArea.Value.attributes).HasFlag(CdiAttributes.OtherRead)) + + if(entry.CdiSystemArea.Value.attributes.HasFlag(CdiAttributes.OtherRead)) stat.Mode |= 4; - if(((CdiAttributes)entry.CdiSystemArea.Value.attributes).HasFlag(CdiAttributes.OwnerExecute)) + + if(entry.CdiSystemArea.Value.attributes.HasFlag(CdiAttributes.OwnerExecute)) stat.Mode |= 64; - if(((CdiAttributes)entry.CdiSystemArea.Value.attributes).HasFlag(CdiAttributes.OwnerRead)) + + if(entry.CdiSystemArea.Value.attributes.HasFlag(CdiAttributes.OwnerRead)) stat.Mode |= 256; } uint eaSizeInSectors = (uint)(entry.XattrLength / 2048); - if(entry.XattrLength % 2048 > 0) eaSizeInSectors++; + + if(entry.XattrLength % 2048 > 0) + eaSizeInSectors++; byte[] ea = ReadSectors(entry.Extents[0].extent, eaSizeInSectors); @@ -276,12 +375,24 @@ namespace DiscImageChef.Filesystems.ISO9660 stat.GID = ear.group; stat.Mode = 0; - if(ear.permissions.HasFlag(Permissions.GroupExecute)) stat.Mode |= 8; - if(ear.permissions.HasFlag(Permissions.GroupRead)) stat.Mode |= 32; - if(ear.permissions.HasFlag(Permissions.OwnerExecute)) stat.Mode |= 64; - if(ear.permissions.HasFlag(Permissions.OwnerRead)) stat.Mode |= 256; - if(ear.permissions.HasFlag(Permissions.OtherExecute)) stat.Mode |= 1; - if(ear.permissions.HasFlag(Permissions.OtherRead)) stat.Mode |= 4; + + if(ear.permissions.HasFlag(Permissions.GroupExecute)) + stat.Mode |= 8; + + if(ear.permissions.HasFlag(Permissions.GroupRead)) + stat.Mode |= 32; + + if(ear.permissions.HasFlag(Permissions.OwnerExecute)) + stat.Mode |= 64; + + if(ear.permissions.HasFlag(Permissions.OwnerRead)) + stat.Mode |= 256; + + if(ear.permissions.HasFlag(Permissions.OtherExecute)) + stat.Mode |= 1; + + if(ear.permissions.HasFlag(Permissions.OtherRead)) + stat.Mode |= 4; stat.CreationTimeUtc = DateHandlers.Iso9660ToDateTime(ear.creation_date); stat.LastWriteTimeUtc = DateHandlers.Iso9660ToDateTime(ear.modification_date); @@ -294,9 +405,12 @@ namespace DiscImageChef.Filesystems.ISO9660 dest = null; Errno err = GetFileEntry(path, out DecodedDirectoryEntry entry); - if(err != Errno.NoError) return err; - if(entry.SymbolicLink is null) return Errno.InvalidArgument; + if(err != Errno.NoError) + return err; + + if(entry.SymbolicLink is null) + return Errno.InvalidArgument; dest = entry.SymbolicLink; @@ -310,9 +424,14 @@ namespace DiscImageChef.Filesystems.ISO9660 string cutPath = path.StartsWith("/", StringComparison.Ordinal) ? path.Substring(1).ToLower(CultureInfo.CurrentUICulture) : path.ToLower(CultureInfo.CurrentUICulture); - string[] pieces = cutPath.Split(new[] {'/'}, StringSplitOptions.RemoveEmptyEntries); - if(pieces.Length == 0) return Errno.InvalidArgument; + string[] pieces = cutPath.Split(new[] + { + '/' + }, StringSplitOptions.RemoveEmptyEntries); + + if(pieces.Length == 0) + return Errno.InvalidArgument; string parentPath = string.Join("/", pieces, 0, pieces.Length - 1); @@ -320,44 +439,52 @@ namespace DiscImageChef.Filesystems.ISO9660 { Errno err = ReadDir(parentPath, out _); - if(err != Errno.NoError) return err; + if(err != Errno.NoError) + return err; } Dictionary parent; - if(pieces.Length == 1) parent = rootDirectoryCache; - else if(!directoryCache.TryGetValue(parentPath, out parent)) return Errno.InvalidArgument; + if(pieces.Length == 1) + parent = rootDirectoryCache; + else if(!directoryCache.TryGetValue(parentPath, out parent)) + return Errno.InvalidArgument; KeyValuePair dirent = parent.FirstOrDefault(t => t.Key.ToLower(CultureInfo.CurrentUICulture) == pieces[pieces.Length - 1]); if(string.IsNullOrEmpty(dirent.Key)) { - if(!joliet && !pieces[pieces.Length - 1].EndsWith(";1", StringComparison.Ordinal)) + if(!joliet && + !pieces[pieces.Length - 1].EndsWith(";1", StringComparison.Ordinal)) { dirent = parent.FirstOrDefault(t => t.Key.ToLower(CultureInfo.CurrentUICulture) == pieces[pieces.Length - 1] + ";1"); - if(string.IsNullOrEmpty(dirent.Key)) return Errno.NoSuchFile; + if(string.IsNullOrEmpty(dirent.Key)) + return Errno.NoSuchFile; } - else return Errno.NoSuchFile; + else + return Errno.NoSuchFile; } entry = dirent.Value; + return Errno.NoError; } // Cannot think how to make this faster, as we don't know the mode sector until it is read, but we have size in bytes byte[] ReadWithExtents(long offset, long size, List<(uint extent, uint size)> extents) { - MemoryStream ms = new MemoryStream(); - long currentFilePos = 0; + var ms = new MemoryStream(); + long currentFilePos = 0; for(int i = 0; i < extents.Count; i++) { if(offset - currentFilePos >= extents[i].size) { currentFilePos += extents[i].size; + continue; } @@ -373,25 +500,30 @@ namespace DiscImageChef.Filesystems.ISO9660 currentExtentSector++; leftExtentSize -= sector.Length; currentFilePos += sector.Length; + continue; } if(offset - currentFilePos > 0) ms.Write(sector, (int)(offset - currentFilePos), (int)(sector.Length - (offset - currentFilePos))); - else ms.Write(sector, 0, sector.Length); + else + ms.Write(sector, 0, sector.Length); currentExtentSector++; leftExtentSize -= sector.Length; currentFilePos += sector.Length; - if(ms.Length >= size) break; + if(ms.Length >= size) + break; } - if(ms.Length >= size) break; + if(ms.Length >= size) + break; } - if(ms.Length >= size) ms.SetLength(size); + if(ms.Length >= size) + ms.SetLength(size); return ms.ToArray(); } diff --git a/DiscImageChef.Filesystems/ISO9660/Structs/Apple.cs b/DiscImageChef.Filesystems/ISO9660/Structs/Apple.cs index 9b2438197..2e0568a42 100644 --- a/DiscImageChef.Filesystems/ISO9660/Structs/Apple.cs +++ b/DiscImageChef.Filesystems/ISO9660/Structs/Apple.cs @@ -57,7 +57,7 @@ namespace DiscImageChef.Filesystems.ISO9660 public readonly AppleId id; public readonly uint type; public readonly uint creator; - public readonly ushort finder_flags; + public readonly FinderFlags finder_flags; } // Little-endian diff --git a/DiscImageChef.Filesystems/ISO9660/Structs/CDi.cs b/DiscImageChef.Filesystems/ISO9660/Structs/CDi.cs index add71bd21..e59c879d4 100644 --- a/DiscImageChef.Filesystems/ISO9660/Structs/CDi.cs +++ b/DiscImageChef.Filesystems/ISO9660/Structs/CDi.cs @@ -40,7 +40,7 @@ namespace DiscImageChef.Filesystems.ISO9660 { static DecodedVolumeDescriptor DecodeVolumeDescriptor(FileStructureVolumeDescriptor pvd) { - DecodedVolumeDescriptor decodedVD = new DecodedVolumeDescriptor + var decodedVD = new DecodedVolumeDescriptor { SystemIdentifier = StringHandlers.CToString(pvd.system_id).TrimEnd(), VolumeIdentifier = StringHandlers.CToString(pvd.volume_id).TrimEnd(), @@ -50,12 +50,14 @@ namespace DiscImageChef.Filesystems.ISO9660 ApplicationIdentifier = StringHandlers.CToString(pvd.application_data).TrimEnd() }; - if(pvd.creation_date[0] == '0' || pvd.creation_date[0] == 0x00) decodedVD.CreationTime = DateTime.MinValue; + if(pvd.creation_date[0] == '0' || + pvd.creation_date[0] == 0x00) + decodedVD.CreationTime = DateTime.MinValue; else - decodedVD.CreationTime = - DateHandlers.HighSierraToDateTime(pvd.creation_date); + decodedVD.CreationTime = DateHandlers.HighSierraToDateTime(pvd.creation_date); - if(pvd.modification_date[0] == '0' || pvd.modification_date[0] == 0x00) + if(pvd.modification_date[0] == '0' || + pvd.modification_date[0] == 0x00) decodedVD.HasModificationTime = false; else { @@ -63,14 +65,18 @@ namespace DiscImageChef.Filesystems.ISO9660 decodedVD.ModificationTime = DateHandlers.HighSierraToDateTime(pvd.modification_date); } - if(pvd.expiration_date[0] == '0' || pvd.expiration_date[0] == 0x00) decodedVD.HasExpirationTime = false; + if(pvd.expiration_date[0] == '0' || + pvd.expiration_date[0] == 0x00) + decodedVD.HasExpirationTime = false; else { decodedVD.HasExpirationTime = true; decodedVD.ExpirationTime = DateHandlers.HighSierraToDateTime(pvd.expiration_date); } - if(pvd.effective_date[0] == '0' || pvd.effective_date[0] == 0x00) decodedVD.HasEffectiveTime = false; + if(pvd.effective_date[0] == '0' || + pvd.effective_date[0] == 0x00) + decodedVD.HasEffectiveTime = false; else { decodedVD.HasEffectiveTime = true; @@ -98,6 +104,7 @@ namespace DiscImageChef.Filesystems.ISO9660 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] public readonly byte[] reserved1; public readonly uint volume_space_size; + // Only used in SVDs [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public readonly byte[] escape_sequences; @@ -169,6 +176,7 @@ namespace DiscImageChef.Filesystems.ISO9660 public readonly ushort reserved4; public readonly ushort volume_sequence_number; public readonly byte name_len; + // Followed by name[name_len] and then CdiSystemArea until length arrives } @@ -176,12 +184,12 @@ namespace DiscImageChef.Filesystems.ISO9660 [StructLayout(LayoutKind.Sequential, Pack = 1)] struct CdiSystemArea { - public readonly ushort group; - public readonly ushort owner; - public readonly ushort attributes; - public readonly ushort reserved1; - public readonly byte file_no; - public readonly byte reserved2; + public readonly ushort group; + public readonly ushort owner; + public readonly CdiAttributes attributes; + public readonly ushort reserved1; + public readonly byte file_no; + public readonly byte reserved2; } } } \ No newline at end of file diff --git a/DiscImageChef.Helpers b/DiscImageChef.Helpers index 0f4820e12..035605d86 160000 --- a/DiscImageChef.Helpers +++ b/DiscImageChef.Helpers @@ -1 +1 @@ -Subproject commit 0f4820e123c5af1f8780f9bf53366ae36f7e60aa +Subproject commit 035605d86937ca36b399938bf4f8f8a271fa66bb