Add support for devices
Address code comments from previous commit Signed-off-by: Derek McGowan <derek@mcgstyle.net> (github: dmcgowan)
This commit is contained in:
parent
200cd6e877
commit
f78105d832
5 changed files with 28 additions and 9 deletions
21
fs/copy.go
21
fs/copy.go
|
@ -24,10 +24,12 @@ func copyDirectory(dst, src string, inodes map[uint64]string) error {
|
||||||
return errors.Errorf("source is not directory")
|
return errors.Errorf("source is not directory")
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := os.Stat(dst); err != nil {
|
if st, err := os.Stat(dst); err != nil {
|
||||||
if err := os.Mkdir(dst, stat.Mode()); err != nil {
|
if err := os.Mkdir(dst, stat.Mode()); err != nil {
|
||||||
return errors.Wrapf(err, "failed to mkdir %s", dst)
|
return errors.Wrapf(err, "failed to mkdir %s", dst)
|
||||||
}
|
}
|
||||||
|
} else if !st.IsDir() {
|
||||||
|
return errors.Errorf("cannot copy to non-directory: %s", dst)
|
||||||
} else {
|
} else {
|
||||||
if err := os.Chmod(dst, stat.Mode()); err != nil {
|
if err := os.Chmod(dst, stat.Mode()); err != nil {
|
||||||
return errors.Wrapf(err, "failed to chmod on %s", dst)
|
return errors.Wrapf(err, "failed to chmod on %s", dst)
|
||||||
|
@ -46,12 +48,14 @@ func copyDirectory(dst, src string, inodes map[uint64]string) error {
|
||||||
for _, fi := range fis {
|
for _, fi := range fis {
|
||||||
source := filepath.Join(src, fi.Name())
|
source := filepath.Join(src, fi.Name())
|
||||||
target := filepath.Join(dst, fi.Name())
|
target := filepath.Join(dst, fi.Name())
|
||||||
if fi.IsDir() {
|
|
||||||
|
switch {
|
||||||
|
case fi.IsDir():
|
||||||
if err := copyDirectory(target, source, inodes); err != nil {
|
if err := copyDirectory(target, source, inodes); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
} else if (fi.Mode() & os.ModeType) == 0 {
|
case (fi.Mode() & os.ModeType) == 0:
|
||||||
link, err := GetLinkSource(target, fi, inodes)
|
link, err := GetLinkSource(target, fi, inodes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "failed to get hardlink")
|
return errors.Wrap(err, "failed to get hardlink")
|
||||||
|
@ -63,7 +67,7 @@ func copyDirectory(dst, src string, inodes map[uint64]string) error {
|
||||||
} else if err := copyFile(source, target); err != nil {
|
} else if err := copyFile(source, target); err != nil {
|
||||||
return errors.Wrap(err, "failed to copy files")
|
return errors.Wrap(err, "failed to copy files")
|
||||||
}
|
}
|
||||||
} else if (fi.Mode() & os.ModeSymlink) == os.ModeSymlink {
|
case (fi.Mode() & os.ModeSymlink) == os.ModeSymlink:
|
||||||
link, err := os.Readlink(source)
|
link, err := os.Readlink(source)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "failed to read link: %s", source)
|
return errors.Wrapf(err, "failed to read link: %s", source)
|
||||||
|
@ -71,10 +75,11 @@ func copyDirectory(dst, src string, inodes map[uint64]string) error {
|
||||||
if err := os.Symlink(link, target); err != nil {
|
if err := os.Symlink(link, target); err != nil {
|
||||||
return errors.Wrapf(err, "failed to create symlink: %s", target)
|
return errors.Wrapf(err, "failed to create symlink: %s", target)
|
||||||
}
|
}
|
||||||
} else if (fi.Mode() & os.ModeDevice) == os.ModeDevice {
|
case (fi.Mode() & os.ModeDevice) == os.ModeDevice:
|
||||||
// TODO: support devices
|
if err := copyDevice(target, fi); err != nil {
|
||||||
return errors.New("devices not supported")
|
return errors.Wrapf(err, "failed to create device")
|
||||||
} else {
|
}
|
||||||
|
default:
|
||||||
// TODO: Support pipes and sockets
|
// TODO: Support pipes and sockets
|
||||||
return errors.Wrapf(err, "unsupported mode %s", fi.Mode())
|
return errors.Wrapf(err, "unsupported mode %s", fi.Mode())
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,3 +108,11 @@ func copyXAttrs(dst, src string) error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func copyDevice(dst string, fi os.FileInfo) error {
|
||||||
|
st, ok := fi.Sys().(*syscall.Stat_t)
|
||||||
|
if !ok {
|
||||||
|
return errors.New("unsupported stat type")
|
||||||
|
}
|
||||||
|
return syscall.Mknod(dst, uint32(fi.Mode().Perm()), int(st.Rdev))
|
||||||
|
}
|
||||||
|
|
|
@ -25,3 +25,7 @@ func copyFileContent(dst, src *os.File) error {
|
||||||
func copyXAttrs(dst, src string) error {
|
func copyXAttrs(dst, src string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func copyDevice(dst string, fi os.FileInfo) error {
|
||||||
|
return errors.New("device copy not supported")
|
||||||
|
}
|
||||||
|
|
|
@ -100,7 +100,7 @@ func Changes(ctx context.Context, upper, lower string) (context.Context, <-chan
|
||||||
cc.errL.Unlock()
|
cc.errL.Unlock()
|
||||||
cancel()
|
cancel()
|
||||||
}
|
}
|
||||||
defer close(changes)
|
close(changes)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return cc, changes
|
return cc, changes
|
||||||
|
|
|
@ -99,6 +99,8 @@ func sameFile(f1, f2 *currentPath) (bool, error) {
|
||||||
|
|
||||||
const compareChuckSize = 32 * 1024
|
const compareChuckSize = 32 * 1024
|
||||||
|
|
||||||
|
// compareFileContent compares the content of 2 same sized files
|
||||||
|
// by comparing each byte.
|
||||||
func compareFileContent(p1, p2 string) (bool, error) {
|
func compareFileContent(p1, p2 string) (bool, error) {
|
||||||
f1, err := os.Open(p1)
|
f1, err := os.Open(p1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in a new issue