예제 #1
0
파일: CSB.cs 프로젝트: poArlim/APFS
        public static List <CSB> get_deleted_csb_list(FileStream fs, UInt64 last_csb_address)
        {
            List <CSB> csb_list      = new List <CSB>();
            UInt64     next_csb_addr = last_csb_address + 2 * CSB.BlockSize;

            while (true)
            {
                // Console.WriteLine("next_csb_addr : {0}", next_csb_addr);
                CSB csb = init_csb(fs, next_csb_addr);
                if (csb == null)
                {
                    break;
                }
                //Console.WriteLine("------deleted csb Address : {0}", csb.CSB_Address);

                //Console.WriteLine("checkpoint : {0}", csb.CSB_Checkpoint);
                //Console.WriteLine(" OldestCSBD : {0}", csb.OldestCSBD);
                //Console.WriteLine(" OriginalCSBD : {0}", csb.OriginalCSBD);
                //Console.WriteLine(" NextCSBD : {0}", csb.NextCSBD);
                //Console.WriteLine(" magic : {0}\n", new String(csb.CSB_Magic));

                csb_list.Add(csb);
                next_csb_addr = csb.CSB_Address + 2 * CSB.BlockSize;
            }

            return(csb_list);
        }
예제 #2
0
파일: CSB.cs 프로젝트: poArlim/APFS
        public static CSB init_first_csb(FileStream fs)
        {
            CSB csb = new CSB();

            csb.CSB_Address = Utility.get_string_address(fs, 0, "NXSB") - 32;

            csb = init_csb(fs, csb.CSB_Address);

            return(csb);
        }
예제 #3
0
파일: CSB.cs 프로젝트: poArlim/APFS
        public static List <CSB> get_csb_list(FileStream fs)
        {
            List <CSB> csb_list  = new List <CSB>();
            CSB        first_csb = CSB.init_first_csb(fs);

            CSB.first_csb_address = first_csb.CSB_Address;
            UInt64 next_csb_addr = Utility.get_address(first_csb.OldestCSBD) + CSB.BlockSize;

            Console.WriteLine("=======first csb Address : {0}", first_csb.CSB_Address);

            Console.WriteLine("checkpoint : {0}", first_csb.CSB_Checkpoint);
            Console.WriteLine(" OldestCSBD : {0}", first_csb.OldestCSBD);
            Console.WriteLine(" OriginalCSBD : {0}", first_csb.OriginalCSBD);
            Console.WriteLine(" NextCSBD : {0}", first_csb.NextCSBD);

            while (true)
            {
                //Console.WriteLine("next_csb_addr : {0}", next_csb_addr);
                CSB csb = init_csb(fs, next_csb_addr);
                if (csb == null)
                {
                    break;
                }

                /*
                 * Console.WriteLine("=======csb Address : {0}", csb.CSB_Address);
                 *
                 * Console.WriteLine("checkpoint : {0}", csb.CSB_Checkpoint);
                 * Console.WriteLine(" OldestCSBD : {0}", csb.OldestCSBD);
                 * Console.WriteLine(" OriginalCSBD : {0}", csb.OriginalCSBD);
                 * Console.WriteLine(" NextCSBD : {0}", csb.NextCSBD);
                 */
                csb_list.Add(csb);
                next_csb_addr = Utility.get_address(csb.NextCSBD) + CSB.BlockSize;
                if (csb.OriginalCSBD == first_csb.OriginalCSBD)
                {
                    break;
                }
            }

            Console.WriteLine("fin init get csb list");
            return(csb_list);
        }
예제 #4
0
파일: CSB.cs 프로젝트: poArlim/APFS
        public static CSB init_csb(FileStream fs, UInt64 block_addr)
        {
            CSB    csb = new CSB();
            int    n;
            string hex;

            byte[] buf = new byte[64];

            fs.Seek((Int64)block_addr + Convert.ToInt64("0x00", 16), SeekOrigin.Begin);
            n   = fs.Read(buf, 0, 8);
            hex = BitConverter.ToString(buf).Replace("-", String.Empty);
            csb.BlockChecksum = Utility.little_hex_to_uint64(hex, n);

            n           = fs.Read(buf, 0, 8);
            hex         = BitConverter.ToString(buf).Replace("-", String.Empty);
            csb.BlockID = Utility.little_hex_to_uint64(hex, n);

            n   = fs.Read(buf, 0, 8);
            hex = BitConverter.ToString(buf).Replace("-", String.Empty);
            csb.CSB_Checkpoint = Utility.little_hex_to_uint64(hex, n);

            fs.Seek((Int64)block_addr + Convert.ToInt64("0x20", 16), SeekOrigin.Begin);
            n             = fs.Read(buf, 0, 4);
            hex           = BitConverter.ToString(buf).Replace("-", String.Empty);
            csb.CSB_Magic = Utility.hex_to_charArray(hex.Substring(0, 8));

            n = fs.Read(buf, 0, 4);
            //hex = BitConverter.ToString(buf).Replace("-", String.Empty);
            //CSB.BlockSize = (UInt32)Utility.little_hex_to_uint64(hex, n);

            n               = fs.Read(buf, 0, 8);
            hex             = BitConverter.ToString(buf).Replace("-", String.Empty);
            csb.TotalBlocks = Utility.little_hex_to_uint64(hex, n);

            fs.Seek((Int64)block_addr + Convert.ToInt64("0x60", 16), SeekOrigin.Begin);
            n              = fs.Read(buf, 0, 8);
            hex            = BitConverter.ToString(buf).Replace("-", String.Empty);
            csb.NextCSB_ID = Utility.little_hex_to_uint64(hex, n);

            fs.Seek((Int64)block_addr + Convert.ToInt64("0x70", 16), SeekOrigin.Begin);
            n             = fs.Read(buf, 0, 4);
            hex           = BitConverter.ToString(buf).Replace("-", String.Empty);
            csb.BaseBlock = (UInt32)Utility.little_hex_to_uint64(hex, n);

            fs.Seek((Int64)block_addr + Convert.ToInt64("0x80", 16), SeekOrigin.Begin);
            n            = fs.Read(buf, 0, 4);
            hex          = BitConverter.ToString(buf).Replace("-", String.Empty);
            csb.NextCSBD = (UInt32)Utility.little_hex_to_uint64(hex, n) + csb.BaseBlock;

            fs.Seek((Int64)block_addr + Convert.ToInt64("0x88", 16), SeekOrigin.Begin);
            n   = fs.Read(buf, 0, 4);
            hex = BitConverter.ToString(buf).Replace("-", String.Empty);
            csb.OriginalCSBD = (UInt32)Utility.little_hex_to_uint64(hex, n) + csb.BaseBlock;

            n              = fs.Read(buf, 0, 4);
            hex            = BitConverter.ToString(buf).Replace("-", String.Empty);
            csb.OldestCSBD = (UInt32)Utility.little_hex_to_uint64(hex, n) - 1;

            fs.Seek((Int64)block_addr + Convert.ToInt64("0xA0", 16), SeekOrigin.Begin);
            n   = fs.Read(buf, 0, 8);
            hex = BitConverter.ToString(buf).Replace("-", String.Empty);
            csb.VolumesIndexblock = Utility.little_hex_to_uint64(hex, n);

            fs.Seek((Int64)block_addr + Convert.ToInt64("0xB4", 16), SeekOrigin.Begin);
            n   = fs.Read(buf, 0, 4);
            hex = BitConverter.ToString(buf).Replace("-", String.Empty);
            csb.VolumesMaxNumber = (UInt32)Utility.little_hex_to_uint64(hex, n);

            n   = fs.Read(buf, 0, 8);
            hex = BitConverter.ToString(buf).Replace("-", String.Empty);
            csb.VolumeID_List = Utility.little_hex_to_uint64(hex, n);

            csb.CSB_Address = block_addr;


            //Console.WriteLine("BlockChecksum :{0}", csb.BlockChecksum);
            //Console.WriteLine("BlockID :{0}", csb.BlockID);
            //Console.WriteLine("CSB_Checkpoint :{0}", csb.CSB_Checkpoint);
            //Console.WriteLine("CSB_Address :{0}", csb.CSB_Address);
            //Console.WriteLine("BlockSize :{0} ", CSB.BlockSize);
            ////string s = new string(csb.CSB_Magic);
            ////Console.WriteLine("-->MAGIC : {0}", s);

            //Console.WriteLine("TotalBlocks :{0}", csb.TotalBlocks);
            //Console.WriteLine("NextCSB_ID :{0}", csb.NextCSB_ID);
            //Console.WriteLine("BaseBlock :{0}", csb.BaseBlock);
            //Console.WriteLine("NextCSBD :{0}", csb.NextCSBD);
            //Console.WriteLine("OriginalCSBD :{0} ", csb.OriginalCSBD);
            //Console.WriteLine("OldestCSBD :{0} ", csb.OldestCSBD);

            //Console.WriteLine("VolumesIndexblock :{0}", csb.VolumesIndexblock);
            //Console.WriteLine("VolumesMaxNumber :{0} ", csb.VolumesMaxNumber);
            //Console.WriteLine("VolumeID_List :{0} ", csb.VolumeID_List);

            String magic = new string(csb.CSB_Magic, 0, csb.CSB_Magic.Length);

            if (magic.Equals("NXSB"))
            {
                return(csb);
            }

            return(null);
        }
예제 #5
0
        public static bool init_APFS(FileStream fs, CSB csb)
        {
            Console.WriteLine("*************** Make File Structure at Checkpoint : {0} *************", csb.CSB_Checkpoint);
            RECORD.parent_node_dic.Clear();
            RECORD.parent_node_dic = new Dictionary <UInt64, List <UInt64> >();
            RECORD.ffr_dict.Clear();
            RECORD.ffr_dict = new Dictionary <UInt64, FileFolderRecord>();
            RECORD.er_dic.Clear();
            RECORD.er_dic = new Dictionary <UInt64, ExtentRecord>();

            ////volume structure
            UInt64 VRB_addr = csb.VolumesIndexblock;

            Console.WriteLine();
            Console.WriteLine("VRB address : {0} {1}", VRB_addr, Utility.get_address(VRB_addr));

            UInt64 VB_addr = Table.get_block_address(fs, VRB_addr, "0x30");

            Console.WriteLine("VB address : {0}", VB_addr);

            Console.WriteLine("first csb address : {0}, blocksize : {1}, totalLength : {2}", CSB.first_csb_address, CSB.BlockSize, CSB.TotalSize);

            Table VB_h;

            VB_h = Table.get_table_header(fs, VB_addr);
            if (VB_h == null)
            {
                throw new Exception("This csb is invalid.");
            }

            //VB record
            Console.WriteLine();
            TableType[] VBrecords = Table.save_record(fs, VB_addr, VB_h);

            //VCSB
            for (int i = 0; i < VB_h.record_num; i++)
            {
                Console.WriteLine();
                UInt64 VCSB_addr;
                VCSB_addr = VBrecords[i].BlockNum;
                Console.WriteLine("VCSB_addr : {0}", VCSB_addr);

                //각 VCSB
                Console.WriteLine();
                VCSB vcsb = VCSB.init_vcsb(fs, VCSB_addr);

                //BTCS
                Console.WriteLine();
                UInt64 BTCS_addr = vcsb.BTCS;
                Console.WriteLine("BTCS address : {0}", BTCS_addr);

                UInt64 BTOM_addr = Table.get_block_address(fs, BTCS_addr, "0x30");
                Console.WriteLine("BTOM address : {0}", BTOM_addr);


                int n = 0;

                List <BTCS> btrn_btln = BTCS.init_btom(fs, BTOM_addr);

                foreach (BTCS b in btrn_btln)
                {
                    n++;
                    Console.WriteLine("btrn_btln : {0} ", n);
                    Console.WriteLine("node id : {0}", b.NodeID);
                    Console.WriteLine("Checkpoint : {0}", b.Checkpoint);
                    Console.WriteLine("block num: {0}, {1}\n", b.BlockNum, Utility.get_address(b.BlockNum));

                    if (n > 1)
                    {
                        RECORD.init_btln(fs, b.BlockNum);
                    }
                }


                // Queue 만들기
                Queue <UInt64> q = new Queue <UInt64>();

                q.Enqueue(2);   // NodeID of root node

                ulong root = 2;

                if (!RECORD.parent_node_dic.ContainsKey(root))
                {
                    return(true);
                }
                RECORD.ffr_dict[root].path = @restore_to_path;



                while (q.Count > 0)
                {
                    UInt64 parent_node_id = q.Dequeue();
                    String parent_path    = RECORD.ffr_dict[parent_node_id].path;

                    Console.WriteLine("ParentID = {0}", parent_node_id);
                    if (!RECORD.parent_node_dic.ContainsKey(parent_node_id))
                    {
                        continue;
                    }
                    foreach (UInt64 child_node_Id in RECORD.parent_node_dic[parent_node_id])
                    {
                        String fname    = new string(RECORD.ffr_dict[child_node_Id].FileName, 0, RECORD.ffr_dict[child_node_Id].FileName.Length - 1);
                        String new_path = Path.Combine(parent_path, fname);
                        RECORD.ffr_dict[child_node_Id].path = new_path;


                        Console.WriteLine("     NodeID = {0}, path : {1}", child_node_Id, new_path);

                        if (RECORD.ffr_dict[child_node_Id].Flag[0] == '8')
                        {
                            if (RECORD.er_dic.ContainsKey(child_node_Id))
                            {
                                Extent new_extent = Extent.read_extent(fs, (long)Utility.get_address(RECORD.er_dic[child_node_Id].ExtentStartBlockNum), (long)RECORD.er_dic[child_node_Id].ExtentLength);
                                Extent.write_extent(child_node_Id, new_extent.buf, new_extent.Count, new_path);
                            }
                            else
                            {
                                if (!File.Exists(new_path))
                                {
                                    File.Create(new_path);
                                }
                            }
                        }
                        else if (RECORD.ffr_dict[child_node_Id].Flag[0] == '4')
                        {
                            q.Enqueue(child_node_Id);

                            Directory.CreateDirectory(new_path);
                        }
                    }
                }

                Console.WriteLine();
            }
            Console.WriteLine("FIN");
            return(true);
        }
예제 #6
0
        public static bool restore_folder(FileStream fs, CSB csb, string search_name)
        {
            RECORD.parent_node_dic.Clear();
            RECORD.parent_node_dic = new Dictionary <UInt64, List <UInt64> >();
            RECORD.ffr_dict.Clear();
            RECORD.ffr_dict = new Dictionary <UInt64, FileFolderRecord>();
            RECORD.er_dic.Clear();
            RECORD.er_dic = new Dictionary <UInt64, ExtentRecord>();

            bool restore = false;
            ////volume structure
            UInt64 VRB_addr = csb.VolumesIndexblock;
            UInt64 VB_addr  = Table.get_block_address(fs, VRB_addr, "0x30");

            Table VB_h = Table.get_table_header(fs, VB_addr);

            if (VB_h == null)
            {
                throw new Exception("This csb is invalid.\n Cannot restore folder");
            }



            //VB record
            Console.WriteLine();
            TableType[] VBrecords = Table.save_record(fs, VB_addr, VB_h);

            //VCSB
            for (int i = 0; i < VB_h.record_num; i++)
            {
                Console.WriteLine();
                UInt64 VCSB_addr;
                VCSB_addr = VBrecords[i].BlockNum;

                //각 VCSB
                Console.WriteLine();
                VCSB vcsb = VCSB.init_vcsb(fs, VCSB_addr);

                //BTCS
                Console.WriteLine();
                UInt64 BTCS_addr = vcsb.BTCS;
                UInt64 BTOM_addr = Table.get_block_address(fs, BTCS_addr, "0x30");


                int n = 0;

                List <BTCS> btrn_btln = BTCS.init_btom(fs, BTOM_addr);

                foreach (BTCS b in btrn_btln)
                {
                    n++;

                    if (n > 1)
                    {
                        RECORD.init_btln(fs, b.BlockNum);
                    }
                }


                // Queue 만들기
                Queue <UInt64> q = new Queue <UInt64>();

                q.Enqueue(2);   // NodeID of root node

                ulong root = 2;

                if (!RECORD.parent_node_dic.ContainsKey(root))
                {
                    return(false);
                }
                RECORD.ffr_dict[root].path = @restore_to_path;

                restore = false;

                while (q.Count > 0)
                {
                    UInt64 parent_node_id = q.Dequeue();
                    String parent_path    = RECORD.ffr_dict[parent_node_id].path;

                    Console.WriteLine("ParentID = {0}", parent_node_id);
                    if (!RECORD.parent_node_dic.ContainsKey(parent_node_id))
                    {
                        continue;
                    }
                    foreach (UInt64 child_node_Id in RECORD.parent_node_dic[parent_node_id])
                    {
                        String fname = new string(RECORD.ffr_dict[child_node_Id].FileName, 0, RECORD.ffr_dict[child_node_Id].FileName.Length - 1);
                        if (restore)
                        {
                            RECORD.ffr_dict[child_node_Id].path = Path.Combine(parent_path, fname);
                        }
                        else
                        {
                            RECORD.ffr_dict[child_node_Id].path = parent_path;
                        }

                        Console.WriteLine("     NodeID = {0}, {1}", child_node_Id, fname);
                        String new_path = RECORD.ffr_dict[child_node_Id].path;
                        if (restore && RECORD.ffr_dict[child_node_Id].Flag[0] == '8')
                        {
                            if (RECORD.er_dic.ContainsKey(child_node_Id))
                            {
                                Extent new_extent = Extent.read_extent(fs, (long)Utility.get_address(RECORD.er_dic[child_node_Id].ExtentStartBlockNum), (long)RECORD.er_dic[child_node_Id].ExtentLength);
                                Extent.write_extent(child_node_Id, new_extent.buf, new_extent.Count, new_path);
                            }
                            else if (!File.Exists(new_path))
                            {
                                File.Create(new_path);
                            }
                        }
                        if (RECORD.ffr_dict[child_node_Id].Flag[0] == '4')
                        {
                            if (!restore)
                            {
                                if (fname.Equals(search_name))
                                {
                                    Console.WriteLine("---------Find Folder-------");
                                    RECORD.ffr_dict[child_node_Id].path = Path.Combine(RECORD.ffr_dict[child_node_Id].path, fname);
                                    Directory.CreateDirectory(RECORD.ffr_dict[child_node_Id].path);
                                    q.Clear();
                                    q.Enqueue(child_node_Id);
                                    restore = true;
                                    break;
                                }
                                else
                                {
                                    q.Enqueue(child_node_Id);
                                }
                            }
                            else
                            {
                                Directory.CreateDirectory(new_path);
                                q.Enqueue(child_node_Id);
                            }
                        }
                    }
                }

                Console.WriteLine();
            }
            Console.WriteLine("FIN");

            return(restore);
        }
예제 #7
0
        static void Main()
        {
            Console.WriteLine("Enter the absolute path of the dmg file : ");
            dmgPath = Console.ReadLine();
            Console.WriteLine("Enter an absolute path to save the file system. : ");
            restore_to_path = Console.ReadLine();

            try
            {
                using (FileStream fs = new FileStream(@dmgPath, FileMode.Open))
                {
                    bool       make_csb         = false;
                    List <CSB> csb_list         = new List <CSB>();
                    List <CSB> deleted_csb_list = new List <CSB>();
                    CSB        msb = new CSB();
                    while (true)
                    {
                        String input = "";
                        Console.WriteLine("-----------------------------------------------------");
                        Console.WriteLine(" 1. Restore Filesystem Structure");
                        Console.WriteLine(" 2. TimeMachine");
                        Console.WriteLine(" 3. Restore Deleted Folder");
                        Console.WriteLine(" 4. Restore Deleted File");
                        Console.WriteLine(" 5. quit");
                        Console.WriteLine("-----------------------------------------------------");
                        input = Console.ReadLine();

                        if (!make_csb)
                        {
                            CSB.TotalSize    = (UInt64)fs.Length;
                            CSB.BlockSize    = (UInt32)4096;
                            csb_list         = CSB.get_csb_list(fs);
                            deleted_csb_list = CSB.get_deleted_csb_list(fs, Utility.get_address(csb_list[csb_list.Count - 1].NextCSBD) + CSB.BlockSize);
                            csb_list.Sort((a, b) => a.CSB_Checkpoint.CompareTo(b.CSB_Checkpoint));
                            msb = csb_list[csb_list.Count - 1];
                            foreach (CSB csb in csb_list)
                            {
                                Console.WriteLine("*************Chckpoint : {0} \n address : {1}", csb.CSB_Checkpoint, csb.CSB_Address);
                                Console.WriteLine("checkpoint : {0}", csb.CSB_Checkpoint);
                                Console.WriteLine(" OldestCSBD : {0}", csb.OldestCSBD);
                                Console.WriteLine(" OriginalCSBD : {0}", csb.OriginalCSBD);
                                Console.WriteLine(" NextCSBD : {0}", csb.NextCSBD);
                            }
                            foreach (CSB csb in deleted_csb_list)
                            {
                                Console.WriteLine("--------------deleted Chckpoint : {0}\n address : {1}", csb.CSB_Checkpoint, csb.CSB_Address);
                                Console.WriteLine("checkpoint : {0}", csb.CSB_Checkpoint);
                                Console.WriteLine(" OldestCSBD : {0}", csb.OldestCSBD);
                                Console.WriteLine(" OriginalCSBD : {0}", csb.OriginalCSBD);
                                Console.WriteLine(" NextCSBD : {0}", csb.NextCSBD);
                            }
                            Console.WriteLine("-------------------");
                            Console.WriteLine("msb checkpoint : {0}", msb.CSB_Checkpoint);
                            make_csb = true;
                        }

                        try
                        {
                            if (input.Equals("1"))
                            {
                                try
                                {
                                    init_APFS(fs, msb);
                                }
                                catch (Exception e)
                                {
                                    Console.WriteLine("This APFS Cannot Recover... :");
                                    Console.WriteLine(e);
                                    return;
                                }
                            }
                            else if (input.Equals("2"))
                            {
                                int chk, idx;

                                Console.WriteLine("\n\nPlease select the checkpoint you want to go back to.");
                                Console.WriteLine("(The larger the checkpoint, the more recent checkpoint.)");
                                Console.Write("Checkpoint : ");
                                for (int i = 0; i < csb_list.Count; i++)
                                {
                                    Console.Write("{0}  ", csb_list[i].CSB_Checkpoint);
                                }
                                Console.Write("\n Deleted Checkpoint : ");
                                for (int i = 0; i < deleted_csb_list.Count; i++)
                                {
                                    Console.Write("{0}  ", deleted_csb_list[i].CSB_Checkpoint);
                                }
                                Console.WriteLine("");
                                string s_chk = Console.ReadLine();
                                chk = Convert.ToInt32(s_chk);
                                if (chk >= (int)csb_list[0].CSB_Checkpoint && chk <= (int)msb.CSB_Checkpoint)
                                {
                                    idx = chk - (int)msb.CSB_Checkpoint + csb_list.Count - 1;
                                    init_APFS(fs, csb_list[idx]);
                                }
                                else if (chk >= (int)deleted_csb_list[0].CSB_Checkpoint && chk <= (int)deleted_csb_list[deleted_csb_list.Count - 1].CSB_Checkpoint)
                                {
                                    idx = chk - (int)deleted_csb_list[deleted_csb_list.Count - 1].CSB_Checkpoint + deleted_csb_list.Count - 1;
                                    init_APFS(fs, deleted_csb_list[idx]);
                                }
                                else
                                {
                                    Console.WriteLine("Invalid Checkpoint Number");
                                }
                            }
                            else if (input.Equals("3"))
                            {
                                bool   find      = false;
                                String to_search = "";
                                Console.WriteLine("Enter the name of the Folder you want to restore : ");
                                to_search = Console.ReadLine();
                                for (int i = csb_list.Count - 1; i >= 0; i--)
                                {
                                    CSB c = csb_list[i];
                                    Console.WriteLine("=========Chckpoint : {0}", c.CSB_Checkpoint);
                                    if (restore_folder(fs, c, to_search))
                                    {
                                        find = true;
                                        break;
                                    }
                                }

                                if (!find)
                                {
                                    for (int i = deleted_csb_list.Count - 1; i >= 0; i--)
                                    {
                                        Console.WriteLine("=========deleted Chckpoint : {0}", deleted_csb_list[i].CSB_Checkpoint);
                                        if (restore_folder(fs, deleted_csb_list[i], to_search))
                                        {
                                            find = true;
                                            break;
                                        }
                                    }
                                }
                            }
                            else if (input.Equals("4"))
                            {
                                bool   find      = false;
                                String to_search = "";
                                Console.WriteLine("Enter the name of the file you want to restore : ");
                                to_search = Console.ReadLine();
                                for (int i = csb_list.Count - 1; i >= 0; i--)
                                {
                                    Console.WriteLine("=========Chckpoint : {0}", csb_list[i].CSB_Checkpoint);
                                    if (restore_file(fs, csb_list[i], to_search))
                                    {
                                        find = true;
                                        break;
                                    }
                                }
                                if (!find)
                                {
                                    for (int i = deleted_csb_list.Count - 1; i >= 0; i--)
                                    {
                                        Console.WriteLine("=========Chckpoint : {0}", deleted_csb_list[i].CSB_Checkpoint);

                                        if (restore_file(fs, deleted_csb_list[i], to_search))
                                        {
                                            find = true;
                                            break;
                                        }
                                    }
                                }
                            }
                            else if (input.Equals("5"))
                            {
                                return;
                            }
                            else
                            {
                                Console.WriteLine("Invalid Input");
                            }
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine(e.Message);
                        }
                    }
                }
            }
            catch (UnauthorizedAccessException)
            {
                Console.WriteLine("Cannot Access dmg file");
                return;
            }
            catch (FileNotFoundException)
            {
                Console.WriteLine("Cannot Find File...");
            }
        }