--- /dev/null
+/*
+sgodup -- File deduplication utility
+Copyright (C) 2020 Sergey Matveev <stargrave@stargrave.org>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 3 of the License.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+package main
+
+import (
+ "io"
+ "log"
+ "os"
+ "path"
+ "syscall"
+)
+
+type FileInode struct {
+ Path string
+ Size int64
+ Dev uint64
+ Ino uint64
+}
+
+func walker(c chan FileInode, dirPath string) {
+ dirFd, err := os.Open(dirPath)
+ if err != nil {
+ log.Fatal(err)
+ }
+ for {
+ fis, err := dirFd.Readdir(1 << 10)
+ if err != nil {
+ if err == io.EOF {
+ break
+ }
+ log.Fatal(err)
+ }
+ for _, fi := range fis {
+ stat := fi.Sys().(*syscall.Stat_t)
+ if fi.Mode().IsRegular() {
+ c <- FileInode{
+ path.Join(dirPath, fi.Name()),
+ fi.Size(),
+ stat.Dev, stat.Ino,
+ }
+ } else if fi.IsDir() {
+ walker(c, path.Join(dirPath, fi.Name()))
+ }
+ }
+ }
+ if err = dirFd.Close(); err != nil {
+ log.Fatal(err)
+ }
+}
+
+func walk(dirPath string) chan FileInode {
+ c := make(chan FileInode, 1<<10)
+ go func() {
+ walker(c, dirPath)
+ close(c)
+ }()
+ return c
+}