/// <summary>
        /// Write an entry to the archive. This method will call the putNextEntry
        /// and then write the contents of the entry, and finally call closeEntry()
        /// for entries that are files. For directories, it will call putNextEntry(),
        /// and then, if the recurse flag is true, process each entry that is a
        /// child of the directory.
        /// </summary>
        /// <param name="sourceEntry">
        /// The TarEntry representing the entry to write to the archive.
        /// </param>
        /// <param name="recurse">
        /// If true, process the children of directory entries.
        /// </param>
        void WriteEntryCore(TarEntry sourceEntry, bool recurse)
        {
            string tempFileName  = null;
            string entryFilename = sourceEntry.File;

            TarEntry entry = (TarEntry)sourceEntry.Clone();

            if (applyUserInfoOverrides)
            {
                entry.GroupId   = groupId;
                entry.GroupName = groupName;
                entry.UserId    = userId;
                entry.UserName  = userName;
            }

            OnProgressMessageEvent(entry, null);

            if (asciiTranslate && !entry.IsDirectory)
            {
                if (!IsBinary(entryFilename))
                {
                    tempFileName = Path.GetTempFileName();

                    using (StreamReader inStream = File.OpenText(entryFilename))
                    {
                        using (Stream outStream = File.Create(tempFileName))
                        {
                            while (true)
                            {
                                string line = inStream.ReadLine();
                                if (line == null)
                                {
                                    break;
                                }
                                byte[] data = Encoding.ASCII.GetBytes(line);
                                outStream.Write(data, 0, data.Length);
                                outStream.WriteByte((byte)'\n');
                            }

                            outStream.Flush();
                        }
                    }

                    entry.Size    = new FileInfo(tempFileName).Length;
                    entryFilename = tempFileName;
                }
            }

            string newName = null;

            if (rootPath != null)
            {
                if (entry.Name.StartsWith(rootPath))
                {
                    newName = entry.Name.Substring(rootPath.Length + 1);
                }
            }

            if (pathPrefix != null)
            {
                newName = (newName == null) ? pathPrefix + "/" + entry.Name : pathPrefix + "/" + newName;
            }

            if (newName != null)
            {
                entry.Name = newName;
            }

            tarOut.PutNextEntry(entry);

            if (entry.IsDirectory)
            {
                if (recurse)
                {
                    TarEntry[] list = entry.GetDirectoryEntries();
                    for (int i = 0; i < list.Length; ++i)
                    {
                        WriteEntryCore(list[i], recurse);
                    }
                }
            }
            else
            {
                using (Stream inputStream = File.OpenRead(entryFilename))
                {
                    byte[] localBuffer = new byte[32 * 1024];
                    while (true)
                    {
                        int numRead = inputStream.Read(localBuffer, 0, localBuffer.Length);

                        if (numRead <= 0)
                        {
                            break;
                        }

                        tarOut.Write(localBuffer, 0, numRead);
                    }
                }

                if ((tempFileName != null) && (tempFileName.Length > 0))
                {
                    File.Delete(tempFileName);
                }

                tarOut.CloseEntry();
            }
        }