func scanFileSystem(rootDirectoryName string, fsScanContext *fsrateio.ReaderContext, scanFilter *filter.Filter, checkScanDisableRequest func() bool, hasher Hasher, oldFS *FileSystem) ( *FileSystem, error) { var fileSystem FileSystem fileSystem.rootDirectoryName = rootDirectoryName fileSystem.fsScanContext = fsScanContext fileSystem.scanFilter = scanFilter fileSystem.checkScanDisableRequest = checkScanDisableRequest if hasher == nil { fileSystem.hasher = GetSimpleHasher(false) } else { fileSystem.hasher = hasher } var stat wsyscall.Stat_t if err := wsyscall.Lstat(rootDirectoryName, &stat); err != nil { return nil, err } fileSystem.InodeTable = make(filesystem.InodeTable) fileSystem.dev = stat.Dev fileSystem.inodeNumber = stat.Ino fileSystem.Mode = filesystem.FileMode(stat.Mode) fileSystem.Uid = stat.Uid fileSystem.Gid = stat.Gid fileSystem.DirectoryCount++ var tmpInode filesystem.RegularInode if sha512.New().Size() != len(tmpInode.Hash) { return nil, errors.New("incompatible hash size") } var oldDirectory *filesystem.DirectoryInode if oldFS != nil && oldFS.InodeTable != nil { oldDirectory = &oldFS.DirectoryInode } err, _ := scanDirectory(&fileSystem.FileSystem.DirectoryInode, oldDirectory, &fileSystem, oldFS, "/") oldFS = nil oldDirectory = nil if err != nil { return nil, err } fileSystem.ComputeTotalDataBytes() if err = fileSystem.RebuildInodePointers(); err != nil { panic(err) } return &fileSystem, nil }
func scanDirectory(directory, oldDirectory *filesystem.DirectoryInode, fileSystem, oldFS *FileSystem, myPathName string) (error, bool) { file, err := os.Open(path.Join(fileSystem.rootDirectoryName, myPathName)) if err != nil { return err, false } names, err := file.Readdirnames(-1) file.Close() if err != nil { return err, false } sort.Strings(names) entryList := make([]*filesystem.DirectoryEntry, 0, len(names)) var copiedDirents int for _, name := range names { if directory == &fileSystem.DirectoryInode && name == ".subd" { continue } filename := path.Join(myPathName, name) if fileSystem.scanFilter != nil && fileSystem.scanFilter.Match(filename) { continue } var stat wsyscall.Stat_t err := wsyscall.Lstat(path.Join(fileSystem.rootDirectoryName, filename), &stat) if err != nil { if err == syscall.ENOENT { continue } return err, false } if stat.Dev != fileSystem.dev { continue } if fileSystem.checkScanDisableRequest != nil && fileSystem.checkScanDisableRequest() { return errors.New("DisableScan"), false } myGC() dirent := new(filesystem.DirectoryEntry) dirent.Name = name dirent.InodeNumber = stat.Ino var oldDirent *filesystem.DirectoryEntry if oldDirectory != nil { index := len(entryList) if len(oldDirectory.EntryList) > index && oldDirectory.EntryList[index].Name == name { oldDirent = oldDirectory.EntryList[index] } } if stat.Mode&syscall.S_IFMT == syscall.S_IFDIR { err = addDirectory(dirent, oldDirent, fileSystem, oldFS, myPathName, &stat) } else if stat.Mode&syscall.S_IFMT == syscall.S_IFREG { err = addRegularFile(dirent, fileSystem, oldFS, myPathName, &stat) } else if stat.Mode&syscall.S_IFMT == syscall.S_IFLNK { err = addSymlink(dirent, fileSystem, oldFS, myPathName, &stat) } else if stat.Mode&syscall.S_IFMT == syscall.S_IFSOCK { continue } else { err = addSpecialFile(dirent, fileSystem, oldFS, &stat) } if err != nil { if err == syscall.ENOENT { continue } return err, false } if oldDirent != nil && *dirent == *oldDirent { dirent = oldDirent copiedDirents++ } entryList = append(entryList, dirent) } if oldDirectory != nil && len(entryList) == copiedDirents && len(entryList) == len(oldDirectory.EntryList) { directory.EntryList = oldDirectory.EntryList return nil, true } else { directory.EntryList = entryList return nil, false } }