| 407 | } |
| 408 | |
| 409 | func startWalker(dir string, res chan<- fileInfo, abort <-chan struct{}) chan error { |
| 410 | walker := func(path string, info os.FileInfo, err error) error { |
| 411 | if err != nil { |
| 412 | return err |
| 413 | } |
| 414 | |
| 415 | rn, _ := filepath.Rel(dir, path) |
| 416 | if rn == "." || rn == ".stfolder" { |
| 417 | return nil |
| 418 | } |
| 419 | if rn == ".stversions" { |
| 420 | return filepath.SkipDir |
| 421 | } |
| 422 | |
| 423 | var f fileInfo |
| 424 | if info.Mode()&os.ModeSymlink != 0 { |
| 425 | f = fileInfo{ |
| 426 | name: rn, |
| 427 | mode: os.ModeSymlink, |
| 428 | } |
| 429 | |
| 430 | tgt, err := os.Readlink(path) |
| 431 | if err != nil { |
| 432 | return err |
| 433 | } |
| 434 | f.hash = sha256.Sum256([]byte(tgt)) |
| 435 | } else if info.IsDir() { |
| 436 | f = fileInfo{ |
| 437 | name: rn, |
| 438 | mode: info.Mode(), |
| 439 | // hash and modtime zero for directories |
| 440 | } |
| 441 | } else { |
| 442 | f = fileInfo{ |
| 443 | name: rn, |
| 444 | mode: info.Mode(), |
| 445 | // comparing timestamps with better precision than a second |
| 446 | // is problematic as there is rounding and truncation going |
| 447 | // on at every level |
| 448 | mod: info.ModTime().Unix(), |
| 449 | size: info.Size(), |
| 450 | } |
| 451 | sum, err := sha256file(path) |
| 452 | if err != nil { |
| 453 | return err |
| 454 | } |
| 455 | f.hash = sum |
| 456 | } |
| 457 | |
| 458 | select { |
| 459 | case res <- f: |
| 460 | return nil |
| 461 | case <-abort: |
| 462 | return errors.New("abort") |
| 463 | } |
| 464 | } |
| 465 | |
| 466 | errc := make(chan error) |