static void ArchiveDirectoryToTARRecursively(Stream tarStream, string absoluteDirectory, string relativeDirectoryInUnixFormat, ref int filesDone, ref long bytesDone, byte[] paddingBuffer, byte[] tempBuffer, FileNameFilter filter) { WIN32_FIND_DATA findData; List <SubdirInfo> subdirs = new List <SubdirInfo>(); IntPtr hFind = FindFirstFile(absoluteDirectory + "\\*.*", out findData); int paddingSize; if (hFind == (IntPtr)(-1)) { return; } try { do { if ((findData.cFileName == ".") || (findData.cFileName == "..")) { continue; } if ((findData.dwFileAttributes & FileAttributes.Directory) != 0) { subdirs.Add(new SubdirInfo { Name = findData.cFileName, Date = DateTime.FromFileTime(MAKELONGLONG(findData.ftLastWriteTime.dwHighDateTime, findData.ftLastWriteTime.dwLowDateTime)) }); } else { string localFN = Path.Combine(absoluteDirectory, findData.cFileName); if (filter != null && !filter(localFN)) { continue; } using (var fsLocal = File.Open(localFN, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { string rel = relativeDirectoryInUnixFormat; if (rel != "") { rel += "/"; } rel += findData.cFileName; var timestamp = DateTime.FromFileTime(MAKELONGLONG(findData.ftLastWriteTime.dwHighDateTime, findData.ftLastWriteTime.dwLowDateTime)); long len = fsLocal.Length; var hdr = TarPacker.CreateHeader(rel, false, len, timestamp, out paddingSize); tarStream.Write(hdr, 0, hdr.Length); CopyStreamWithProgress(fsLocal, tarStream, ref filesDone, ref bytesDone, tempBuffer, len); tarStream.Write(paddingBuffer, 0, paddingSize); } } } while (FindNextFile(hFind, out findData)); } finally { FindClose(hFind); } foreach (var subdir in subdirs) { string rel = relativeDirectoryInUnixFormat; if (rel != "") { rel += "/"; } rel += subdir.Name; tarStream.Write(TarPacker.CreateHeader(rel, true, 0, subdir.Date, out paddingSize), 0, 512); ArchiveDirectoryToTARRecursively(tarStream, Path.Combine(absoluteDirectory, subdir.Name), rel, ref filesDone, ref bytesDone, paddingBuffer, tempBuffer, filter); } }