Specifies the parameters for a file search.
예제 #1
0
        public FileSystemEnumerator(String path, String originalUserPath, String searchPattern, SearchOption searchOption, SearchResultHandler <TSource> resultHandler)
        {
            Contract.Requires(path != null);
            Contract.Requires(originalUserPath != null);
            Contract.Requires(searchPattern != null);
            Contract.Requires(searchOption == SearchOption.AllDirectories || searchOption == SearchOption.TopDirectoryOnly);
            Contract.Requires(resultHandler != null);

            oldMode = Win32Api.SetErrorMode(Win32Api.FailCriticalErrors);

            searchStack = new List <SearchData>();

            String normalizedSearchPattern = NormalizeSearchPattern(searchPattern);

            if (normalizedSearchPattern.Length == 0)
            {
                isEmpty = true;
            }
            else
            {
                this.resultHandler = resultHandler;
                this.searchOption  = searchOption;

                fullPath = PathHelperMethods.GetFullPathInternal(path);
                String fullSearchString = GetFullSearchString(fullPath, normalizedSearchPattern);
                normalizedSearchPath = Path.GetDirectoryName(fullSearchString);

                // permission demands
                var demandPaths = new String[2];
                // Any illegal chars such as *, ? will be caught by FileIOPermission.HasIllegalCharacters
                demandPaths[0] = GetDemandDir(fullPath, true);
                // For filters like foo\*.cs we need to verify if the directory foo is not denied access.
                // Do a demand on the combined path so that we can fail early in case of deny
                demandPaths[1] = GetDemandDir(normalizedSearchPath, true);
                new FileIOPermission(FileIOPermissionAccess.PathDiscovery, demandPaths).Demand();

                // normalize search criteria
                searchCriteria = GetNormalizedSearchCriteria(fullSearchString, normalizedSearchPath);

                // fix up user path
                String searchPatternDirName = Path.GetDirectoryName(normalizedSearchPattern);
                String userPathTemp         = originalUserPath;
                if (searchPatternDirName != null && searchPatternDirName.Length != 0)
                {
                    userPathTemp = Path.Combine(userPathTemp, searchPatternDirName);
                }
                userPath = userPathTemp;

                searchData = new SearchData(normalizedSearchPath, userPath, searchOption);

                CommonInit();
            }
        }
예제 #2
0
        [SecurityCritical] // auto-generated
        void AddSearchableDirsToStack(SearchData localSearchData)
        {
            Contract.Requires(localSearchData != null);

            String         searchPath = localSearchData.fullPath + "*";
            SafeFindHandle hnd        = null;
            var            data       = new FindData();

            try
            {
                // Get all files and dirs
                hnd = Win32Api.IO.FindFirstFile(searchPath, data);

                if (hnd.IsInvalid)
                {
                    int hr = Marshal.GetLastWin32Error();

                    // This could happen if the dir doesn't contain any files.
                    // Continue with the recursive search though, eventually
                    // searchStack will become empty
                    if (hr == Win32Error.ERROR_ACCESS_DENIED || hr == Win32Error.ERROR_FILE_NOT_FOUND || hr == Win32Error.ERROR_NO_MORE_FILES || hr == Win32Error.ERROR_PATH_NOT_FOUND)
                    {
                        return;
                    }

                    HandleError(hr, localSearchData.fullPath);
                }

                // Add subdirs to searchStack. Exempt ReparsePoints as appropriate
                int incr = 0;
                do
                {
                    if (data.IsDir)
                    {
                        // FullPath
                        var pathBuffer = new StringBuilder(localSearchData.fullPath);
                        pathBuffer.Append(data.FileName);
                        String tempFullPath = pathBuffer.ToString();

                        // UserPath
                        pathBuffer.Length = 0;
                        pathBuffer.Append(localSearchData.userPath);
                        pathBuffer.Append(data.FileName);

                        SearchOption option = localSearchData.searchOptions;

#if EXCLUDE_REPARSEPOINTS
                        // Traverse reparse points depending on the searchoption specified
                        if ((searchDataSubDir.searchOption == SearchOption.AllDirectories) && (0 != (data.dwFileAttributes & Win32Native.FILE_ATTRIBUTE_REPARSE_POINT)))
                        {
                            option = SearchOption.TopDirectoryOnly;
                        }
#endif
                        // Setup search data for the sub directory and push it into the stack
                        var searchDataSubDir = new SearchData(tempFullPath, pathBuffer.ToString(), option);

                        searchStack.Insert(incr++, searchDataSubDir);
                    }
                } while(Win32Api.IO.FindNextFile(hnd, data));
                // We don't care about errors here
            }
            finally
            {
                if (hnd != null)
                {
                    hnd.Dispose();
                }
            }
        }
예제 #3
0
        public override bool MoveNext()
        {
            var data = new FindData();

            switch (state)
            {
            case stateInit:
            {
                if (isEmpty)
                {
                    state = stateFinish;
                    goto case stateFinish;
                }
                if (searchData.searchOptions == SearchOption.TopDirectoryOnly)
                {
                    state = stateFindNextFile;
                    if (current != null)
                    {
                        return(true);
                    }
                    goto case stateFindNextFile;
                }
                state = stateSearchNextDir;
                goto case stateSearchNextDir;
            }

            case stateSearchNextDir:
            {
                Contract.Assert(searchData.searchOptions != SearchOption.TopDirectoryOnly, "should not reach this code path if searchOption == TopDirectoryOnly");
                // Traverse directory structure. We need to get '*'
                while (searchStack.Count > 0)
                {
                    searchData = searchStack[0];
                    Contract.Assert((searchData.fullPath != null), "fullpath can't be null!");
                    searchStack.RemoveAt(0);

                    // Traverse the subdirs
                    AddSearchableDirsToStack(searchData);

                    // Execute searchCriteria against the current directory
                    String searchPath = searchData.fullPath + searchCriteria;

                    // Open a Find handle
                    safeFindHandle = Win32Api.IO.FindFirstFile(searchPath, data);
                    if (safeFindHandle.IsInvalid)
                    {
                        int hr = Marshal.GetLastWin32Error();
                        if (hr == Win32Error.ERROR_ACCESS_DENIED || hr == Win32Error.ERROR_FILE_NOT_FOUND || hr == Win32Error.ERROR_NO_MORE_FILES || hr == Win32Error.ERROR_PATH_NOT_FOUND)
                        {
                            continue;
                        }

                        safeFindHandle.Dispose();
                        HandleError(hr, searchData.fullPath);
                    }

                    state = stateFindNextFile;
                    needsParentPathDiscoveryDemand = true;
                    SearchResult searchResult = CreateSearchResult(searchData, data);
                    if (resultHandler.IsResultIncluded(searchResult))
                    {
                        if (needsParentPathDiscoveryDemand)
                        {
                            DoDemand(searchData.fullPath);
                            needsParentPathDiscoveryDemand = false;
                        }
                        current = resultHandler.CreateObject(searchResult);
                        return(true);
                    }
                    goto case stateFindNextFile;
                }
                state = stateFinish;
                goto case stateFinish;
            }

            case stateFindNextFile:
            {
                if (searchData != null && safeFindHandle != null)
                {
                    // Keep asking for more matching files/dirs, add it to the list
                    while (Win32Api.IO.FindNextFile(safeFindHandle, data))
                    {
                        SearchResult searchResult = CreateSearchResult(searchData, data);
                        if (resultHandler.IsResultIncluded(searchResult))
                        {
                            if (needsParentPathDiscoveryDemand)
                            {
                                DoDemand(searchData.fullPath);
                                needsParentPathDiscoveryDemand = false;
                            }
                            current = resultHandler.CreateObject(searchResult);
                            return(true);
                        }
                    }

                    // Make sure we quit with a sensible error.
                    int hr = Marshal.GetLastWin32Error();

                    if (safeFindHandle != null)
                    {
                        safeFindHandle.Dispose();
                    }

                    // ERROR_FILE_NOT_FOUND is valid here because if the top level
                    // dir doen't contain any subdirs and matching files then
                    // we will get here with this errorcode from the searchStack walk
                    if ((hr != 0) && (hr != Win32Error.ERROR_NO_MORE_FILES) &&
                        (hr != Win32Error.ERROR_FILE_NOT_FOUND))
                    {
                        HandleError(hr, searchData.fullPath);
                    }
                }
                if (searchData.searchOptions == SearchOption.TopDirectoryOnly)
                {
                    state = stateFinish;
                    goto case stateFinish;
                }
                state = stateSearchNextDir;
                goto case stateSearchNextDir;
            }

            case stateFinish:
            {
                Dispose();
                break;
            }
            }
            return(false);
        }