mirror of
https://github.com/octoleo/restic.git
synced 2024-11-26 23:06:32 +00:00
Merge pull request #626 from rfjakob/master
Add "-x", "--one-file-system" option
This commit is contained in:
commit
0a9cbd47c7
@ -22,6 +22,7 @@ type CmdBackup struct {
|
|||||||
Parent string `short:"p" long:"parent" description:"use this parent snapshot (default: last snapshot in repo that has the same target)"`
|
Parent string `short:"p" long:"parent" description:"use this parent snapshot (default: last snapshot in repo that has the same target)"`
|
||||||
Force bool `short:"f" long:"force" description:"Force re-reading the target. Overrides the \"parent\" flag"`
|
Force bool `short:"f" long:"force" description:"Force re-reading the target. Overrides the \"parent\" flag"`
|
||||||
Excludes []string `short:"e" long:"exclude" description:"Exclude a pattern (can be specified multiple times)"`
|
Excludes []string `short:"e" long:"exclude" description:"Exclude a pattern (can be specified multiple times)"`
|
||||||
|
ExcludeOtherFS bool `short:"x" long:"one-file-system" description:"Exclude other file systems"`
|
||||||
ExcludeFile string `long:"exclude-file" description:"Read exclude-patterns from file"`
|
ExcludeFile string `long:"exclude-file" description:"Read exclude-patterns from file"`
|
||||||
Stdin bool `long:"stdin" description:"read backup data from stdin"`
|
Stdin bool `long:"stdin" description:"read backup data from stdin"`
|
||||||
StdinFilename string `long:"stdin-filename" default:"stdin" description:"file name to use when reading from stdin"`
|
StdinFilename string `long:"stdin-filename" default:"stdin" description:"file name to use when reading from stdin"`
|
||||||
@ -239,6 +240,27 @@ func filterExisting(items []string) (result []string, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// gatherDevices returns the set of unique device ids of the files and/or
|
||||||
|
// directory paths listed in "items".
|
||||||
|
func gatherDevices(items []string) (deviceMap map[uint64]struct{}, err error) {
|
||||||
|
deviceMap = make(map[uint64]struct{})
|
||||||
|
for _, item := range items {
|
||||||
|
fi, err := fs.Lstat(item)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
id, err := fs.DeviceID(fi)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
deviceMap[id] = struct{}{}
|
||||||
|
}
|
||||||
|
if len(deviceMap) == 0 {
|
||||||
|
return nil, errors.New("zero allowed devices")
|
||||||
|
}
|
||||||
|
return deviceMap, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (cmd CmdBackup) readFromStdin(args []string) error {
|
func (cmd CmdBackup) readFromStdin(args []string) error {
|
||||||
if len(args) != 0 {
|
if len(args) != 0 {
|
||||||
return errors.Fatalf("when reading from stdin, no additional files can be specified")
|
return errors.Fatalf("when reading from stdin, no additional files can be specified")
|
||||||
@ -291,6 +313,16 @@ func (cmd CmdBackup) Execute(args []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// allowed devices
|
||||||
|
var allowedDevs map[uint64]struct{}
|
||||||
|
if cmd.ExcludeOtherFS {
|
||||||
|
allowedDevs, err = gatherDevices(target)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
debug.Log("backup.Execute", "allowed devices: %v\n", allowedDevs)
|
||||||
|
}
|
||||||
|
|
||||||
repo, err := cmd.global.OpenRepository()
|
repo, err := cmd.global.OpenRepository()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -361,9 +393,26 @@ func (cmd CmdBackup) Execute(args []string) error {
|
|||||||
|
|
||||||
if matched {
|
if matched {
|
||||||
debug.Log("backup.Execute", "path %q excluded by a filter", item)
|
debug.Log("backup.Execute", "path %q excluded by a filter", item)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return !matched
|
if !cmd.ExcludeOtherFS {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
id, err := fs.DeviceID(fi)
|
||||||
|
if err != nil {
|
||||||
|
// This should never happen because gatherDevices() would have
|
||||||
|
// errored out earlier. If it still does that's a reason to panic.
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
_, found := allowedDevs[id]
|
||||||
|
if !found {
|
||||||
|
debug.Log("backup.Execute", "path %q on disallowed device %d", item, id)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
stat, err := archiver.Scan(target, selectFilter, cmd.newScanProgress())
|
stat, err := archiver.Scan(target, selectFilter, cmd.newScanProgress())
|
||||||
|
21
src/restic/fs/deviceid_unix.go
Normal file
21
src/restic/fs/deviceid_unix.go
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// +build !windows
|
||||||
|
|
||||||
|
package fs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"restic/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DeviceID extracts the device ID from an os.FileInfo object by casting it
|
||||||
|
// to syscall.Stat_t
|
||||||
|
func DeviceID(fi os.FileInfo) (deviceID uint64, err error) {
|
||||||
|
if st, ok := fi.Sys().(*syscall.Stat_t); ok {
|
||||||
|
// st.Dev is uint32 on Darwin and uint64 on Linux. Just cast
|
||||||
|
// everything to uint64.
|
||||||
|
return uint64(st.Dev), nil
|
||||||
|
}
|
||||||
|
return 0, errors.New("Could not cast to syscall.Stat_t")
|
||||||
|
}
|
15
src/restic/fs/deviceid_windows.go
Normal file
15
src/restic/fs/deviceid_windows.go
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// +build windows
|
||||||
|
|
||||||
|
package fs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"restic/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DeviceID extracts the device ID from an os.FileInfo object by casting it
|
||||||
|
// to syscall.Stat_t
|
||||||
|
func DeviceID(fi os.FileInfo) (deviceID uint64, err error) {
|
||||||
|
return 0, errors.New("Device IDs are not supported on Windows")
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user