go-judge/envexec/file_util_linux.go

56 lines
1.1 KiB
Go

package envexec
import (
"os"
"syscall"
)
func copyDir(src *os.File, dst string) error {
// make sure dir exists
os.MkdirAll(dst, 0777)
newDir, err := os.Open(dst)
if err != nil {
return err
}
defer newDir.Close()
dir := src
names, err := dir.Readdirnames(-1)
if err != nil {
return err
}
for _, n := range names {
if err := copyFileDir(int(dir.Fd()), int(newDir.Fd()), n); err != nil {
return err
}
}
return nil
}
func copyFileDir(srcDirFd, dstDirFd int, name string) error {
// open the source file
fd, err := syscall.Openat(srcDirFd, name, syscall.O_CLOEXEC|syscall.O_RDONLY, 0777)
if err != nil {
return err
}
defer syscall.Close(fd)
var st syscall.Stat_t
if err := syscall.Fstat(fd, &st); err != nil {
return err
}
// open the dst file
dstFd, err := syscall.Openat(dstDirFd, name, syscall.O_CLOEXEC|syscall.O_WRONLY|syscall.O_CREAT|syscall.O_TRUNC, 0777)
if err != nil {
return err
}
defer syscall.Close(dstFd)
// send file, ignore error for now if it is dir
if _, err := syscall.Sendfile(dstFd, fd, nil, int(st.Size)); err != nil && err != syscall.EINVAL {
return err
}
return nil
}