Example #1
0
File: dirs.go Project: mildred/doc
// Creates a directory dst from the information found in src
// First error is fatal, other errors are issues replicating attributes
func MkdirFrom(src, dst string) (error, []error) {
	var errs []error

	src_st, err := os.Stat(src)
	if err != nil {
		return err, nil
	}

	err = os.Mkdir(dst, src_st.Mode())
	if err != nil && !os.IsExist(err) {
		return err, nil
	}

	if stat, ok := src_st.Sys().(*syscall.Stat_t); ok {
		err = os.Lchown(dst, int(stat.Uid), int(stat.Gid))
		if err != nil {
			errs = append(errs, err)
		}

		atime := time.Unix(stat.Atim.Sec, stat.Atim.Nsec)
		err = os.Chtimes(dst, atime, src_st.ModTime())
		if err != nil {
			errs = append(errs, err)
		}
	}

	xattr, values, err := attrs.GetList(src)
	if err != nil {
		errs = append(errs, err)
	}

	for i, attrname := range xattr {
		err = attrs.Set(src, attrname, values[i])
		if err != nil {
			errs = append(errs, err)
		}
	}

	return nil, errs
}
Example #2
0
func (act *CopyAction) Run() error {
	var err error
	if act.Link {
		err = os.Link(act.Src, act.Dst)
		if err != nil {
			return fmt.Errorf("link %s: %s", act.Dst, err.Error())
		}
	} else if act.manualMode && act.srcInfo.Mode()&^(os.ModeDir /*|os.ModeSymlink*/) == 0 { // FIXME: enable symlinks
		stat, ok := act.srcInfo.Sys().(*syscall.Stat_t)

		if !ok {
			panic("Could not get Stat_t")
		}

		symlink := act.srcInfo.Mode()&os.ModeSymlink != 0

		if act.srcInfo.IsDir() {
			err = os.Mkdir(act.Dst, 0700)
			if err != nil {
				return err
			}
		} else if symlink {
			link, err := os.Readlink(act.Src)
			if err != nil {
				return err
			}

			err = os.Symlink(link, act.Dst)
			if err != nil {
				return err
			}
		} else {
			f, err := os.OpenFile(act.Dst, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
			if err != nil {
				return err
			}
			defer f.Close()

			f0, err := os.Open(act.Src)
			if err != nil {
				return err
			}
			defer f0.Close()

			_, err = io.Copy(f, f0)
			if err != nil {
				return err
			}
		}

		err = os.Lchown(act.Dst, int(stat.Uid), int(stat.Gid))
		if err != nil {
			log.Println(err)
			err = nil
		}

		if !symlink {

			atime := time.Unix(stat.Atim.Sec, stat.Atim.Nsec)
			err = os.Chtimes(act.Dst, atime, act.srcInfo.ModTime())
			if err != nil {
				return err
			}

			err = os.Chmod(act.Dst, act.SrcMode)
			if err != nil {
				return err
			}

			// FIXME: extended attributes for symlinks
			// golang is missing some syscalls

			xattr, values, err := attrs.GetList(act.Src)
			if err != nil {
				return err
			}

			for i, attrname := range xattr {
				err = attrs.Set(act.Src, attrname, values[i])
				if err != nil {
					return err
				}
			}

		}

		return nil
	} else {
		os.MkdirAll(filepath.Dir(act.Dst), 0755) // Ignore error
		cmd := exec.Command("/bin/cp", "-a", "--no-preserve=mode", "--reflink=auto", "-d", "-T", act.Src, act.Dst)
		cmd.Stderr = os.Stderr
		err = cmd.Run()
		if err != nil {
			return fmt.Errorf("cp %s %s: %s", act.Src, act.Dst, err.Error())
		}
		err = os.Chmod(act.Dst, act.SrcMode)
		if err != nil {
			return err
		}
	}

	if act.Conflict {
		if act.SrcMode&os.ModeSymlink == 0 {
			err = repo.MarkConflictFor(act.Dst, filepath.Base(act.OriginalDst))
			if err != nil {
				return fmt.Errorf("%s: could not mark conflict: %s", act.Dst, err.Error())
			}
		}
		if act.OrigDstMode&os.ModeSymlink == 0 {
			err = repo.AddConflictAlternative(act.OriginalDst, filepath.Base(act.Dst))
			if err != nil {
				return fmt.Errorf("%s: could add conflict alternative: %s", act.Dst, err.Error())
			}
		}
	}
	if act.SrcMode&os.ModeSymlink == 0 {
		if act.Hash != nil {
			info, err := os.Lstat(act.Dst)
			if err != nil {
				return fmt.Errorf("%s: could add lstat: %s", act.Dst, err.Error())
			}
			_, err = repo.CommitFileHash(act.Dst, info, act.Hash, false)
			if err != nil {
				return fmt.Errorf("%s: could not commit: %s", act.Dst, err.Error())
			}
		} else {
			hash, err := attrs.Get(act.Src, repo.XattrHash)
			if err == nil {
				err = attrs.Set(act.Dst, repo.XattrHash, hash)
				if err != nil {
					return fmt.Errorf("%s: could add xattr %s: %s", act.Dst, repo.XattrHash, err.Error())
				}
			}
			hashTime, err := attrs.Get(act.Src, repo.XattrHashTime)
			if err == nil {
				err = attrs.Set(act.Dst, repo.XattrHashTime, hashTime)
				if err != nil {
					return fmt.Errorf("%s: could add xattr %s: %s", act.Dst, repo.XattrHashTime, err.Error())
				}
			}
		}
	}
	return nil
}
Example #3
0
File: files.go Project: mildred/doc
func CopyFileTemp(src, dst string) (string, error, []error) {
	var errs []error

	src_st, err := os.Lstat(src)
	if err != nil {
		return "", err, nil
	}
	symlink := src_st.Mode()&os.ModeSymlink != 0

	src_f, err := os.Open(src)
	if err != nil {
		return "", err, nil
	}

	f, err := ioutil.TempFile(filepath.Dir(dst), "temp")
	if err != nil {
		return "", err, nil
	}
	fname := f.Name()

	if symlink {
		f.Close()
		err = os.Remove(fname)
		if err != nil {
			return "", err, nil
		}

		target, err := os.Readlink(src)
		if err != nil {
			return "", err, nil
		}

		err = os.Symlink(target, fname)
		if err != nil {
			return "", err, nil
		}
	} else {
		defer f.Close()
		_, err = io.Copy(f, src_f)
		if err != nil {
			if e := os.Remove(fname); e != nil {
				errs = append(errs, e)
			}
			return "", err, errs
		}
	}

	if stat, ok := src_st.Sys().(*syscall.Stat_t); ok {

		err = os.Lchown(fname, int(stat.Uid), int(stat.Gid))
		if err != nil {
			errs = append(errs, err)
		}

		if !symlink {

			atime := time.Unix(stat.Atim.Sec, stat.Atim.Nsec)
			err = os.Chtimes(fname, atime, src_st.ModTime())
			if err != nil {
				errs = append(errs, err)
			}
		}
	}

	if !symlink {

		err = os.Chmod(fname, src_st.Mode())
		if err != nil {
			errs = append(errs, err)
		}

		// FIXME: extended attributes for symlinks
		// golang is missing some syscalls

		xattr, values, err := attrs.GetList(src)
		if err != nil {
			errs = append(errs, err)
		} else {
			for i, attrname := range xattr {
				err = attrs.Set(fname, attrname, values[i])
				if err != nil {
					errs = append(errs, err)
				}
			}
		}
	}

	return fname, err, errs
}