コード例 #1
1
		private void WriteObjectToTar (TarOutputStream  tar_out,
					       FileSystemObject fso,
					       EventTracker     tracker)
		{
			MemoryStream memory = null;

			TarHeader header;
			header = new TarHeader ();

			StringBuilder name_builder;
			name_builder = new StringBuilder (fso.FullName);
			name_builder.Remove (0, this.FullName.Length+1);
			header.Name = name_builder.ToString ();

			header.ModTime = fso.Timestamp;
			if (fso is DirectoryObject) {
				header.Mode = 511; // 0777
				header.TypeFlag = TarHeader.LF_DIR;
				header.Size = 0;
			} else {
				header.Mode = 438; // 0666
				header.TypeFlag = TarHeader.LF_NORMAL;
				memory = new MemoryStream ();
				((FileObject) fso).AddToStream (memory, tracker);
				header.Size = memory.Length;
			}

			TarEntry entry;
			entry = new TarEntry (header);

			tar_out.PutNextEntry (entry);
			if (memory != null) {
				tar_out.Write (memory.ToArray (), 0, (int) memory.Length);
				memory.Close ();
			}
			tar_out.CloseEntry ();

			// If this is a directory, write out the children
			if (fso is DirectoryObject)
				foreach (FileSystemObject child in fso.Children)
					WriteObjectToTar (tar_out, child, tracker);
		}
コード例 #2
0
		private void WriteObjectToZip (ZipOutputStream  zip_out,
					       FileSystemObject fso,
					       EventTracker     tracker)
		{

			MemoryStream memory = null;

			string name;
			name = fso.FullName.Substring (this.FullName.Length + 1);
			if (fso is DirectoryObject)
				name += "/";

			ZipEntry entry;
			entry = new ZipEntry (name);
			entry.DateTime = fso.Timestamp;
			
			if (fso is DirectoryObject)
				entry.Size = 0;
			else {
				memory = new MemoryStream ();
				((FileObject) fso).AddToStream (memory, tracker);
				entry.Size = memory.Length;
			}

			zip_out.PutNextEntry (entry);
			if (memory != null) {
				zip_out.Write (memory.ToArray (), 0, (int) memory.Length);
				memory.Close ();
			}

			// If this is a directory, write out the children
			if (fso is DirectoryObject)
				foreach (FileSystemObject child in fso.Children)
					WriteObjectToZip (zip_out, child, tracker);
		}
コード例 #3
0
ファイル: TestBasic.cs プロジェクト: ArsenShnurkov/beagle-1
		public bool HammerOnce (DirectoryObject dir, EventTracker tracker)
		{
			FileObject target;
			target = dir.PickChildFile ();
			if (target == null)
				return false;

			Log.Info ("Deleted file '{0}'", target.ShortName);			
			target.Parent.RemoveChild (target, tracker);
			
			return true;
		}
コード例 #4
0
ファイル: TestBasic.cs プロジェクト: ArsenShnurkov/beagle-1
		public bool HammerOnce (DirectoryObject dir, EventTracker tracker)
		{
			FileObject created;
			created = new TextFileObject (); // FIXME: or an archive

			DirectoryObject parent;
			parent = dir.PickDirectory ();
			parent.AddChild (created, tracker);
			
			Log.Info ("Created file '{0}'", created.ShortName);

			return true;
		}
コード例 #5
0
ファイル: TestBasic.cs プロジェクト: ArsenShnurkov/beagle-1
		public bool HammerOnce (DirectoryObject dir, EventTracker tracker)
		{
			DirectoryObject created;
			created = new DirectoryObject ();

			DirectoryObject parent;
			parent = dir.PickDirectory ();
			parent.AddChild (created, tracker);
			
			Log.Info ("Created directory {0}", created.ShortName);

			return true;
		}
コード例 #6
0
ファイル: FileObject.cs プロジェクト: ArsenShnurkov/beagle-1
		override public void AddOnDisk (EventTracker tracker)
		{
			FileStream stream;
			stream = new FileStream (FullName,
						 FileMode.Create,
						 FileAccess.Write,
						 FileShare.ReadWrite);
			AddToStream (stream, tracker);
			stream.Close ();

			// Stamp the right timestamp onto the file
			FileInfo info;
			info = new FileInfo (FullName);
			info.LastWriteTime = Timestamp;
		}
コード例 #7
0
ファイル: Abuse.cs プロジェクト: ArsenShnurkov/beagle-1
		public Abuse (DirectoryObject root,
			      EventTracker    tracker,
			      ICollection     hammers)
		{
			this.root = root;
			this.tracker = tracker;

			this.hammers = new IHammer [hammers.Count];
			int i = 0;
			foreach (IHammer hammer in hammers)
				this.hammers [i++] = hammer;

			idle_handler = new GLib.IdleHandler (AbuseWorker);
			timeout_handler = new GLib.TimeoutHandler (RescheduleAbuse);
			verified_handler = new Daemon.VerifiedHandler (VerifiedWorker);
		}
コード例 #8
0
		override public void AddToStream (Stream stream, EventTracker tracker)
		{
			if (tracker != null)
				tracker.ExpectingAdded (UriFu.UriToEscapedString (this.Uri));

			UnclosableStream unclosable;
			unclosable = new UnclosableStream (stream);

			ZipOutputStream zip_out;
			zip_out = new ZipOutputStream (unclosable);

			foreach (FileSystemObject fso in Children)
				WriteObjectToZip (zip_out, fso, tracker);
			zip_out.Finish ();
			zip_out.Close ();
		}
コード例 #9
0
		override public void AddToStream (Stream stream, EventTracker tracker)
		{
			if (tracker != null)
				tracker.ExpectingAdded (UriFu.UriToEscapedString (this.Uri));
			
			// We can't just use a StreamWriter here, since that
			// will close the underlying stream when it gets
			// disposed.
			UnclosableStream unclosable = new UnclosableStream (stream);
			StreamWriter writer = new StreamWriter (unclosable);

			foreach (string str in body) 
				writer.WriteLine (str);

			writer.Close ();
		}
コード例 #10
0
ファイル: Toolbox.cs プロジェクト: ArsenShnurkov/beagle-1
			public bool HammerOnce (DirectoryObject dir, EventTracker tracker)
			{
				// We randomly pick an IHammer, and call HammerOnce on it.
				// If it returns false, we try the next IHammer until we
				// find one that returns true or until we've exhausted
				// all possibilities.
				int i;
				i = random.Next (hammers.Count);

				for (int j = 0; j < hammers.Count; ++j) {
					int k = (i + j) % hammers.Count;
					IHammer hammer;
					hammer = hammers [k] as IHammer;
					if (hammer.HammerOnce (dir, tracker))
						return true;
				}

				return false;
			}
コード例 #11
0
ファイル: TestBasic.cs プロジェクト: ArsenShnurkov/beagle-1
		public bool HammerOnce (DirectoryObject dir, EventTracker tracker)
		{
			FileObject victim;

			do {
				victim = dir.PickChildFile ();
			} while (victim != null && victim.IsWritable);

			if (victim == null)
				return false;

			// Create an object w/ the right type
			FileObject created;
			created = TreeBuilder.NewFile (5, 10, victim.Extension, 0.1, 0.5, null); // FIXME: stupid magic numbers

			Log.Info ("Clobbered file '{0}'", victim.ShortName);
			victim.Parent.ClobberingAddChild (created, victim, tracker);

			return true;
		}
コード例 #12
0
		override public void AddToStream (Stream stream, EventTracker tracker)
		{
			if (ChildCount > 1)
				throw new Exception ("Bzip2 file " + Uri + " has " + ChildCount + " children");

			if (tracker != null)
				tracker.ExpectingAdded (UriFu.UriToEscapedString (this.Uri));

			UnclosableStream unclosable;
			unclosable = new UnclosableStream (stream);
			
			BZip2OutputStream bz2_out;
			bz2_out = new BZip2OutputStream (unclosable);
			
			MemoryStream memory;
			memory = new MemoryStream ();
			// There should just be one child
			foreach (FileObject file in Children)
				file.AddToStream (memory, tracker);
			bz2_out.Write (memory.ToArray (), 0, (int) memory.Length);
			memory.Close ();

			bz2_out.Close ();
		}
コード例 #13
0
ファイル: Bludgeon.cs プロジェクト: ArsenShnurkov/beagle-1
        static void Main(string [] args)
        {
            args = CommandLine.Process(typeof(BludgeonMain), args);

            // BU.CommandLine.Process returns null if --help was passed
            if (args == null)
            {
                return;
            }

            if (list_hammers)
            {
                foreach (string hammer in Toolbox.HammerNames)
                {
                    Console.WriteLine("  - {0}", hammer);
                }
                return;
            }

            ArrayList hammers_to_use;

            hammers_to_use = new ArrayList();
            foreach (string name in args)
            {
                IHammer hammer;
                hammer = Toolbox.GetHammer(name);
                if (hammer != null)
                {
                    hammers_to_use.Add(hammer);
                }
                else
                {
                    Log.Failure("Unknown hammer '{0}'", name);
                }
            }

            root = CreateTestRoot();
            TreeBuilder.Build(root,
                              30,             // number of directories
                              100,            // number of files
                              0,              //0.1,   // no archives
                              0,              //0.5,   // archive decay, which does nothing here
                              false,          // build all directories first, not in random order
                              null);          // no need to track events
            if (!root.VerifyOnDisk())
            {
                throw new Exception("VerifyOnDisk failed for " + root.FullName);
            }

            EventTracker tracker;

            tracker = new EventTracker();

            abuse = new Abuse(root, tracker, hammers_to_use);

            abuse.TotalCount = total_count;
            abuse.TotalTime  = total_time;

            abuse.Cycles    = cycles;
            abuse.MinCycles = min_cycles;
            abuse.MaxCycles = max_cycles;

            abuse.Pause    = pause;
            abuse.MinPause = min_pause;
            abuse.MaxPause = max_pause;

            GLib.Idle.Add(new GLib.IdleHandler(Startup));
            main_loop = new GLib.MainLoop();
            main_loop.Run();
        }
コード例 #14
0
ファイル: TestBasic.cs プロジェクト: ArsenShnurkov/beagle-1
		public bool HammerOnce (DirectoryObject dir, EventTracker tracker)
		{
			DirectoryObject new_parent;
			new_parent = dir.PickDirectory ();

			// 10 is a stupid magic number here.
			FileSystemObject target = null;
			for (int i = 0; i < 10 && target == null; ++i) {
				target = PickTarget (dir);
				if (target == null)
					return false;
				if (target.IsAncestorOf (new_parent))
					target = null;
			}
			if (target == null)
				return false;

			Log.Spew ("Moved {0} to {1}", target.ShortName, new_parent.ShortName);
			target.Parent.MoveChild (target, new_parent, tracker);
			return true;
		}
コード例 #15
0
 abstract public void AddToStream(Stream stream, EventTracker tracker);
コード例 #16
0
		// We assume that the FileSystemObject is in the tree, it its new position
		// when we call this.
		virtual public void MoveOnDisk (string old_full_name, EventTracker tracker)
		{
			throw new Exception ("MoveOnDisk undefined for " + FullName);
		}
コード例 #17
0
		public virtual void MoveChild (FileSystemObject child, FileSystemObject new_parent, EventTracker tracker)
		{
			if (child.parent != this)
				throw new Exception (child.Uri.ToString () + " is not a child of " + Uri.ToString ());

			if (new_parent == null || new_parent == child.parent)
				return;

			// We can't move child into new_parent if child is
			// already above new_parent in the tree.
			if (child.IsAncestorOf (new_parent))
				throw new Exception ("Can't move " + child.Uri.ToString () + " to " + new_parent.Uri.ToString ());
			
			string old_full_name;
			old_full_name = child.FullName;

			// FIXME: We need to handle the case of the moved
			// child clobbering another w/ the same name.

			child.parent = new_parent;
			this.children.Remove (child.Name);
			new_parent.children [child.Name] = child;

			// FIXME: What if this is not rooted, but new_parent is?
			if (new_parent.IsRooted)
				child.MoveOnDisk (old_full_name, tracker);
		}
コード例 #18
0
		public virtual void ClobberingAddChild (FileSystemObject child, FileSystemObject victim, EventTracker tracker)
		{
			if (children == null)
				throw new Exception ("Can't add a child to " + Uri.ToString ());
			if (child.parent != null)
				throw new Exception ("Can't add parented child " + child.Uri.ToString () + " to " + Uri.ToString ());
			if (victim.parent != this)
				throw new Exception ("Victim " + victim.Uri.ToString () + " is not a child of " + Uri.ToString ());
			if (child.Extension != victim.Extension)
				throw new Exception ("Extension mismatch: " + child.Extension + " vs. " + victim.Extension);

			victim.parent = null;
			child.parent = this;
			child.id = victim.id;
			child.base_name = victim.base_name;
			child.name = null;
			children [child.Name] = child;

			if (IsRooted)
				child.AddOnDisk (tracker);
		}
コード例 #19
0
        static public void Build(DirectoryObject root,
                                 int n_directories,
                                 int n_files,
                                 double p_archive,
                                 double archive_decay,
                                 bool build_in_random_order,
                                 EventTracker tracker)
        {
            //Log.Info ("BUILD {0} {1} {2}", n_directories, n_files, p_archive);
            Random random;

            random = new Random();

            // First, create the list of all of the directories we could
            // put things in.
            ArrayList all_dirs;

            all_dirs = new ArrayList();
            GetAllSubdirectories(root, all_dirs);

            int nd = n_directories, nf = n_files;

            // Next, we construct the directories and files.
            while (nd > 0 || nf > 0)
            {
                // If we are not building in a random order,
                // we create all of the directories first.
                bool create_dir;
                if (build_in_random_order)
                {
                    create_dir = (random.Next(nd + nf) < nd);
                }
                else
                {
                    create_dir = (nd > 0);
                }

                if (create_dir)
                {
                    DirectoryObject dir;
                    dir = new DirectoryObject();

                    FileSystemObject parent;
                    parent = (FileSystemObject)all_dirs [random.Next(all_dirs.Count)];
                    parent.AddChild(dir, tracker);
                    all_dirs.Add(dir);

                    //Log.Spew ("dir {0}: {1}", n_directories - nd, dir.FullName);
                    --nd;
                }
                else
                {
                    FileObject file;
                    file = NewFile(n_directories, n_files, null, p_archive, archive_decay, random);

                    FileSystemObject parent;
                    parent = (FileSystemObject)all_dirs [random.Next(all_dirs.Count)];
                    parent.AddChild(file, tracker);

#if false
                    // Commented out because it breaks queries

                    // 20% of the time make the file unwritable, which prevents us from
                    // being able to set extended attributes and makes us fall back to
                    // our sqlite store.
                    if (random.Next(5) == 0)
                    {
                        Syscall.chmod(file.FullName, (FilePermissions)292);                           // 0444
                    }
#endif

                    //Log.Spew ("file {0}: {1}", n_files - nf, file.FullName);
                    --nf;
                }
            }
        }
コード例 #20
0
		override public void DeleteOnDisk (EventTracker tracker)
		{
			// Recursively delete the children
			foreach (FileSystemObject fso in children.Values)
				fso.DeleteOnDisk (tracker);

			// Then delete ourselves
			Syscall.rmdir (FullName);
		}
コード例 #21
0
		///////////////////////////////////////////////////////////////////////

		override public void AddOnDisk (EventTracker tracker)
		{
			string full_name;
			full_name = FullName;
			if (full_name == null)
				throw new Exception ("Attempt to instantiate something other than a real file: " + Uri);

			if (is_root) {
				// Root directories must already exist.
				if (! Directory.Exists (full_name))
					throw new Exception ("Missing root directory " + full_name);
			} else {
				Directory.CreateDirectory (full_name);
				timestamp = Directory.GetLastWriteTimeUtc (full_name);
			}

			if (tracker != null)
				tracker.ExpectingAdded (UriFu.UriToEscapedString (this.Uri));

			// Recursively add the children
			foreach (FileSystemObject fso in children.Values)
				fso.AddOnDisk (tracker);
		}
コード例 #22
0
		public override void MoveChild (FileSystemObject child, FileSystemObject new_parent, EventTracker tracker)
		{
			int d_files, d_dirs;
			GetCountDeltas (child, out d_files, out d_dirs);

			DirectoryObject curr;
			curr = this;
			while (curr != null) {
				curr.n_files_below -= d_files;
				curr.n_dirs_below -= d_dirs;
				curr = (DirectoryObject) curr.Parent;
			}
			curr = (DirectoryObject) new_parent;
			while (curr != null) {
				curr.n_files_below += d_files;
				curr.n_dirs_below += d_dirs;
				curr = (DirectoryObject) curr.Parent;
			}
			
			base.MoveChild (child, new_parent, tracker);
		}
コード例 #23
0
		public override void RemoveChild (FileSystemObject child, EventTracker tracker)
		{
			// Likewise, we have to walk up the tree and adjust
			// the n_*_below counts when we remove a child.

			int d_files, d_dirs;
			GetCountDeltas (child, out d_files, out d_dirs);

			DirectoryObject curr;
			curr = this;
			while (curr != null) {
				curr.n_files_below -= d_files;
				curr.n_dirs_below -= d_dirs;
				curr = (DirectoryObject) curr.Parent;
			}

			base.RemoveChild (child, tracker);
		}
コード例 #24
0
 override public void MoveOnDisk(string old_full_name, EventTracker tracker)
 {
     Syscall.rename(old_full_name, FullName);
     // FIXME: adjust tracker
 }
コード例 #25
0
 override public void DeleteOnDisk(EventTracker tracker)
 {
     Syscall.unlink(FullName);
     // FIXME: adjust tracker
 }
コード例 #26
0
ファイル: TreeBuilder.cs プロジェクト: ArsenShnurkov/beagle-1
		static public void Build (DirectoryObject root,
					  int             n_directories,
					  int             n_files,
					  double          p_archive,
					  double          archive_decay,
					  bool            build_in_random_order,
					  EventTracker    tracker)
		{
			//Log.Info ("BUILD {0} {1} {2}", n_directories, n_files, p_archive);
			Random random;
			random = new Random ();

			// First, create the list of all of the directories we could
			// put things in.
			ArrayList all_dirs;
			all_dirs = new ArrayList ();
			GetAllSubdirectories (root, all_dirs);

			int nd = n_directories, nf = n_files;

			// Next, we construct the directories and files.
			while (nd > 0 || nf > 0) {
				
				// If we are not building in a random order,
				// we create all of the directories first.
				bool create_dir;
				if (build_in_random_order)
					create_dir = (random.Next (nd + nf) < nd);
				else
					create_dir = (nd > 0);

				if (create_dir) {
					
					DirectoryObject dir;
					dir = new DirectoryObject ();

					FileSystemObject parent;
					parent = (FileSystemObject) all_dirs [random.Next (all_dirs.Count)];
					parent.AddChild (dir, tracker);
					all_dirs.Add (dir);

					//Log.Spew ("dir {0}: {1}", n_directories - nd, dir.FullName);
					--nd;
					
				} else {

					
					FileObject file;
					file = NewFile (n_directories, n_files, null, p_archive, archive_decay, random);

					FileSystemObject parent;
					parent = (FileSystemObject) all_dirs [random.Next (all_dirs.Count)];
					parent.AddChild (file, tracker);

#if false
					// Commented out because it breaks queries
	
					// 20% of the time make the file unwritable, which prevents us from
					// being able to set extended attributes and makes us fall back to
					// our sqlite store.
					if (random.Next (5) == 0)
						Syscall.chmod (file.FullName, (FilePermissions) 292); // 0444
#endif

					//Log.Spew ("file {0}: {1}", n_files - nf, file.FullName);
					--nf;
				}
			}
		}
コード例 #27
0
ファイル: Bludgeon.cs プロジェクト: ArsenShnurkov/beagle-1
		static void Main (string [] args)
		{
			args = CommandLine.Process (typeof (BludgeonMain), args);

			// BU.CommandLine.Process returns null if --help was passed
			if (args == null)
				return;

			if (list_hammers) {
				foreach (string hammer in Toolbox.HammerNames)
					Console.WriteLine ("  - {0}", hammer);
				return;
			}

			ArrayList hammers_to_use;
			hammers_to_use = new ArrayList ();
			foreach (string name in args) {
				IHammer hammer;
				hammer = Toolbox.GetHammer (name);
				if (hammer != null)
					hammers_to_use.Add (hammer);
				else
					Log.Failure ("Unknown hammer '{0}'", name);
			}

			root = CreateTestRoot ();
			TreeBuilder.Build (root,
					   30,    // number of directories
					   100,   // number of files
					   0, //0.1,   // no archives
					   0, //0.5,   // archive decay, which does nothing here
					   false, // build all directories first, not in random order
					   null); // no need to track events
			if (! root.VerifyOnDisk ())
				throw new Exception ("VerifyOnDisk failed for " + root.FullName);
			
			EventTracker tracker;
			tracker = new EventTracker ();

			abuse = new Abuse (root, tracker, hammers_to_use);

			abuse.TotalCount = total_count;
			abuse.TotalTime = total_time;

			abuse.Cycles = cycles;
			abuse.MinCycles = min_cycles;
			abuse.MaxCycles = max_cycles;

			abuse.Pause = pause;
			abuse.MinPause = min_pause;
			abuse.MaxPause = max_pause;

			GLib.Idle.Add (new GLib.IdleHandler (Startup));
			main_loop = new GLib.MainLoop ();
			main_loop.Run ();
		}
コード例 #28
0
ファイル: FileObject.cs プロジェクト: ArsenShnurkov/beagle-1
		abstract public void AddToStream (Stream stream, EventTracker tracker);
コード例 #29
0
		public virtual void AddChild (FileSystemObject child, EventTracker tracker)
		{
			if (children == null)
				throw new Exception ("Can't add a child to " + Uri.ToString ());
			if (child.parent != null)
				throw new Exception ("Can't add parented child " + child.Uri.ToString () + " to " + Uri.ToString ());

			// FIXME: Need to handle the case of the added child
			// clobbering another w/ the same name.

			child.parent = this;
			children [child.Name] = child;
			
			if (IsRooted)
				child.AddOnDisk (tracker);
		}
コード例 #30
0
        public override void MoveChild(FileSystemObject child, FileSystemObject new_parent, EventTracker tracker)
        {
            int d_files, d_dirs;

            GetCountDeltas(child, out d_files, out d_dirs);

            DirectoryObject curr;

            curr = this;
            while (curr != null)
            {
                curr.n_files_below -= d_files;
                curr.n_dirs_below  -= d_dirs;
                curr = (DirectoryObject)curr.Parent;
            }
            curr = (DirectoryObject)new_parent;
            while (curr != null)
            {
                curr.n_files_below += d_files;
                curr.n_dirs_below  += d_dirs;
                curr = (DirectoryObject)curr.Parent;
            }

            base.MoveChild(child, new_parent, tracker);
        }
コード例 #31
0
		public virtual void RemoveChild (FileSystemObject child, EventTracker tracker)
		{
			if (child.parent != this)
				throw new Exception (child.Uri.ToString () + " is not a child of " + Uri.ToString ());

			if (IsRooted)
				child.DeleteOnDisk (tracker);

			child.parent = null;
			children.Remove (child.Name);
		}
コード例 #32
0
ファイル: FileObject.cs プロジェクト: ArsenShnurkov/beagle-1
		override public void DeleteOnDisk (EventTracker tracker)
		{
			Syscall.unlink (FullName);
			// FIXME: adjust tracker
		}
コード例 #33
0
		// We assume that the FileSystemObject is still in the tree (has a .parent
		// set, etc.) when we call this.
		virtual public void DeleteOnDisk (EventTracker tracker)
		{
			throw new Exception ("DeleteOnDisk undefined for " + FullName);	
		}
コード例 #34
0
ファイル: FileObject.cs プロジェクト: ArsenShnurkov/beagle-1
		override public void MoveOnDisk (string old_full_name, EventTracker tracker)
		{
			Syscall.rename (old_full_name, FullName);
			// FIXME: adjust tracker
		}
コード例 #35
0
		public override void AddChild (FileSystemObject child, EventTracker tracker)
		{
			// Every time we add a child, we walk up the tree
			// and adjust the n_*_below counts for every node
			// above us.

			int d_files, d_dirs;
			GetCountDeltas (child, out d_files, out d_dirs);

			DirectoryObject curr;
			curr = this;
			while (curr != null) {
				curr.n_files_below += d_files;
				curr.n_dirs_below += d_dirs;
				curr = (DirectoryObject) curr.Parent;
			}
				
			base.AddChild (child, tracker);
		}
コード例 #36
0
		override public void AddToStream (Stream stream, EventTracker tracker)
		{
			if (tracker != null)
				tracker.ExpectingAdded (UriFu.UriToEscapedString (this.Uri));

			UnclosableStream unclosable;
			unclosable = new UnclosableStream (stream);

			TarOutputStream tar_out;
			tar_out = new TarOutputStream (unclosable);
			foreach (FileSystemObject fso in Children)
				WriteObjectToTar (tar_out, fso, tracker);
			
			// This calls close on the underlying stream,
			// which is why we wrapped the stream in an
			// UnclosableStream.
			tar_out.Close ();
		}