internal MacSerialStream(MacSerialDevice device)
            : base(device)
        {
            string fileSystemName = device.GetFileSystemName();

            int ret;
            int handle = NativeMethods.retry(() => NativeMethods.open(fileSystemName, NativeMethods.oflag.RDWR | NativeMethods.oflag.NOCTTY | NativeMethods.oflag.NONBLOCK));

            if (handle < 0)
            {
                var error = (NativeMethods.error)Marshal.GetLastWin32Error();
                if (error == NativeMethods.error.EACCES)
                {
                    throw DeviceException.CreateUnauthorizedAccessException(device, "Not permitted to open serial device at " + fileSystemName + ".");
                }
                else
                {
                    throw DeviceException.CreateIOException(device, "Unable to open serial device (" + error.ToString() + ").");
                }
            }

            ret = NativeMethods.retry(() => NativeMethods.ioctl(handle, NativeMethods.TIOCEXCL));
            if (ret < 0)
            {
                NativeMethods.retry(() => NativeMethods.close(handle));
                throw new IOException("Unable to open serial device exclusively.");
            }

            /*
             * ret = NativeMethods.retry(() => NativeMethods.fcntl(handle, NativeMethods.F_SETFL, 0));
             * if (ret < 0)
             * {
             *  NativeMethods.retry(() => NativeMethods.ioctl(handle, NativeMethods.TIOCNXCL));
             *  NativeMethods.retry(() => NativeMethods.close(handle));
             *  throw new IOException("Unable to remove blocking from port.");
             * }
             */

            ret = NativeMethods.retry(() => NativeMethods.tcgetattr(handle, out _oldSettings));
            if (ret < 0)
            {
                NativeMethods.retry(() => NativeMethods.ioctl(handle, NativeMethods.TIOCNXCL));
                NativeMethods.retry(() => NativeMethods.close(handle));
                throw new IOException("Unable to get serial port settings.");
            }

            _newSettings = _oldSettings;
            NativeMethods.cfmakeraw(ref _newSettings);
            _handle = handle;
            InitSettings();
            UpdateSettings();
        }
        protected override void Dispose(bool disposing)
        {
            try
            {
                lock (_lock)
                {
                    int handle = Interlocked.Exchange(ref _handle, -1);
                    if (handle >= 0)
                    {
                        NativeMethods.retry(() => NativeMethods.tcsetattr(handle, NativeMethods.TCSANOW, ref _oldSettings));
                        NativeMethods.retry(() => NativeMethods.ioctl(handle, NativeMethods.TIOCNXCL));
                        NativeMethods.retry(() => NativeMethods.close(handle));
                    }
                }
            }
            catch
            {
            }

            base.Dispose(disposing);
        }