예제 #1
0
        /// <summary>
        /// Ensures the specified directory exists
        /// </summary>
        /// <param name="directory">The directory.</param>
        public void CreateDirectory(string directory)
        {
            if (string.IsNullOrEmpty(directory))
            {
                throw new ArgumentNullException("directory");
            }

            directory = Path.GetFullPath(QQnPath.Combine(_directory, directory));             // Gets directory with separator

            if (!directory.StartsWith(_directory))
            {
                throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "Directory {0} is not below root", directory), "directory");
            }

            if (Directory.Exists(directory))
            {
                return;
            }

            CreateDirectory(QQnPath.GetParentDirectory(directory));
            Directory.CreateDirectory(directory);

            DirectoryMapDirectory item = DoGetDirectory(QQnPath.GetRelativePath(directory, _directory));

            using (item.Updater())
            {
                item.Created = true;
            }
        }
예제 #2
0
        /// <summary>
        /// Initializes a new instance of the <see cref="DirectoryMap"/> class.
        /// </summary>
        /// <param name="dirInfo">The dir info.</param>
        protected DirectoryMap(DirectoryInfo dirInfo)
        {
            if (dirInfo == null)
            {
                throw new ArgumentNullException("dirInfo");
            }
            else if (!dirInfo.Exists)
            {
                throw new DirectoryNotFoundException("Directory does not exist");
            }

            //_dirInfo = dirInfo;
            _directory = dirInfo.FullName;

            string mapFile = QQnPath.Combine(dirInfo.FullName, DirectoryMapData.DirMapFile);

            DirectoryMapData mapData = null;

            if (File.Exists(mapFile))
            {
                mapData = DirectoryMapData.Load(dirInfo.FullName);
            }

            _data = mapData ?? new DirectoryMapData(dirInfo.FullName);
        }
예제 #3
0
        public static DirectoryMapData Load(string path)
        {
            if (string.IsNullOrEmpty(path))
            {
                throw new ArgumentNullException("path");
            }

            path = Path.GetFullPath(path);

            using (FileStream fs = File.OpenRead(QQnPath.Combine(path, DirMapFile)))
            {
                XPathDocument doc = new XPathDocument(fs);

                XPathNavigator nav = doc.CreateNavigator();
                nav.MoveToRoot();
                nav.MoveToFirstChild();

                DirectoryMapData data;
                TokenizerArgs    ta = new TokenizerArgs();
                ta.SkipUnknownNamedItems = true;
                if (Tokenizer.TryParseXml(nav, ta, out data))
                {
                    data._directory = path;
                    return(data);
                }
            }
            return(null);
        }
예제 #4
0
        /// <summary>
        /// Verifies the file.
        /// </summary>
        /// <param name="baseDirectory">The base directory.</param>
        /// <param name="verifyData">The verify data.</param>
        /// <param name="verificationMode">The verification mode.</param>
        /// <returns></returns>
        public static bool VerifyFile(string baseDirectory, IVerifiableFile verifyData, VerifyMode verificationMode)
        {
            if (string.IsNullOrEmpty(baseDirectory))
            {
                throw new ArgumentNullException("baseDirectory");
            }
            else if (verifyData == null)
            {
                throw new ArgumentNullException("verifyData");
            }

            string path = QQnPath.Combine(baseDirectory, verifyData.Filename);

            FileInfo fif = new FileInfo(path);

            if (!fif.Exists)
            {
                return(false);
            }

            if (verificationMode < VerifyMode.Time)
            {
                return(true);
            }

            bool hasTime    = verifyData.LastWriteTimeUtc.HasValue;
            bool timeFailed = hasTime && fif.LastWriteTimeUtc != verifyData.LastWriteTimeUtc.Value;

            if (timeFailed && verificationMode == VerifyMode.Time)
            {
                return(false);
            }

            if (verificationMode < VerifyMode.TimeSize)
            {
                return(true);
            }

            bool hasSize    = (verifyData.FileSize >= 0);
            bool sizeFailed = hasSize && fif.Length != verifyData.FileSize;

            if ((timeFailed || sizeFailed) && verificationMode == VerifyMode.TimeSize)
            {
                return(false);
            }

            if (verificationMode < VerifyMode.FileHash)
            {
                return(true);
            }

            if (!string.IsNullOrEmpty(verifyData.FileHash) && !QQnCryptoHelpers.VerifyFileHash(fif.FullName, verifyData.FileHash))
            {
                return(false);
            }

            return(true);
        }
예제 #5
0
        /// <summary>
        /// Checks if a DirMap exists for the specified path
        /// </summary>
        /// <param name="path">The path.</param>
        /// <returns></returns>
        public static bool Exists(string path)
        {
            if (string.IsNullOrEmpty(path))
            {
                throw new ArgumentNullException("path");
            }

            path = Path.GetFullPath(path);

            return(Directory.Exists(path) && File.Exists(QQnPath.Combine(path, ".tDirMap")));
        }
예제 #6
0
        /// <summary>
        /// Creates the file.
        /// </summary>
        /// <param name="path">The path.</param>
        /// <param name="fileMode">The file mode.</param>
        /// <param name="hash">The hash.</param>
        /// <param name="size">The size.</param>
        /// <param name="allowExternal">if set to <c>true</c> [allow external].</param>
        /// <returns></returns>
        public Stream OpenFile(string path, FileMode fileMode, string hash, long size, bool allowExternal)
        {
            if (string.IsNullOrEmpty(path))
            {
                throw new ArgumentNullException("path");
            }

            string fullPath = QQnPath.CombineFullPath(_directory, path);

            path = QQnPath.MakeRelativePath(_directory, fullPath);

            switch (fileMode)
            {
            case FileMode.CreateNew:
            case FileMode.Create:
                if (!allowExternal && File.Exists(fullPath))
                {
                    throw new IOException(string.Format(CultureInfo.InvariantCulture, "Unmanaged file {0} exists", path));
                }
                break;

            case FileMode.Open:
            case FileMode.Truncate:
                if (!_data.Files.Contains(path) && (!allowExternal || !File.Exists(path)))
                {
                    throw new IOException("File does not exist");
                }
                break;

            default:
                throw new ArgumentException("The specified mode is not supported");
            }

            if (size < 0)
            {
                size = -1;
            }

            CreateDirectory(Path.GetDirectoryName(fullPath));

            DirectoryMapFile file = DoGetFile(path);

            if (file.ToBeDeleted && (fileMode == FileMode.Create || fileMode == FileMode.CreateNew))
            {
                file.ToBeDeleted = false;
            }

            return(new DirectoryMapStream(File.Open(fullPath, fileMode), file, fileMode, hash, string.IsNullOrEmpty(hash) ? -1 : size, _data.HashType));
        }
예제 #7
0
        /// <summary>
        /// Unschedules the delete.
        /// </summary>
        /// <param name="path">The path.</param>
        public void UnscheduleDelete(string path)
        {
            if (string.IsNullOrEmpty(path))
            {
                throw new ArgumentNullException("path");
            }

            path = QQnPath.EnsureRelativePath(_directory, path);

            if (!_data.Files.Contains(path))
            {
                return;                 // Not in DirectoryMap
            }
            DirectoryMapFile file = DoGetFile(path);

            file.ToBeDeleted = false;
        }
예제 #8
0
        /// <summary>
        /// Initializes a new instance of the <see cref="SeekableStream"/> class.
        /// </summary>
        /// <param name="innerStream">The inner stream.</param>
        /// <param name="length">The length.</param>
        public SeekableStream(Stream innerStream, long length)
        {
            if (innerStream == null)
            {
                throw new ArgumentNullException("innerStream");
            }

            _parentStream = innerStream;
            if (innerStream.CanSeek)
            {
                _innerStream = innerStream;
                _length      = innerStream.Length;
            }
            else
            {
                length = _length;
                if (length >= 0 && length < (1024 * 1024))                 // Less than 1 MB, use memory
                {
                    byte[] buffer = new byte[length];
                    innerStream.Read(buffer, 0, buffer.Length);
                    innerStream.Close();
                    _innerStream          = new MemoryStream(buffer, false);
                    _innerStream.Position = 0;
                }
                else
                {
                    FileStream tempStream = new DeleteOnCloseStream(true);
                    try
                    {
                        // For now, just read the file at once; we should optimize this to read when needed
                        QQnPath.CopyStream(innerStream, tempStream);
                        tempStream.Position = 0;

                        _innerStream = tempStream;
                    }
                    finally
                    {
                        if (_innerStream != tempStream)
                        {
                            tempStream.Close();
                        }
                    }
                }
            }
        }
예제 #9
0
        public void Write()
        {
            string   file = QQnPath.Combine(_directory, DirMapFile);
            FileInfo fif  = new FileInfo(file);

            if (fif.Exists && (fif.Attributes & (FileAttributes.Hidden | FileAttributes.ReadOnly)) != 0)
            {
                // The hidden flag is threated for some read-only like flag by .Net, so we must reset it
                fif.Attributes = FileAttributes.Normal;
            }

            using (FileStream fs = File.Create(file))
                using (XmlWriter xw = XmlWriter.Create(fs))
                {
                    xw.WriteStartDocument();
                    xw.WriteStartElement("DirectoryMap", DirMapNs);

                    Tokenizer.TryWriteXml(xw, this);
                }
            File.SetAttributes(file, FileAttributes.Normal | FileAttributes.Hidden);
        }
예제 #10
0
        /// <summary>
        /// Deletes the specified file if it is within the DirectoryMap
        /// </summary>
        /// <param name="path"></param>
        public void DeleteFile(string path)
        {
            if (string.IsNullOrEmpty(path))
            {
                throw new ArgumentNullException("path");
            }

            path = QQnPath.EnsureRelativePath(_directory, path);

            if (!_data.Files.Contains(path))
            {
                return;                 // Not in DirectoryMap
            }
            DirectoryMapFile file = DoGetFile(path);

            if (file.Exists)
            {
                File.Delete(file.FullName);
            }

            _data.Files.Remove(path);
        }
예제 #11
0
        /// <summary>
        /// Adds the file.
        /// </summary>
        /// <param name="path">The path.</param>
        /// <returns></returns>
        public DirectoryMapFile AddFile(string path)
        {
            if (string.IsNullOrEmpty(path))
            {
                throw new ArgumentNullException("path");
            }

            string fullPath = QQnPath.Combine(_directory, path);

            path = QQnPath.MakeRelativePath(_directory, fullPath);

            if (_data.Files.Contains(path) || File.Exists(fullPath))
            {
                DirectoryMapFile dmf = DoGetFile(path);
                dmf.ToBeDeleted = false;

                return(dmf);
            }
            else
            {
                throw new FileNotFoundException("File not found", fullPath);
            }
        }
예제 #12
0
        /// <summary>
        /// Gets the file.
        /// </summary>
        /// <param name="path">The path.</param>
        /// <param name="addExistingFile">if set to <c>true</c> [add existing file].</param>
        /// <returns></returns>
        public DirectoryMapFile GetFile(string path, bool addExistingFile)
        {
            if (string.IsNullOrEmpty(path))
            {
                throw new ArgumentNullException("path");
            }

            string fullPath = QQnPath.Combine(_directory, path);

            path = QQnPath.MakeRelativePath(_directory, fullPath);

            if (_data.Files.Contains(path))
            {
                return(DoGetFile(path));
            }
            else if (addExistingFile && File.Exists(fullPath))
            {
                return(AddFile(path));
            }
            else
            {
                return(null);
            }
        }
예제 #13
0
        /// <summary>
        /// Updates the file.
        /// </summary>
        /// <param name="baseDirectory">The base directory.</param>
        /// <param name="verifyData">The verify data.</param>
        /// <param name="hashType">Type of the hash.</param>
        public static void UpdateFile(string baseDirectory, IUpdatableVerifiableFile verifyData, HashType hashType)
        {
            if (string.IsNullOrEmpty(baseDirectory))
            {
                throw new ArgumentNullException("baseDirectory");
            }
            else if (verifyData == null)
            {
                throw new ArgumentNullException("verifyData");
            }

            FileInfo fif = new FileInfo(QQnPath.Combine(baseDirectory, verifyData.Filename));

            if (!fif.Exists)
            {
                return;
            }

            long     size = fif.Length;
            string   hash = QQnCryptoHelpers.CalculateFileHash(fif.FullName, hashType);
            DateTime dt   = fif.LastWriteTimeUtc;

            verifyData.UpdateVerifyData(hash, size, dt);
        }