| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- package main
- import (
- "fmt"
- "os"
- "path"
- "path/filepath"
- "strings"
- )
- const BlockSize = 128 * 1024
- type File struct {
- Name string
- Flags uint32
- Modified int64
- Blocks BlockList
- }
- func (f File) Dump() {
- fmt.Printf("%s\n", f.Name)
- for _, b := range f.Blocks {
- fmt.Printf(" %dB @ %d: %x\n", b.Length, b.Offset, b.Hash)
- }
- fmt.Println()
- }
- func (f File) Size() (bytes int) {
- for _, b := range f.Blocks {
- bytes += int(b.Length)
- }
- return
- }
- func isTempName(name string) bool {
- return strings.HasPrefix(path.Base(name), ".syncthing.")
- }
- func tempName(name string, modified int64) string {
- tdir := path.Dir(name)
- tname := fmt.Sprintf(".syncthing.%s.%d", path.Base(name), modified)
- return path.Join(tdir, tname)
- }
- func genWalker(base string, res *[]File, model *Model) filepath.WalkFunc {
- return func(p string, info os.FileInfo, err error) error {
- if err != nil {
- return err
- }
- if isTempName(p) {
- return nil
- }
- if info.Mode()&os.ModeType == 0 {
- rn, err := filepath.Rel(base, p)
- if err != nil {
- return err
- }
- fi, err := os.Stat(p)
- if err != nil {
- return err
- }
- modified := fi.ModTime().Unix()
- hf, ok := model.LocalFile(rn)
- if ok && hf.Modified == modified {
- // No change
- *res = append(*res, hf)
- } else {
- if opts.Debug.TraceFile {
- debugf("FILE: Hash %q", p)
- }
- fd, err := os.Open(p)
- if err != nil {
- return err
- }
- defer fd.Close()
- blocks, err := Blocks(fd, BlockSize)
- if err != nil {
- return err
- }
- f := File{
- Name: rn,
- Flags: uint32(info.Mode()),
- Modified: modified,
- Blocks: blocks,
- }
- *res = append(*res, f)
- }
- }
- return nil
- }
- }
- func Walk(dir string, model *Model, followSymlinks bool) []File {
- var files []File
- fn := genWalker(dir, &files, model)
- err := filepath.Walk(dir, fn)
- if err != nil {
- warnln(err)
- }
- if !opts.NoSymlinks {
- d, err := os.Open(dir)
- if err != nil {
- warnln(err)
- return files
- }
- fis, err := d.Readdir(-1)
- if err != nil {
- warnln(err)
- return files
- }
- d.Close()
- for _, fi := range fis {
- if fi.Mode()&os.ModeSymlink != 0 {
- err := filepath.Walk(path.Join(dir, fi.Name())+"/", fn)
- if err != nil {
- warnln(err)
- }
- }
- }
- }
- return files
- }
- func cleanTempFile(path string, info os.FileInfo, err error) error {
- if err != nil {
- return err
- }
- if info.Mode()&os.ModeType == 0 && isTempName(path) {
- if opts.Debug.TraceFile {
- debugf("FILE: Remove %q", path)
- }
- os.Remove(path)
- }
- return nil
- }
- func CleanTempFiles(dir string) {
- filepath.Walk(dir, cleanTempFile)
- }
|