X-Git-Url: http://www.git.cypherpunks.ru/?a=blobdiff_plain;f=src%2Ftmp.go;h=4a43eaa41a2675969f0d7109fe362f5304c93866;hb=891cee4997bb0a269d4b2f35311bab104bdc3283;hp=3c305ce36a54d7ec4432d8d98c1c43392a1311a5;hpb=c8b26fe06596d26bdb14c5be85760fb3ddb197b3;p=nncp.git diff --git a/src/tmp.go b/src/tmp.go index 3c305ce..4a43eaa 100644 --- a/src/tmp.go +++ b/src/tmp.go @@ -1,6 +1,6 @@ /* NNCP -- Node to Node copy, utilities for store-and-forward data exchange -Copyright (C) 2016-2019 Sergey Matveev +Copyright (C) 2016-2022 Sergey Matveev This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,24 +19,38 @@ package nncp import ( "bufio" + "fmt" "hash" "io" - "io/ioutil" "os" "path/filepath" - - "golang.org/x/crypto/blake2b" + "strconv" + "time" ) +var NoSync bool + +func init() { + NoSync = os.Getenv(CfgNoSync) != "" +} + +func TempFile(dir, prefix string) (*os.File, error) { + // Assume that probability of suffix collision is negligible + suffix := strconv.FormatInt(time.Now().UnixNano()+int64(os.Getpid()), 16) + name := filepath.Join(dir, "nncp"+prefix+suffix) + return os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, os.FileMode(0666)) +} + func (ctx *Ctx) NewTmpFile() (*os.File, error) { jobsPath := filepath.Join(ctx.Spool, "tmp") - var err error - if err = os.MkdirAll(jobsPath, os.FileMode(0700)); err != nil { + if err := ensureDir(jobsPath); err != nil { return nil, err } - fd, err := ioutil.TempFile(jobsPath, "") + fd, err := TempFile(jobsPath, "") if err == nil { - ctx.LogD("tmp", SDS{"src": fd.Name()}, "created") + ctx.LogD("tmp", LEs{{"Src", fd.Name()}}, func(les LEs) string { + return "Temporary file created: " + fd.Name() + }) } return fd, err } @@ -53,10 +67,7 @@ func (ctx *Ctx) NewTmpFileWHash() (*TmpFileWHash, error) { if err != nil { return nil, err } - hsh, err := blake2b.New256(nil) - if err != nil { - return nil, err - } + hsh := MTHNew(0, 0) return &TmpFileWHash{ W: bufio.NewWriter(io.MultiWriter(hsh, tmp)), Fd: tmp, @@ -71,21 +82,54 @@ func (tmp *TmpFileWHash) Cancel() { os.Remove(tmp.Fd.Name()) } +func DirSync(dirPath string) error { + if NoSync { + return nil + } + fd, err := os.Open(dirPath) + if err != nil { + return err + } + err = fd.Sync() + if err != nil { + fd.Close() + return err + } + return fd.Close() +} + +func (tmp *TmpFileWHash) Checksum() string { + return Base32Codec.EncodeToString(tmp.Hsh.Sum(nil)) +} + func (tmp *TmpFileWHash) Commit(dir string) error { var err error - if err = os.MkdirAll(dir, os.FileMode(0700)); err != nil { + if err = ensureDir(dir); err != nil { return err } if err = tmp.W.Flush(); err != nil { tmp.Fd.Close() return err } - if err = tmp.Fd.Sync(); err != nil { - tmp.Fd.Close() + if !NoSync { + if err = tmp.Fd.Sync(); err != nil { + tmp.Fd.Close() + return err + } + } + if err = tmp.Fd.Close(); err != nil { return err } - tmp.Fd.Close() - checksum := ToBase32(tmp.Hsh.Sum(nil)) - tmp.ctx.LogD("tmp", SDS{"src": tmp.Fd.Name(), "dst": checksum}, "commit") - return os.Rename(tmp.Fd.Name(), filepath.Join(dir, checksum)) + checksum := tmp.Checksum() + tmp.ctx.LogD( + "tmp-rename", + LEs{{"Src", tmp.Fd.Name()}, {"Dst", checksum}}, + func(les LEs) string { + return fmt.Sprintf("Temporary file: %s -> %s", tmp.Fd.Name(), checksum) + }, + ) + if err = os.Rename(tmp.Fd.Name(), filepath.Join(dir, checksum)); err != nil { + return err + } + return DirSync(dir) }