func (s *cpSuite) TestCopyPreserveAll(c *C) { src := filepath.Join(c.MkDir(), "meep") dst := filepath.Join(c.MkDir(), "copied-meep") err := ioutil.WriteFile(src, []byte(nil), 0644) c.Assert(err, IsNil) // give it some different atime/mtime tv := []syscall.Timeval{ syscall.Timeval{Sec: 0, Usec: 0}, syscall.Timeval{Sec: 0, Usec: 0}, } err = syscall.Utimes(src, tv) c.Assert(err, IsNil) err = CopyFile(src, dst, CopyFlagPreserveAll) c.Assert(err, IsNil) // ensure that the mtime got preserved st1, err := os.Stat(src) c.Assert(err, IsNil) st2, err := os.Stat(dst) c.Assert(err, IsNil) c.Assert(st1.ModTime(), Equals, st2.ModTime()) }
// Chtimes changes the access and modification times of the named // file, similar to the Unix utime() or utimes() functions. // // The argument times are in nanoseconds, although the underlying // filesystem may truncate or round the values to a more // coarse time unit. func Chtimes(name string, atime_ns int64, mtime_ns int64) Error { var utimes [2]syscall.Timeval utimes[0] = syscall.NsecToTimeval(atime_ns) utimes[1] = syscall.NsecToTimeval(mtime_ns) if e := syscall.Utimes(name, utimes[0:]); e != 0 { return &PathError{"chtimes", name, Errno(e)} } return nil }
// Chtimes changes the access and modification times of the named // file, similar to the Unix utime() or utimes() functions. // // The underlying filesystem may truncate or round the values to a // less precise time unit. func Chtimes(name string, atime time.Time, mtime time.Time) error { var utimes [2]syscall.Timeval atime_ns := atime.Unix()*1e9 + int64(atime.Nanosecond()) mtime_ns := mtime.Unix()*1e9 + int64(mtime.Nanosecond()) utimes[0] = syscall.NsecToTimeval(atime_ns) utimes[1] = syscall.NsecToTimeval(mtime_ns) if e := syscall.Utimes(name, utimes[0:]); e != nil { return &PathError{"chtimes", name, e} } return nil }
// OSX does not have the utimensat syscall neded to implement this properly. // We do our best to emulate it using futimes. func (fs *loopbackFileSystem) Utimens(path string, a *time.Time, m *time.Time, context *fuse.Context) fuse.Status { tv := make([]syscall.Timeval, 2) if a == nil { tv[0].Usec = _UTIME_OMIT } else { tv[0] = timeToTimeval(a) } if m == nil { tv[1].Usec = _UTIME_OMIT } else { tv[1] = timeToTimeval(m) } err := syscall.Utimes(path, tv) return fuse.ToStatus(err) }
// This implementation should work for all systems that implement the utimes syscall func (e *entry) SetMtime(mtime time.Time) error { tvMtime := syscall.NsecToTimeval(mtime.UnixNano()) tvAtime := syscall.NsecToTimeval(time.Now().UnixNano()) resolvedPath := resolveSymlink(e.realPath()) err := syscall.Utimes(resolvedPath, []syscall.Timeval{tvAtime, tvMtime}) if err != nil { return err } e.fileInfo, err = os.Stat(resolvedPath) if err != nil { return err } return nil }
func main() { lsFiles := exec.Command("git", "ls-files", "-z") out, err := lsFiles.Output() if err != nil { fmt.Fprint(os.Stderr, err) os.Exit(1) } files := strings.Split(strings.TrimRight(string(out), "\x00"), "\x00") for _, file := range files { gitLog := exec.Command( "/bin/sh", "-c", fmt.Sprintf(`git log -n 1 --date=rfc2822 "%s" | head -n 3 | tail -n 1`, file), ) out, err := gitLog.Output() if err != nil { fmt.Fprint(os.Stderr, err) os.Exit(1) } mStr := strings.TrimSpace(strings.TrimLeft(string(out), "Date:")) mTime, err := time.Parse(rfc2822, mStr) if err != nil { fmt.Fprintf(os.Stderr, "%s on %s", err, file) os.Exit(1) } mTimeval := syscall.NsecToTimeval(mTime.UnixNano()) times := []syscall.Timeval{ mTimeval, mTimeval, } syscall.Utimes(file, times) fmt.Printf("%s: %s\n", file, mTime) } }
func main() { var fileFlag = flag.String("file", "", "file to modify date") var offsetFlag = flag.Int("offset", -300, "number of seconds") flag.Parse() if *fileFlag == "" { flag.Usage() os.Exit(1) } t := time.Now() seconds := int(t.UnixNano()/1e9) + *offsetFlag timeval := syscall.Timeval{int32(seconds), 0} timevals := []syscall.Timeval{timeval, timeval} err := syscall.Utimes(*fileFlag, timevals) if err != nil { panic(err) } }
func (self *Syncer) copyRegularFile(srcName string, stat *os.FileInfo, dstName string, out chan SyncStats) { stats := new(SyncStats) defer func() { out <- *stats }() outfd, err := os.Open(dstName, os.O_CREATE|os.O_EXCL|os.O_WRONLY, stat.Permission()) if err != nil { fmt.Fprintf(self.ErrorWriter, "Error opening copy output file %s: %s\n", dstName, err) stats.ErrorCount++ return } defer outfd.Close() infd, err := os.Open(srcName, os.O_RDONLY, 0) if err != nil { fmt.Fprintf(self.ErrorWriter, "Error opening copy source file %s: %s\n", srcName, err) stats.ErrorCount++ return } defer infd.Close() const BUF_SIZE = 1024 * 256 buf := make([]byte, BUF_SIZE) bytesRemain := stat.Size for bytesRemain > 0 { n, err := infd.Read(buf) switch { case n == 0: break case n < 0: stats.ErrorCount++ fmt.Fprintf(self.ErrorWriter, "Error copying file %s in read: %s", srcName, err) return default: outN, err := outfd.Write(buf[0:n]) if err != nil || outN != n { fmt.Fprintf(self.ErrorWriter, "Error copying file %s in write: %s", srcName, err) return } bytesRemain -= int64(outN) } } // Close it explicitly before we syscall.Utime() it, even // though the precautionary defer'd Close() above will close // it again later. That's harmless. err = outfd.Close() if err != nil { stats.ErrorCount++ return } // When the Chtimes patch is merged upstream... // err = os.Chtimes(dstName, stat.Atime_ns, stat.Mtime_ns) var tv []syscall.Timeval = make([]syscall.Timeval, 2) tv[0] = syscall.NsecToTimeval(stat.Atime_ns) tv[1] = syscall.NsecToTimeval(stat.Mtime_ns) errno := syscall.Utimes(dstName, tv) if errno != 0 { fmt.Fprintf(self.ErrorWriter, "Error modifying utimes on %s: %v", dstName, errno) stats.ErrorCount++ return } stats.FilesCreated++ if self.Verbose { fmt.Fprintln(self.VerboseWriter, dstName) } }
func (s *SyncReceiver) HandleConnection(conn net.Conn) { var err error defer func() { log.Println("Receiver: client disconnect with:", err) if err != nil { conn.Write([]byte{VerifyResultError}) } conn.Close() }() log.Println("New Connection Com") br := bufio.NewReader(conn) headerLen := syncHeaderLen() headerBuf := make([]byte, headerLen) _, err = br.Read(headerBuf) if err != nil { return } syncHeader := NewSyncHeaderFromBytes(headerBuf) log.Println("Read Header Succ", syncHeader.FileLength) buf_filename, err := br.ReadBytes('\n') //log.Println(len(buf_filename), buf_filename) if len(buf_filename) <= 1 { return } filename := string(buf_filename[0 : len(buf_filename)-1]) log.Println("filename:", filename) filename = path.Join(s.cfg.SyncRootFolder, filename) var fi os.FileInfo fi, err = os.Stat(filename) if os.IsNotExist(err) || fi.IsDir() { log.Printf("no such file: %s\n", filename) conn.Write([]byte{VerifyResultTransferToMe}) //NOW Read&Write Entire File rbuf := make([]byte, 512) //readbuf //create temp file tempfilename := filename + ".syncing" tempFile, err := os.Create(tempfilename) if err != nil { log.Println("Create temp file error", err) return } endTransfer := false readedBytes := int64(0) for !endTransfer { n, err := br.Read(rbuf) if err != nil { log.Println("Transfering File Err:", err) return } if n > 0 { if nw, err := tempFile.Write(rbuf[0:n]); err != nil || nw != n { log.Println("Write tempfile error") return } } readedBytes += int64(n) if readedBytes > syncHeader.FileLength { log.Println("Transfer more than syncheader:", readedBytes, syncHeader.FileLength) return } else if readedBytes == syncHeader.FileLength { endTransfer = true } log.Println("recv:", n) } if err := tempFile.Close(); err != nil { log.Println("Sync&Close temp file failed!") return } // log.Println("file recv over") //rename file & give a new mod time os.Rename(tempfilename, filename) fi, _ = os.Stat(filename) accessTimeval := new(syscall.Timeval) accessTimeval.Sec = fi.ModTime().Unix() modTimeval := new(syscall.Timeval) modTimeval.Sec = syncHeader.FileModTime.Unix() err = syscall.Utimes(filename, []syscall.Timeval{*accessTimeval, *modTimeval}) if err != nil { log.Println("utime error:", err) return } err = nil conn.Write([]byte{VerifyResultDoNext}) log.Println("sync over!!!") } else { if syncHeader.FileLength == fi.Size() && syncHeader.FileModTime.Equal(fi.ModTime()) { log.Println("Timestamp & Size Equal. This file is synced") conn.Write([]byte{VerifyResultDoNext}) //TBD continue the loop } else { log.Println("Modtime not equal. So need file compare") //Send need compare flag conn.Write([]byte{VerifyResultNeedCompare}) //Compute & Send chunkchecksum // syncHeader.FileLength f, err := os.Open(filename) if err != nil { log.Println("open file err:", err) return } checkSum := NewRollingCheckSum(f, syncHeader.ChunkSize) hashes, err := checkSum.SumEveryChunk() if err != nil { log.Println("error when generate checksum", err) return } checksumBytes := CheckSumPackArrayToBytes(hashes) conn.Write(checksumBytes) //adler+md5 //Recv TransferData Packages } } /* version := br.ReadByte() packageType := br.ReadByte() if !(version == 0x01 && packageType == PackageTypeSyncRequest) { return } return temp2 := make([]byte, 2) br.Read(temp) //little endian packageLen := uint16(temp2[0])|(uint16(temp2[1])<<8) io.WriteString(conn, "Hi") */ }