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:
Derek McGowan 2017-02-01 14:23:56 -08:00
parent 200cd6e877
commit f78105d832
5 changed files with 28 additions and 9 deletions

View file

@ -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())
} }

View file

@ -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))
}

View file

@ -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")
}

View file

@ -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

View file

@ -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 {