コード例 #1
0
ファイル: io.go プロジェクト: dholbach/snappy
// AtomicWriteFile updates the filename atomically and works otherwise
// like io/ioutil.WriteFile()
//
// Note that it won't follow symlinks and will replace existing symlinks
// with the real file
func AtomicWriteFile(filename string, data []byte, perm os.FileMode, flags AtomicWriteFlags) (err error) {
	if flags&AtomicWriteFollow != 0 {
		if fn, err := os.Readlink(filename); err == nil || (fn != "" && os.IsNotExist(err)) {
			if filepath.IsAbs(fn) {
				filename = fn
			} else {
				filename = filepath.Join(filepath.Dir(filename), fn)
			}
		}
	}
	tmp := filename + "." + strutil.MakeRandomString(12)

	// XXX: if go switches to use aio_fsync, we need to open the dir for writing
	dir, err := os.Open(filepath.Dir(filename))
	if err != nil {
		return err
	}
	defer dir.Close()

	fd, err := os.OpenFile(tmp, os.O_WRONLY|os.O_CREATE|os.O_TRUNC|os.O_EXCL, perm)
	if err != nil {
		return err
	}
	defer func() {
		e := fd.Close()
		if err == nil {
			err = e
		}
		if err != nil {
			os.Remove(tmp)
		}
	}()

	// according to the docs, Write returns a non-nil error when n !=
	// len(b), so don't worry about short writes.
	if _, err := fd.Write(data); err != nil {
		return err
	}

	if err := fd.Sync(); err != nil {
		return err
	}

	if err := os.Rename(tmp, filename); err != nil {
		return err
	}

	return dir.Sync()
}
コード例 #2
0
ファイル: io_test.go プロジェクト: dholbach/snappy
func (ts *AtomicWriteTestSuite) TestAtomicWriteFileNoOverwriteTmpExisting(c *C) {
	tmpdir := c.MkDir()
	// ensure we always get the same result
	rand.Seed(1)
	expectedRandomness := strutil.MakeRandomString(12)
	// ensure we always get the same result
	rand.Seed(1)

	p := filepath.Join(tmpdir, "foo")
	err := ioutil.WriteFile(p+"."+expectedRandomness, []byte(""), 0644)
	c.Assert(err, IsNil)

	err = AtomicWriteFile(p, []byte(""), 0600, 0)
	c.Assert(err, ErrorMatches, "open .*: file exists")
}
コード例 #3
0
ファイル: subscriber.go プロジェクト: dholbach/snappy
// NewSubscriber returns a new subscriber containing the given websocket
// connection and type/resource filters set from the query string params in the
// supplied http request
func NewSubscriber(c websocketConnection, r *http.Request) *Subscriber {
	s := &Subscriber{
		uuid: strutil.MakeRandomString(16),
		conn: c,
	}

	q := r.URL.Query()
	if len(q["types"]) > 0 {
		s.types = strings.Split(q["types"][0], ",")
	}
	if len(q["resource"]) > 0 {
		s.resource = q["resource"][0]
	}

	return s
}
コード例 #4
0
ファイル: run.go プロジェクト: dholbach/snappy
// genClassicScopeName generates an uniq name for the classic scope
func genClassicScopeName() string {
	now := time.Now()
	ti := fmt.Sprintf("%4d-%02d-%02d_%02d:%02d:%02d", now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second())
	return fmt.Sprintf("snappy-classic_%s_%s.scope", ti, strutil.MakeRandomString(5))
}