public static void ReadTOC(UnixFileDescriptor fd, out byte first, out byte last, out MMC.TrackDescriptor[] tracks, bool nativeAddress) { { // Read the TOC header var req = new TOCHeaderRequest(); if (NativeApi.SendIORequest(fd.Value, IOCTL.CDIOREADTOCHEADER, ref req) != 0) { throw new IOException("Failed to retrieve table of contents.", new UnixException()); } first = req.starting_track; last = req.ending_track; } { var trackcount = last - first + 2; // first->last plus lead-out var itemsize = Util.SizeOfStructure <MMC.TrackDescriptor>(); var req = new TOCEntriesRequest { address_format = CDAddressFormat.CD_LBA_FORMAT, starting_track = first, data_len = (ushort)(trackcount * itemsize), }; req.data = Marshal.AllocHGlobal(new IntPtr(req.data_len)); try { if (NativeApi.SendIORequest(fd.Value, IOCTL.CDIOREADTOCENTRIES, ref req) != 0) { throw new IOException("Failed to retrieve TOC entries.", new UnixException()); } tracks = new MMC.TrackDescriptor[trackcount]; var walker = req.data; for (var i = 0; i < trackcount; ++i) { tracks[i] = Util.MarshalPointerToStructure <MMC.TrackDescriptor>(walker); // The FixUp call assumes the address is in network byte order. if (nativeAddress) { tracks[i].Address = IPAddress.HostToNetworkOrder(tracks[i].Address); } tracks[i].FixUp(req.address_format == CDAddressFormat.CD_MSF_FORMAT); walker += itemsize; } } finally { Marshal.FreeHGlobal(req.data); } } }
private static extern int SendIORequest(int fd, IOCTL command, ref TOCEntriesRequest request);