root/lang/csharp/Tools/mdumpfs.cs

Revision 3582, 15.7 kB (checked in by mayuki, 13 months ago)

lang/csharp/Tools: import HashGen?, mdumpfs

  • Property svn:keywords set to Id
Line 
1/*
2 * mdumpfs.cs
3 * $CVSId: mdumpfs.cs,v 1.6 2004/01/13 13:56:20 Mayuki Sawatari Exp $
4 * $Id$
5 *
6 * Copyright (c) 2003 Mayuki Sawatari, All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE MISUZILLA.ORG ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29 
30using System;
31using System.IO;
32using System.Text;
33using System.Text.RegularExpressions;
34using System.Runtime.InteropServices;
35
36namespace Misuzilla.Tools.mdumpfs
37{
38        public class ComandLineInterface
39        {
40                private static Verbosity _verbosity = Verbosity.DirectoryOnly;
41                public static Int32
42                Main(String[] args)
43                {
44                        StartupInfo startup = new StartupInfo();
45                        startup.Error = new ErrorHandler(ErrorHandled);
46                        startup.DumpProgress = new DumpProgressHandler(DumpProgressHandled);
47
48                        if (args.Length < 2) {
49                                ShowUsage();
50                                Console.Error.WriteLine("�R�}���h���C�����s�����Ă��܂��B");
51                                return 1;
52                        }
53
54                        // command line params
55                        for (Int32 i = 2; i < args.Length; i++) {
56                                switch (args[i].ToLower()) {
57                                /*case "-e": case "/e":
58                                        if (i < args.Length - 1) {
59                                                reExclude = new Regex("("+Regex.Escape(args[i+1]).Replace(',', '|')+")");
60                                                i++;
61                                        }
62                                        break;*/
63                                case "-re": case "/re":
64                                        if (i < args.Length - 1) {
65                                                startup.Exclude = new Regex(args[i+1]);
66                                                i++;
67                                        }
68                                        break;
69                                case "-l": case "/l":
70                                        if (i < args.Length - 1) {
71                                                startup.PreviousDateLimit = Int32.Parse(args[i+1]);
72                                                i++;
73                                        }
74                                        break;
75                                case "-v": case "/v":
76                                        if (i < args.Length - 1) {
77                                                try {
78                                                        _verbosity = (Verbosity)Enum.Parse(typeof(Verbosity), args[i+1], true);
79                                                        i++;
80                                                } catch (System.ArgumentException) {
81                                                        _verbosity = Verbosity.Detail;
82                                                }
83                                        } else {
84                                                _verbosity = Verbosity.Detail;
85                                        }
86                                        break;
87                                case "-s": case "/s": case "-q": case "/q":
88                                        _verbosity = Verbosity.Silent;
89                                        break;
90                                case "-c": case "/c":
91                                        startup.CheckMode = true;
92                                        break;
93                                case "-?": case "/?": case "-h": case "--help":
94                                        ShowUsage();
95                                        return 0;
96                                default:
97                                        Console.Error.WriteLine("���m�̃R�}���h���C���I�v�V���� \"{0}\" �͖����������B", args[i]);
98                                        break;
99                                }
100                        }
101
102                        startup.SourceDirectory = Path.GetFullPath(args[0] + Path.DirectorySeparatorChar);
103                        startup.DestinationRootDirectory = Path.GetFullPath(args[1] + Path.DirectorySeparatorChar);
104
105                        if (_verbosity == Verbosity.Debug) {
106                                Console.WriteLine("srcDir:\t\t'{0}'\ndestRootDir:\t'{1}'\nbasename:\t'{2}'\nArg:\t\t'{3}'\n", startup.SourceDirectory, startup.DestinationRootDirectory, "", args[0]);
107                                Console.WriteLine("prevDir:\t'{0}'\ndestDir:\t'{1}'",
108                                        Dumper.GetPreviousSnap(startup.DestinationRootDirectory, startup.StartDate, startup.PreviousDateLimit),
109                                        startup.DestinationDirectory);
110                        }
111
112                        if (!FileUtility.IsNTFS(startup.DestinationRootDirectory)) {
113                                Console.Error.WriteLine("�G���[: �o�b�N�A�b�v���{�����[����TFS�łȂ��������܂���);
114                                return 1;
115                        } else if (Environment.OSVersion.Version < new Version("5.0") ||
116                                        Environment.OSVersion.Platform != PlatformID.Win32NT) {
117                                Console.Error.WriteLine("�G���[: ���̃\�t�g�E�F�A��Windows2000 �ȍ~��NT�x�[�X��Windows ��v�Ƃ��܂��B");
118                                return 1;
119                        }
120
121                        if (_verbosity == Verbosity.Silent)
122                                Console.SetOut(StreamWriter.Null);
123
124                        try {
125                                Console.WriteLine("Destination Directory: {0}", startup.DestinationDirectory);
126                                Dumper.Copy(startup);
127                        } catch (IOException ie) {
128                                Console.Error.WriteLine("�G���[: {0}", ie.Message);
129                                return 1;
130                        }
131
132                        return 0;
133                }
134               
135                public static void
136                ShowUsage()
137                {
138                        Console.Error.WriteLine("�f�B���N�g���̃X�i�b�v�V���b�g������܂��B");
139                        Console.Error.WriteLine("");
140                        Console.Error.WriteLine("mdumpfs �R�s�[���f�B���N�g�� �R�s�[���B���N�g�� [-v [0-5]|-s] [-re regex] [-l num]\n");
141                        Console.Error.WriteLine("�R�}���h���C���I�v�V����:");
142                        Console.Error.WriteLine("  -v [0-5]\t�R�s�[���̓n�[�h�����N�����t�@�C���������");
143                        Console.Error.WriteLine("          \t0: �o�͂��Ȃ�(-s�Ɠ���)�B");
144                        Console.Error.WriteLine("          \t1: ���������f�B���N�g�����̂ݕ\���B");
145                        Console.Error.WriteLine("          \t2: 1 �ɉ���t�@�C����(�h�b�g)�v�ŕ\������");
146                        Console.Error.WriteLine("          \t3: �t�@�C�����������");
147                        Console.Error.WriteLine("          \t4: �X�V���ꂽ�t�@�C���̂ݕ\������");
148                        Console.Error.WriteLine("          \t5: �S�Ă̏��������");
149                        Console.Error.WriteLine("          \t6: �f�o�b�O���������");
150                        Console.Error.WriteLine("  -s\t\t�W���o�͂֌��ʂ�͂�Ȃ��B");
151                        Console.Error.WriteLine("  -c\t\t�`�F�b�N�݂̂Ńo�b�N�A�b�v������B");
152                        Console.Error.WriteLine("  -re <regex>\t���K�\���Ƀ}�b�`�����B���N�g��/�t�@�C����ۊO�ɂ���");
153                        Console.Error.WriteLine("  -l <num>\t�O��X�i�b�v�V���b�g�������w�莞�A31��);
154                        Console.Error.WriteLine("");
155                        Console.Error.WriteLine("�O����31��)�̃X�i�b�v�V���b�g�Ɣ����X�V���ꂽ�t�@�C����s�[���܂��B");
156                        Console.Error.WriteLine("�X�V�������Ȃ��t�@�C���͑O��X�i�b�v�V���b�g�̃t�@�C���ւ̃n�[�h�����N�Ƃ��ĕۑ��������B\n");
157                }
158
159                public static void
160                ErrorHandled(String reason, String fileName, String srcBaseDir, String destBaseDir, String prevBaseDir)
161                {
162                        Console.Error.WriteLine("�G���[: {0}", reason);
163                }
164                public static void
165                DumpProgressHandled(Int32 action, String fileName, String srcBaseDir, String destBaseDir, String prevBaseDir)
166                {
167                        String srcFileName = Path.Combine(srcBaseDir, fileName);
168                        String destFileName = Path.Combine(destBaseDir, fileName);
169                        String prevFileName = Path.Combine(prevBaseDir, fileName);
170                       
171                        switch (action) {
172                        case 0: // found
173                                switch (_verbosity) {
174                                case Verbosity.UpdateOnly: break;
175                                case Verbosity.DirectoryAndFileCount:
176                                        Console.Write("\n{0}", srcBaseDir); break;
177                                default:
178                                        Console.WriteLine("{0}", srcBaseDir); break;
179                                }
180                                break;
181                        case 1: // hardlink
182                                switch (_verbosity) {
183                                case Verbosity.Detail:
184                                        Console.WriteLine("Hardlink: {0} -> {1}", prevFileName, destFileName); break;
185                                case Verbosity.FileName:
186                                        Console.WriteLine("{0}", prevFileName); break;
187                                case Verbosity.DirectoryAndFileCount:
188                                        Console.Write("."); break;
189                                }
190                                break;
191                        case 2: // copy
192                                switch (_verbosity) {
193                                case Verbosity.Detail:
194                                        Console.WriteLine("Copy: {0} -> {1}", srcFileName, destFileName); break;
195                                case Verbosity.FileName:
196                                case Verbosity.UpdateOnly:
197                                        Console.WriteLine("{0}", srcFileName); break;
198                                case Verbosity.DirectoryAndFileCount:
199                                        Console.Write("."); break;
200                                }
201                                break;
202                        }
203                }
204        }
205       
206        public enum
207        Verbosity
208        {
209                Silent = 0,
210                DirectoryOnly,
211                DirectoryAndFileCount,
212                FileName,
213                UpdateOnly,
214                Detail,
215                Debug,
216        }
217       
218        public delegate void DumpProgressHandler(Int32 action, String fileName, String srcBaseDir, String destBaseDir, String prevBaseDir);
219        public delegate void ErrorHandler(String reason, String fileName, String srcBaseDir, String destBaseDir, String prevBaseDir);
220        public class Dumper
221        {
222                private StartupInfo _startInfo;
223               
224                public Dumper(StartupInfo start)
225                {
226                        _startInfo = start;
227                }
228               
229                public static Boolean
230                Copy(StartupInfo start)
231                {
232                        return (new Dumper(start)).Copy();
233                }
234                public Boolean
235                Copy()
236                {
237                        return CopyInternal(_startInfo.SourceDirectory, _startInfo.DestinationDirectory, GetPreviousSnap());
238                }
239               
240                private Boolean
241                CopyInternal(String srcBaseDir, String destBaseDir, String prevBaseDir)
242                {
243                        FileInfo[] files;
244                        OnDumpProgress(0, "", srcBaseDir, destBaseDir, prevBaseDir);
245
246                        try {
247                                if (!_startInfo.CheckMode) Directory.CreateDirectory(destBaseDir);
248                                files = new DirectoryInfo(srcBaseDir).GetFiles();
249                        } catch (SystemException e) {
250                                OnError(e.Message, "", srcBaseDir, destBaseDir, prevBaseDir);
251                                return false;
252                        }
253                       
254                        // file
255                        foreach (FileInfo f in files) {
256                                // exclude
257                                if (_startInfo.Exclude != null && _startInfo.Exclude.IsMatch(f.Name)) continue;
258                               
259                                String srcFileName = Path.Combine(srcBaseDir, f.Name);
260                                String destFileName = Path.Combine(destBaseDir, f.Name);
261
262                                try {
263                                        String prevFileName = Path.Combine(prevBaseDir, f.Name);
264                                        if (prevBaseDir != "" &&
265                                                FileUtility.IsSameFile(prevFileName, srcFileName)) {
266                                                // hard link
267                                                if (!_startInfo.CheckMode) FileUtility.CreateHardLink(prevFileName, destFileName);
268                                                OnDumpProgress(1, f.Name, srcBaseDir, destBaseDir, prevBaseDir);
269                                        } else {
270                                                // copy
271                                                if (!_startInfo.CheckMode) File.Copy(srcFileName, destFileName, true);
272                                                OnDumpProgress(2, f.Name, srcBaseDir, destBaseDir, prevBaseDir);
273                                        }
274                                } catch (UnauthorizedAccessException uae) {
275                                        OnError(uae.Message, f.Name, srcBaseDir, destBaseDir, prevBaseDir);
276                                        if (!_startInfo.IgnoreError) return false;
277                                } catch (IOException ie) {
278                                        OnError(ie.Message, f.Name, srcBaseDir, destBaseDir, prevBaseDir);
279                                        if (!_startInfo.IgnoreError) return false;
280                                }
281                        }
282                       
283                        // directory
284                        foreach (String dir in Directory.GetDirectories(srcBaseDir)) {
285                                String dirName = Path.GetFileName(dir);
286                                if (_startInfo.Exclude != null && _startInfo.Exclude.IsMatch(dir+Path.DirectorySeparatorChar)) continue;
287                               
288                                if (!CopyInternal(
289                                        Path.Combine(srcBaseDir, dirName + Path.DirectorySeparatorChar),
290                                        Path.Combine(destBaseDir, dirName + Path.DirectorySeparatorChar),
291                                        (prevBaseDir != "") ? Path.Combine(prevBaseDir, dirName) : ""
292                                )) return false;
293                        }
294                       
295                        return true;
296                }
297               
298                protected void
299                OnDumpProgress(Int32 action, String fileName, String srcBaseDir, String destBaseDir, String prevBaseDir)
300                {
301                        if (_startInfo.DumpProgress != null)
302                                _startInfo.DumpProgress(action, fileName, srcBaseDir, destBaseDir, prevBaseDir);
303                }
304                protected void
305                OnError(String reason, String fileName, String srcBaseDir, String destBaseDir, String prevBaseDir)
306                {
307                        if (_startInfo.Error != null)
308                                _startInfo.Error(reason, fileName, srcBaseDir, destBaseDir, prevBaseDir);
309                }
310               
311               
312                public String
313                GetPreviousSnap()
314                {
315                        String dirName = Path.GetFileName(_startInfo.SourceDirectory.TrimEnd(new Char[] {Path.DirectorySeparatorChar}));
316                        String prevDir = GetPreviousSnap(_startInfo.DestinationRootDirectory, _startInfo.StartDate, _startInfo.PreviousDateLimit);
317                        if (prevDir != "") prevDir = Path.Combine(prevDir, dirName);
318                        return prevDir;
319                }
320               
321                public static String
322                GetPreviousSnap(String destRootDir, DateTime baseDate, Int32 prevLimit)
323                {
324                        // -1��
325                        if (prevLimit < 1) throw new ArgumentException("�O��s������s���ł�");
326
327                        for (Int32 i = 0; i < prevLimit; i++) {
328                                DateTime prevDate = baseDate.AddDays(~i);
329                                String prevDir = Path.Combine(destRootDir, prevDate.ToString("yyyy") + Path.DirectorySeparatorChar + prevDate.ToString("MM") + Path.DirectorySeparatorChar + prevDate.ToString("dd"));
330                                //String prevDir = Path.Combine(destRootDir, prevDate.ToString("yyyyMMdd"));
331                                if (Directory.Exists(prevDir)) return prevDir;
332                        }
333                        return "";
334                }
335        }
336       
337        public class StartupInfo
338        {
339                private String _destDir;
340                private String _srcDir;
341                private DateTime _startDate = DateTime.Now;
342                private Int32 _prevDateLimit = 31;
343                private Regex _reExclude = null;
344                private Int64 _excludeSize = 0;
345                private Boolean _ignoreError = false;
346                private Boolean _checkMode = false;
347               
348                public ErrorHandler Error;
349                public DumpProgressHandler DumpProgress;
350               
351                public StartupInfo()
352                {
353                }
354                public StartupInfo(String srcBaseDir, String destBaseDir)
355                {
356                        _srcDir = srcBaseDir;
357                        _destDir = destBaseDir;
358                }
359               
360                public Boolean
361                CheckMode
362                {
363                        get { return _checkMode; }
364                        set { _checkMode = value; }
365                }
366                public Boolean
367                IgnoreError
368                {
369                        get { return _ignoreError; }
370                        set { _ignoreError = value; }
371                }
372                public Regex
373                Exclude
374                {
375                        get { return _reExclude; }
376                        set { _reExclude = value; }
377                }
378                public Int64
379                ExcludeSize
380                {
381                        get { return _excludeSize; }
382                        set { _excludeSize = value; }
383                }
384                public Int32
385                PreviousDateLimit
386                {
387                        get { return _prevDateLimit; }
388                        set { _prevDateLimit = value; }
389                }
390                public DateTime
391                StartDate
392                {
393                        get { return _startDate; }
394                        set { _startDate = value; }
395                }
396                public String
397                DestinationRootDirectory
398                {
399                        get { return _destDir; }
400                        set { _destDir = value; }
401                }
402                public String
403                DestinationDirectory
404                {
405                        get
406                        {
407                                String dirName = Path.GetFileName(_srcDir.TrimEnd(new Char[] {Path.DirectorySeparatorChar}));
408                                return Path.Combine(
409                                                Path.Combine(
410                                                        _destDir,
411                                                        DateTime.Now.ToString("yyyy") + Path.DirectorySeparatorChar +
412                                                        DateTime.Now.ToString("MM") + Path.DirectorySeparatorChar +
413                                                        DateTime.Now.ToString("dd")
414                                                ), dirName) + Path.DirectorySeparatorChar;
415                        }
416                }
417                public String
418                SourceDirectory
419                {
420                        get { return _srcDir; }
421                        set { _srcDir = value; }
422                }
423        }
424       
425       
426        internal class FileUtility
427        {
428                public static Boolean
429                IsSameFile(String file1, String file2)
430                {
431                        if (!File.Exists(file1) || !File.Exists(file2)) return false;
432                       
433                        FileInfo fi1 = new FileInfo(file1);
434                        FileInfo fi2 = new FileInfo(file2);
435                        return fi1.Length == fi2.Length && fi1.LastWriteTime == fi2.LastWriteTime;
436                }
437               
438                public static Boolean
439                IsNTFS(String rootPath)
440                {
441                        StringBuilder sb = new StringBuilder(255);
442                        GetVolumeInformation(Directory.GetDirectoryRoot(rootPath), IntPtr.Zero, 0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, sb, 255);
443
444                        return sb.ToString().CompareTo("NTFS") == 0;
445                }
446                public static void
447                CreateHardLink(String existingFileName, String newFileName)
448                {
449                        //if (!CreateHardLinkAPI(newFileName, existingFileName, IntPtr.Zero)) {
450                        //      throw new IOException("CreateHardLink API �����s���܂����B");
451                        //}
452                        CreateHardLinkAPI(newFileName, existingFileName, IntPtr.Zero);
453                }
454               
455                [DllImport("Kernel32.Dll", CharSet=CharSet.Unicode)]
456                private static extern Boolean
457                GetVolumeInformation(
458                        String lpRootPathName,
459                        IntPtr /*StringBulider*/ lpVolumeNameBuffer,
460                        Int32 nVolumeNameSize,
461                        /*ref*/ IntPtr lpVolumeSerialNumber,
462                        /*ref*/ IntPtr lpMaximumComponentLength,
463                        /*ref*/ IntPtr lpFileSystemFlags,
464                        StringBuilder lpFileSystemNameBuffer,
465                        Int32 nFileSystemNameSize
466                );
467               
468                [DllImport("Kernel32.Dll", CharSet=CharSet.Unicode, EntryPoint="CreateHardLink")]
469                private static extern Boolean
470                CreateHardLinkAPI(
471                        [MarshalAs(UnmanagedType.LPTStr)] String lpFileName,
472                        [MarshalAs(UnmanagedType.LPTStr)] String lpExistingFileName,
473                        IntPtr /* LPSECURITY_ATTRIBUTES */ lpSecurityAttributes
474                );
475        }
476}
Note: See TracBrowser for help on using the browser.