Skip to content

Commit

Permalink
allow a backupfs with fully qualified windows volumes.
Browse files Browse the repository at this point in the history
  • Loading branch information
john-behm-bertelsmann committed Jan 25, 2023
1 parent 51de5ce commit b0e148e
Showing 1 changed file with 28 additions and 4 deletions.
32 changes: 28 additions & 4 deletions backupfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ var (
// File is implemented by the imported directory.
type File = afero.File

// New creates a new layered backup file system that backups files from fs to backup in case that an
// NewBackupFs creates a new layered backup file system that backups files from fs to backup in case that an
// existing file in fs is about to be overwritten or removed.
func NewBackupFs(base, backup afero.Fs) *BackupFs {
return &BackupFs{
Expand All @@ -58,6 +58,25 @@ func NewBackupFs(base, backup afero.Fs) *BackupFs {
}
}

// NewBackupFsWithVolume creates a new layered backup file system that backups files from fs to backup in case that an
// existing file in fs is about to be overwritten or removed.
// Contrary to the normal backupfs this variant allows to use absolute windows paths (C:\A\B\C instead of \A\B\C)
func NewBackupFsWithVolume(base, backup afero.Fs) *BackupFs {
return &BackupFs{
base: base,
backup: backup,
windowsVolumePaths: true,

// this map is needed in order to keep track of non existing files
// consecutive changes might lead to files being backed up
// that were never there before
// but could have been written by us in the mean time.
// without this structure we would never know whether there was actually
// no previous file to be backed up.
baseInfos: make(map[string]os.FileInfo),
}
}

// BackupFs is a file system abstraction that takes two underlying filesystems.
// One filesystem that is is being used to read and write files and a second filesystem
// which is used as backup target in case that a file of the base filesystem is about to be
Expand All @@ -74,6 +93,10 @@ type BackupFs struct {
// it is not nil in case that the file existed on the base file system
baseInfos map[string]os.FileInfo
mu sync.Mutex

// windowsVolumePaths can be set to true in order to allow fully
// qualified windows paths (including volume names C:\A\B\C instead of \A\B\C)
windowsVolumePaths bool
}

// GetBaseFs returns the fs layer that is being written to
Expand Down Expand Up @@ -322,7 +345,8 @@ func (fs *BackupFs) UnmarshalJSON(data []byte) error {

// returns the cleaned path
func (fs *BackupFs) realPath(name string) (path string, err error) {
if runtime.GOOS == "windows" && filepath.IsAbs(name) {
// check path for being an absolute windows path
if !fs.windowsVolumePaths && runtime.GOOS == "windows" && filepath.IsAbs(name) {
// On Windows a common mistake would be to provide an absolute OS path
// We could strip out the base part, but that would not be very portable.

Expand Down Expand Up @@ -873,7 +897,7 @@ func (fs *BackupFs) Chown(name string, uid, gid int) error {
return nil
}

//Chtimes changes the access and modification times of the named file
// Chtimes changes the access and modification times of the named file
func (fs *BackupFs) Chtimes(name string, atime, mtime time.Time) error {
name, err := fs.realPath(name)
if err != nil {
Expand Down Expand Up @@ -970,7 +994,7 @@ func (fs *BackupFs) trackedLstat(name string) (os.FileInfo, bool, error) {
return fi, lstatCalled, nil
}

//SymlinkIfPossible changes the access and modification times of the named file
// SymlinkIfPossible changes the access and modification times of the named file
func (fs *BackupFs) SymlinkIfPossible(oldname, newname string) error {
oldname, err := fs.realPath(oldname)
if err != nil {
Expand Down

0 comments on commit b0e148e

Please sign in to comment.