Beispiel #1
0
        public void Open(string path)
        {
            string filename      = Path.GetFileName(path);
            string filenameNoExt = Path.GetFileNameWithoutExtension(path);
            string parentFolder  = Path.GetDirectoryName(path);

            parentFolder ??= "";

            if (filename is null ||
                filenameNoExt is null)
            {
                throw new ArgumentNullException(nameof(path));
            }

            // Prepend data fork name with "R."
            string proDosAppleDouble = Path.Combine(parentFolder, "R." + filename);

            // Prepend data fork name with '%'
            string unixAppleDouble = Path.Combine(parentFolder, "%" + filename);

            // Change file extension to ADF
            string dosAppleDouble = Path.Combine(parentFolder, filenameNoExt + ".ADF");

            // Change file extension to adf
            string dosAppleDoubleLower = Path.Combine(parentFolder, filenameNoExt + ".adf");

            // Store AppleDouble header file in ".AppleDouble" folder with same name
            string netatalkAppleDouble = Path.Combine(parentFolder, ".AppleDouble", filename);

            // Store AppleDouble header file in "resource.frk" folder with same name
            string daveAppleDouble = Path.Combine(parentFolder, "resource.frk", filename);

            // Prepend data fork name with "._"
            string osxAppleDouble = Path.Combine(parentFolder, "._" + filename);

            // Adds ".rsrc" extension
            string unArAppleDouble = Path.Combine(parentFolder, filename + ".rsrc");

            // Check AppleDouble created by A/UX in ProDOS filesystem
            if (File.Exists(proDosAppleDouble))
            {
                var prodosStream = new FileStream(proDosAppleDouble, FileMode.Open, FileAccess.Read);

                if (prodosStream.Length > 26)
                {
                    byte[] prodosB = new byte[26];
                    prodosStream.Read(prodosB, 0, 26);
                    _header = Marshal.ByteArrayToStructureBigEndian <AppleDoubleHeader>(prodosB);
                    prodosStream.Close();

                    if (_header.magic == MAGIC &&
                        (_header.version == VERSION || _header.version == VERSION2))
                    {
                        _headerPath = proDosAppleDouble;
                    }
                }
            }

            // Check AppleDouble created by A/UX in UFS filesystem
            if (File.Exists(unixAppleDouble))
            {
                var unixStream = new FileStream(unixAppleDouble, FileMode.Open, FileAccess.Read);

                if (unixStream.Length > 26)
                {
                    byte[] unixB = new byte[26];
                    unixStream.Read(unixB, 0, 26);
                    _header = Marshal.ByteArrayToStructureBigEndian <AppleDoubleHeader>(unixB);
                    unixStream.Close();

                    if (_header.magic == MAGIC &&
                        (_header.version == VERSION || _header.version == VERSION2))
                    {
                        _headerPath = unixAppleDouble;
                    }
                }
            }

            // Check AppleDouble created by A/UX in FAT filesystem
            if (File.Exists(dosAppleDouble))
            {
                var dosStream = new FileStream(dosAppleDouble, FileMode.Open, FileAccess.Read);

                if (dosStream.Length > 26)
                {
                    byte[] dosB = new byte[26];
                    dosStream.Read(dosB, 0, 26);
                    _header = Marshal.ByteArrayToStructureBigEndian <AppleDoubleHeader>(dosB);
                    dosStream.Close();

                    if (_header.magic == MAGIC &&
                        (_header.version == VERSION || _header.version == VERSION2))
                    {
                        _headerPath = dosAppleDouble;
                    }
                }
            }

            // Check AppleDouble created by A/UX in case preserving FAT filesystem
            if (File.Exists(dosAppleDoubleLower))
            {
                var doslStream = new FileStream(dosAppleDoubleLower, FileMode.Open, FileAccess.Read);

                if (doslStream.Length > 26)
                {
                    byte[] doslB = new byte[26];
                    doslStream.Read(doslB, 0, 26);
                    _header = Marshal.ByteArrayToStructureBigEndian <AppleDoubleHeader>(doslB);
                    doslStream.Close();

                    if (_header.magic == MAGIC &&
                        (_header.version == VERSION || _header.version == VERSION2))
                    {
                        _headerPath = dosAppleDoubleLower;
                    }
                }
            }

            // Check AppleDouble created by Netatalk
            if (File.Exists(netatalkAppleDouble))
            {
                var netatalkStream = new FileStream(netatalkAppleDouble, FileMode.Open, FileAccess.Read);

                if (netatalkStream.Length > 26)
                {
                    byte[] netatalkB = new byte[26];
                    netatalkStream.Read(netatalkB, 0, 26);
                    _header = Marshal.ByteArrayToStructureBigEndian <AppleDoubleHeader>(netatalkB);
                    netatalkStream.Close();

                    if (_header.magic == MAGIC &&
                        (_header.version == VERSION || _header.version == VERSION2))
                    {
                        _headerPath = netatalkAppleDouble;
                    }
                }
            }

            // Check AppleDouble created by DAVE
            if (File.Exists(daveAppleDouble))
            {
                var daveStream = new FileStream(daveAppleDouble, FileMode.Open, FileAccess.Read);

                if (daveStream.Length > 26)
                {
                    byte[] daveB = new byte[26];
                    daveStream.Read(daveB, 0, 26);
                    _header = Marshal.ByteArrayToStructureBigEndian <AppleDoubleHeader>(daveB);
                    daveStream.Close();

                    if (_header.magic == MAGIC &&
                        (_header.version == VERSION || _header.version == VERSION2))
                    {
                        _headerPath = daveAppleDouble;
                    }
                }
            }

            // Check AppleDouble created by Mac OS X
            if (File.Exists(osxAppleDouble))
            {
                var osxStream = new FileStream(osxAppleDouble, FileMode.Open, FileAccess.Read);

                if (osxStream.Length > 26)
                {
                    byte[] osxB = new byte[26];
                    osxStream.Read(osxB, 0, 26);
                    _header = Marshal.ByteArrayToStructureBigEndian <AppleDoubleHeader>(osxB);
                    osxStream.Close();

                    if (_header.magic == MAGIC &&
                        (_header.version == VERSION || _header.version == VERSION2))
                    {
                        _headerPath = osxAppleDouble;
                    }
                }
            }

            // Check AppleDouble created by UnAr (from The Unarchiver)
            if (File.Exists(unArAppleDouble))
            {
                var unarStream = new FileStream(unArAppleDouble, FileMode.Open, FileAccess.Read);

                if (unarStream.Length > 26)
                {
                    byte[] unarB = new byte[26];
                    unarStream.Read(unarB, 0, 26);
                    _header = Marshal.ByteArrayToStructureBigEndian <AppleDoubleHeader>(unarB);
                    unarStream.Close();

                    if (_header.magic == MAGIC &&
                        (_header.version == VERSION || _header.version == VERSION2))
                    {
                        _headerPath = unArAppleDouble;
                    }
                }
            }

            var fs = new FileStream(_headerPath, FileMode.Open, FileAccess.Read);

            fs.Seek(0, SeekOrigin.Begin);

            byte[] hdrB = new byte[26];
            fs.Read(hdrB, 0, 26);
            _header = Marshal.ByteArrayToStructureBigEndian <AppleDoubleHeader>(hdrB);

            AppleDoubleEntry[] entries = new AppleDoubleEntry[_header.entries];

            for (int i = 0; i < _header.entries; i++)
            {
                byte[] entry = new byte[12];
                fs.Read(entry, 0, 12);
                entries[i] = Marshal.ByteArrayToStructureBigEndian <AppleDoubleEntry>(entry);
            }

            _creationTime  = DateTime.UtcNow;
            _lastWriteTime = _creationTime;

            foreach (AppleDoubleEntry entry in entries)
            {
                switch ((AppleDoubleEntryID)entry.id)
                {
                case AppleDoubleEntryID.DataFork:
                    // AppleDouble have datafork in separated file
                    break;

                case AppleDoubleEntryID.FileDates:
                    fs.Seek(entry.offset, SeekOrigin.Begin);
                    byte[] datesB = new byte[16];
                    fs.Read(datesB, 0, 16);

                    AppleDoubleFileDates dates =
                        Marshal.ByteArrayToStructureBigEndian <AppleDoubleFileDates>(datesB);

                    _creationTime  = DateHandlers.UnixUnsignedToDateTime(dates.creationDate);
                    _lastWriteTime = DateHandlers.UnixUnsignedToDateTime(dates.modificationDate);

                    break;

                case AppleDoubleEntryID.FileInfo:
                    fs.Seek(entry.offset, SeekOrigin.Begin);
                    byte[] finfo = new byte[entry.length];
                    fs.Read(finfo, 0, finfo.Length);

                    if (_macintoshHome.SequenceEqual(_header.homeFilesystem))
                    {
                        AppleDoubleMacFileInfo macinfo =
                            Marshal.ByteArrayToStructureBigEndian <AppleDoubleMacFileInfo>(finfo);

                        _creationTime  = DateHandlers.MacToDateTime(macinfo.creationDate);
                        _lastWriteTime = DateHandlers.MacToDateTime(macinfo.modificationDate);
                    }
                    else if (_proDosHome.SequenceEqual(_header.homeFilesystem))
                    {
                        AppleDoubleProDOSFileInfo prodosinfo =
                            Marshal.ByteArrayToStructureBigEndian <AppleDoubleProDOSFileInfo>(finfo);

                        _creationTime  = DateHandlers.MacToDateTime(prodosinfo.creationDate);
                        _lastWriteTime = DateHandlers.MacToDateTime(prodosinfo.modificationDate);
                    }
                    else if (_unixHome.SequenceEqual(_header.homeFilesystem))
                    {
                        AppleDoubleUnixFileInfo unixinfo =
                            Marshal.ByteArrayToStructureBigEndian <AppleDoubleUnixFileInfo>(finfo);

                        _creationTime  = DateHandlers.UnixUnsignedToDateTime(unixinfo.creationDate);
                        _lastWriteTime = DateHandlers.UnixUnsignedToDateTime(unixinfo.modificationDate);
                    }
                    else if (_dosHome.SequenceEqual(_header.homeFilesystem))
                    {
                        AppleDoubleDOSFileInfo dosinfo =
                            Marshal.ByteArrayToStructureBigEndian <AppleDoubleDOSFileInfo>(finfo);

                        _lastWriteTime =
                            DateHandlers.DosToDateTime(dosinfo.modificationDate, dosinfo.modificationTime);
                    }

                    break;

                case AppleDoubleEntryID.ResourceFork:
                    _rsrcFork = entry;

                    break;
                }
            }

            _dataFork = new AppleDoubleEntry
            {
                id = (uint)AppleDoubleEntryID.DataFork
            };

            if (File.Exists(path))
            {
                var dataFs = new FileStream(path, FileMode.Open, FileAccess.Read);
                _dataFork.length = (uint)dataFs.Length;
                dataFs.Close();
            }

            fs.Close();
            _opened   = true;
            _basePath = path;
        }
Beispiel #2
0
        public void Open(string path)
        {
            string filename      = Path.GetFileName(path);
            string filenameNoExt = Path.GetFileNameWithoutExtension(path);
            string parentFolder  = Path.GetDirectoryName(path);

            // Prepend data fork name with "R."
            string ProDosAppleDouble =
                Path.Combine(parentFolder ?? throw new InvalidOperationException(), "R." + filename);
            // Prepend data fork name with '%'
            string UNIXAppleDouble = Path.Combine(parentFolder, "%" + filename);
            // Change file extension to ADF
            string DOSAppleDouble = Path.Combine(parentFolder, filenameNoExt + ".ADF");
            // Change file extension to adf
            string DOSAppleDoubleLower = Path.Combine(parentFolder, filenameNoExt + ".adf");
            // Store AppleDouble header file in ".AppleDouble" folder with same name
            string NetatalkAppleDouble =
                Path.Combine(parentFolder, ".AppleDouble", filename ?? throw new InvalidOperationException());
            // Store AppleDouble header file in "resource.frk" folder with same name
            string DAVEAppleDouble = Path.Combine(parentFolder, "resource.frk", filename);
            // Prepend data fork name with "._"
            string OSXAppleDouble = Path.Combine(parentFolder, "._" + filename);
            // Adds ".rsrc" extension
            string UnArAppleDouble = Path.Combine(parentFolder, filename + ".rsrc");

            // Check AppleDouble created by A/UX in ProDOS filesystem
            if (File.Exists(ProDosAppleDouble))
            {
                FileStream prodosStream = new FileStream(ProDosAppleDouble, FileMode.Open, FileAccess.Read);
                if (prodosStream.Length > 26)
                {
                    byte[] prodos_b = new byte[26];
                    prodosStream.Read(prodos_b, 0, 26);
                    header = BigEndianMarshal.ByteArrayToStructureBigEndian <AppleDoubleHeader>(prodos_b);
                    prodosStream.Close();
                    if (header.magic == AppleDoubleMagic &&
                        (header.version == AppleDoubleVersion || header.version == AppleDoubleVersion2))
                    {
                        headerPath = ProDosAppleDouble;
                    }
                }
            }

            // Check AppleDouble created by A/UX in UFS filesystem
            if (File.Exists(UNIXAppleDouble))
            {
                FileStream unixStream = new FileStream(UNIXAppleDouble, FileMode.Open, FileAccess.Read);
                if (unixStream.Length > 26)
                {
                    byte[] unix_b = new byte[26];
                    unixStream.Read(unix_b, 0, 26);
                    header = BigEndianMarshal.ByteArrayToStructureBigEndian <AppleDoubleHeader>(unix_b);
                    unixStream.Close();
                    if (header.magic == AppleDoubleMagic &&
                        (header.version == AppleDoubleVersion || header.version == AppleDoubleVersion2))
                    {
                        headerPath = UNIXAppleDouble;
                    }
                }
            }

            // Check AppleDouble created by A/UX in FAT filesystem
            if (File.Exists(DOSAppleDouble))
            {
                FileStream dosStream = new FileStream(DOSAppleDouble, FileMode.Open, FileAccess.Read);
                if (dosStream.Length > 26)
                {
                    byte[] dos_b = new byte[26];
                    dosStream.Read(dos_b, 0, 26);
                    header = BigEndianMarshal.ByteArrayToStructureBigEndian <AppleDoubleHeader>(dos_b);
                    dosStream.Close();
                    if (header.magic == AppleDoubleMagic &&
                        (header.version == AppleDoubleVersion || header.version == AppleDoubleVersion2))
                    {
                        headerPath = DOSAppleDouble;
                    }
                }
            }

            // Check AppleDouble created by A/UX in case preserving FAT filesystem
            if (File.Exists(DOSAppleDoubleLower))
            {
                FileStream doslStream = new FileStream(DOSAppleDoubleLower, FileMode.Open, FileAccess.Read);
                if (doslStream.Length > 26)
                {
                    byte[] dosl_b = new byte[26];
                    doslStream.Read(dosl_b, 0, 26);
                    header = BigEndianMarshal.ByteArrayToStructureBigEndian <AppleDoubleHeader>(dosl_b);
                    doslStream.Close();
                    if (header.magic == AppleDoubleMagic &&
                        (header.version == AppleDoubleVersion || header.version == AppleDoubleVersion2))
                    {
                        headerPath = DOSAppleDoubleLower;
                    }
                }
            }

            // Check AppleDouble created by Netatalk
            if (File.Exists(NetatalkAppleDouble))
            {
                FileStream netatalkStream = new FileStream(NetatalkAppleDouble, FileMode.Open, FileAccess.Read);
                if (netatalkStream.Length > 26)
                {
                    byte[] netatalk_b = new byte[26];
                    netatalkStream.Read(netatalk_b, 0, 26);
                    header = BigEndianMarshal.ByteArrayToStructureBigEndian <AppleDoubleHeader>(netatalk_b);
                    netatalkStream.Close();
                    if (header.magic == AppleDoubleMagic &&
                        (header.version == AppleDoubleVersion || header.version == AppleDoubleVersion2))
                    {
                        headerPath = NetatalkAppleDouble;
                    }
                }
            }

            // Check AppleDouble created by DAVE
            if (File.Exists(DAVEAppleDouble))
            {
                FileStream daveStream = new FileStream(DAVEAppleDouble, FileMode.Open, FileAccess.Read);
                if (daveStream.Length > 26)
                {
                    byte[] dave_b = new byte[26];
                    daveStream.Read(dave_b, 0, 26);
                    header = BigEndianMarshal.ByteArrayToStructureBigEndian <AppleDoubleHeader>(dave_b);
                    daveStream.Close();
                    if (header.magic == AppleDoubleMagic &&
                        (header.version == AppleDoubleVersion || header.version == AppleDoubleVersion2))
                    {
                        headerPath = DAVEAppleDouble;
                    }
                }
            }

            // Check AppleDouble created by Mac OS X
            if (File.Exists(OSXAppleDouble))
            {
                FileStream osxStream = new FileStream(OSXAppleDouble, FileMode.Open, FileAccess.Read);
                if (osxStream.Length > 26)
                {
                    byte[] osx_b = new byte[26];
                    osxStream.Read(osx_b, 0, 26);
                    header = BigEndianMarshal.ByteArrayToStructureBigEndian <AppleDoubleHeader>(osx_b);
                    osxStream.Close();
                    if (header.magic == AppleDoubleMagic &&
                        (header.version == AppleDoubleVersion || header.version == AppleDoubleVersion2))
                    {
                        headerPath = OSXAppleDouble;
                    }
                }
            }

            // Check AppleDouble created by UnAr (from The Unarchiver)
            if (File.Exists(UnArAppleDouble))
            {
                FileStream unarStream = new FileStream(UnArAppleDouble, FileMode.Open, FileAccess.Read);
                if (unarStream.Length > 26)
                {
                    byte[] unar_b = new byte[26];
                    unarStream.Read(unar_b, 0, 26);
                    header = BigEndianMarshal.ByteArrayToStructureBigEndian <AppleDoubleHeader>(unar_b);
                    unarStream.Close();
                    if (header.magic == AppleDoubleMagic &&
                        (header.version == AppleDoubleVersion || header.version == AppleDoubleVersion2))
                    {
                        headerPath = UnArAppleDouble;
                    }
                }
            }

            FileStream fs = new FileStream(headerPath, FileMode.Open, FileAccess.Read);

            fs.Seek(0, SeekOrigin.Begin);

            byte[] hdr_b = new byte[26];
            fs.Read(hdr_b, 0, 26);
            header = BigEndianMarshal.ByteArrayToStructureBigEndian <AppleDoubleHeader>(hdr_b);

            AppleDoubleEntry[] entries = new AppleDoubleEntry[header.entries];
            for (int i = 0; i < header.entries; i++)
            {
                byte[] entry = new byte[12];
                fs.Read(entry, 0, 12);
                entries[i] = BigEndianMarshal.ByteArrayToStructureBigEndian <AppleDoubleEntry>(entry);
            }

            creationTime  = DateTime.UtcNow;
            lastWriteTime = creationTime;
            foreach (AppleDoubleEntry entry in entries)
            {
                switch ((AppleDoubleEntryID)entry.id)
                {
                case AppleDoubleEntryID.DataFork:
                    // AppleDouble have datafork in separated file
                    break;

                case AppleDoubleEntryID.FileDates:
                    fs.Seek(entry.offset, SeekOrigin.Begin);
                    byte[] dates_b = new byte[16];
                    fs.Read(dates_b, 0, 16);
                    AppleDoubleFileDates dates =
                        BigEndianMarshal.ByteArrayToStructureBigEndian <AppleDoubleFileDates>(dates_b);
                    creationTime  = DateHandlers.UnixUnsignedToDateTime(dates.creationDate);
                    lastWriteTime = DateHandlers.UnixUnsignedToDateTime(dates.modificationDate);
                    break;

                case AppleDoubleEntryID.FileInfo:
                    fs.Seek(entry.offset, SeekOrigin.Begin);
                    byte[] finfo = new byte[entry.length];
                    fs.Read(finfo, 0, finfo.Length);
                    if (MacintoshHome.SequenceEqual(header.homeFilesystem))
                    {
                        AppleDoubleMacFileInfo macinfo =
                            BigEndianMarshal.ByteArrayToStructureBigEndian <AppleDoubleMacFileInfo>(finfo);
                        creationTime  = DateHandlers.MacToDateTime(macinfo.creationDate);
                        lastWriteTime = DateHandlers.MacToDateTime(macinfo.modificationDate);
                    }
                    else if (ProDOSHome.SequenceEqual(header.homeFilesystem))
                    {
                        AppleDoubleProDOSFileInfo prodosinfo =
                            BigEndianMarshal.ByteArrayToStructureBigEndian <AppleDoubleProDOSFileInfo>(finfo);
                        creationTime  = DateHandlers.MacToDateTime(prodosinfo.creationDate);
                        lastWriteTime = DateHandlers.MacToDateTime(prodosinfo.modificationDate);
                    }
                    else if (UNIXHome.SequenceEqual(header.homeFilesystem))
                    {
                        AppleDoubleUNIXFileInfo unixinfo =
                            BigEndianMarshal.ByteArrayToStructureBigEndian <AppleDoubleUNIXFileInfo>(finfo);
                        creationTime  = DateHandlers.UnixUnsignedToDateTime(unixinfo.creationDate);
                        lastWriteTime = DateHandlers.UnixUnsignedToDateTime(unixinfo.modificationDate);
                    }
                    else if (DOSHome.SequenceEqual(header.homeFilesystem))
                    {
                        AppleDoubleDOSFileInfo dosinfo =
                            BigEndianMarshal.ByteArrayToStructureBigEndian <AppleDoubleDOSFileInfo>(finfo);
                        lastWriteTime =
                            DateHandlers.DosToDateTime(dosinfo.modificationDate, dosinfo.modificationTime);
                    }

                    break;

                case AppleDoubleEntryID.ResourceFork:
                    rsrcFork = entry;
                    break;
                }
            }

            dataFork = new AppleDoubleEntry {
                id = (uint)AppleDoubleEntryID.DataFork
            };
            if (File.Exists(path))
            {
                FileStream dataFs = new FileStream(path, FileMode.Open, FileAccess.Read);
                dataFork.length = (uint)dataFs.Length;
                dataFs.Close();
            }

            fs.Close();
            opened   = true;
            basePath = path;
        }