Skip to content
This repository was archived by the owner on Sep 11, 2020. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions utils/fs/fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,9 @@ var (
)

type Filesystem interface {
//Create opens a file in write-only mode.
Create(filename string) (File, error)
//Open opens a file in read-only mode.
Open(filename string) (File, error)
OpenFile(filename string, flag int, perm os.FileMode) (File, error)
Stat(filename string) (FileInfo, error)
ReadDir(path string) ([]FileInfo, error)
TempFile(dir, prefix string) (File, error)
Expand All @@ -38,3 +37,16 @@ type File interface {
}

type FileInfo os.FileInfo

type BaseFile struct {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I though that we are adding this to the bare package not to the OS one

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed wildcard import.

BaseFilename string
Closed bool
}

func (f *BaseFile) Filename() string {
return f.BaseFilename
}

func (f *BaseFile) IsClosed() bool {
return f.Closed
}
50 changes: 31 additions & 19 deletions utils/fs/os/os.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ func NewOS(baseDir string) *OS {
}
}

// Create creates a new GlusterFSFile
// Create creates a file and opens it with standard permissions
// and modes O_RDWR, O_CREATE and O_TRUNC.
func (fs *OS) Create(filename string) (File, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to avoid duplicate code you can call fs.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666), and the same for Open

fullpath := path.Join(fs.base, filename)

Expand All @@ -42,6 +43,30 @@ func (fs *OS) Create(filename string) (File, error) {
return newOSFile(filename, f), nil
}

// OpenFile is equivalent to standard os.OpenFile.
// If flag os.O_CREATE is set, all parent directories will be created.
func (fs *OS) OpenFile(filename string, flag int, perm os.FileMode) (File, error) {
fullpath := path.Join(fs.base, filename)

if flag|os.O_CREATE != 0 {
if err := fs.createDir(fullpath); err != nil {
return nil, err
}
}

f, err := os.OpenFile(fullpath, flag, perm)
if err != nil {
return nil, err
}

filename, err = filepath.Rel(fs.base, fullpath)
if err != nil {
return nil, err
}

return newOSFile(filename, f), nil
}

func (fs *OS) createDir(fullpath string) error {
dir := filepath.Dir(fullpath)
if dir != "." {
Expand Down Expand Up @@ -82,8 +107,7 @@ func (fs *OS) Rename(from, to string) error {
return os.Rename(from, to)
}

// Open opens the named file for reading. If successful, methods on the returned
// file can be used for reading only.
// Open opens a file in read-only mode.
func (fs *OS) Open(filename string) (File, error) {
fullpath := fs.Join(fs.base, filename)
f, err := os.Open(fullpath)
Expand Down Expand Up @@ -147,15 +171,13 @@ func (fs *OS) Base() string {

// osFile represents a file in the os filesystem
type osFile struct {
filename string
closed bool
file *os.File
BaseFile
file *os.File
}

func newOSFile(filename string, file *os.File) File {
return &osFile{
filename: filename,
closed: false,
BaseFile: BaseFile{BaseFilename: filename},
file: file,
}
}
Expand All @@ -173,21 +195,11 @@ func (f *osFile) Write(p []byte) (int, error) {
}

func (f *osFile) Close() error {
f.closed = true
f.BaseFile.Closed = true

return f.file.Close()
}

func (f *osFile) ReadAt(p []byte, off int64) (n int, err error) {
return f.file.ReadAt(p, off)
}

//Filename returns the filename from the File
func (f *osFile) Filename() string {
return f.filename
}

//IsClosed returns if te file is closed
func (f *osFile) IsClosed() bool {
return f.closed
}
131 changes: 120 additions & 11 deletions utils/fs/test/fs_suite.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package test
import (
"fmt"
"io/ioutil"
"os"
"strings"
"testing"

Expand Down Expand Up @@ -35,13 +36,13 @@ func (s *FilesystemSuite) TestCreateDepthAbsolute(c *C) {
}

func (s *FilesystemSuite) TestCreateOverwrite(c *C) {
for i := 0; i < 2; i++ {
for i := 0; i < 3; i++ {
f, err := s.Fs.Create("foo")
c.Assert(err, IsNil)

l, err := f.Write([]byte("foo"))
l, err := f.Write([]byte(fmt.Sprintf("foo%d", i)))
c.Assert(err, IsNil)
c.Assert(l, Equals, 3)
c.Assert(l, Equals, 4)

err = f.Close()
c.Assert(err, IsNil)
Expand All @@ -52,25 +53,135 @@ func (s *FilesystemSuite) TestCreateOverwrite(c *C) {

wrote, err := ioutil.ReadAll(f)
c.Assert(err, IsNil)
c.Assert(wrote, DeepEquals, []byte("foo"))
c.Assert(string(wrote), DeepEquals, "foo2")
}

func (s *FilesystemSuite) TestCreateClose(c *C) {
f, err := s.Fs.Create("foo")
c.Assert(err, IsNil)
c.Assert(f.IsClosed(), Equals, false)

f.Write([]byte("foo"))
_, err = f.Write([]byte("foo"))
c.Assert(err, IsNil)
c.Assert(f.Close(), IsNil)

f, err = s.Fs.Open(f.Filename())
c.Assert(err, IsNil)

wrote, err := ioutil.ReadAll(f)
c.Assert(err, IsNil)
c.Assert(string(wrote), DeepEquals, "foo")
c.Assert(f.Close(), IsNil)
}

func (s *FilesystemSuite) TestOpenFileNoTruncate(c *C) {
defaultMode := os.FileMode(0666)

// Create when it does not exist
f, err := s.Fs.OpenFile("foo1", os.O_CREATE|os.O_WRONLY, defaultMode)
c.Assert(err, IsNil)
c.Assert(f.Filename(), Equals, "foo1")
s.testWriteClose(c, f, "foo1")

f, err = s.Fs.OpenFile("foo1", os.O_RDONLY, defaultMode)
c.Assert(err, IsNil)
s.testReadClose(c, f, "foo1")

// Create when it does exist
f, err = s.Fs.OpenFile("foo1", os.O_CREATE|os.O_WRONLY, defaultMode)
c.Assert(err, IsNil)
c.Assert(f.Filename(), Equals, "foo1")
s.testWriteClose(c, f, "bar")

f, err = s.Fs.OpenFile("foo1", os.O_RDONLY, defaultMode)
c.Assert(err, IsNil)
s.testReadClose(c, f, "bar1")
}

func (s *FilesystemSuite) TestOpenFileAppend(c *C) {
defaultMode := os.FileMode(0666)

f, err := s.Fs.OpenFile("foo1", os.O_CREATE|os.O_WRONLY|os.O_APPEND, defaultMode)
c.Assert(err, IsNil)
c.Assert(f.Filename(), Equals, "foo1")
s.testWriteClose(c, f, "foo1")

f, err = s.Fs.OpenFile("foo1", os.O_WRONLY|os.O_APPEND, defaultMode)
c.Assert(err, IsNil)
c.Assert(f.Filename(), Equals, "foo1")
s.testWriteClose(c, f, "bar1")

f, err = s.Fs.OpenFile("foo1", os.O_RDONLY, defaultMode)
c.Assert(err, IsNil)
s.testReadClose(c, f, "foo1bar1")
}

func (s *FilesystemSuite) TestOpenFileReadWrite(c *C) {
defaultMode := os.FileMode(0666)

file, err := s.Fs.Open(f.Filename())
f, err := s.Fs.OpenFile("foo1", os.O_CREATE|os.O_TRUNC|os.O_RDWR, defaultMode)
c.Assert(err, IsNil)
c.Assert(f.Filename(), Equals, "foo1")

wrote, err := ioutil.ReadAll(file)
written, err := f.Write([]byte("foobar"))
c.Assert(written, Equals, 6)
c.Assert(err, IsNil)
c.Assert(wrote, DeepEquals, []byte("foo"))

c.Assert(f.IsClosed(), Equals, true)
_, err = f.Seek(0, os.SEEK_SET)
c.Assert(err, IsNil)

written, err = f.Write([]byte("qux"))
c.Assert(written, Equals, 3)
c.Assert(err, IsNil)

_, err = f.Seek(0, os.SEEK_SET)
c.Assert(err, IsNil)

s.testReadClose(c, f, "quxbar")
}

func (s *FilesystemSuite) TestOpenFile(c *C) {
defaultMode := os.FileMode(0666)

f, err := s.Fs.OpenFile("foo1", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, defaultMode)
c.Assert(err, IsNil)
s.testWriteClose(c, f, "foo1")

// Truncate if it exists
f, err = s.Fs.OpenFile("foo1", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, defaultMode)
c.Assert(err, IsNil)
c.Assert(f.Filename(), Equals, "foo1")
s.testWriteClose(c, f, "foo1overwritten")

// Read-only if it exists
f, err = s.Fs.OpenFile("foo1", os.O_RDONLY, defaultMode)
c.Assert(err, IsNil)
c.Assert(f.Filename(), Equals, "foo1")
s.testReadClose(c, f, "foo1overwritten")

// Create when it does exist
f, err = s.Fs.OpenFile("foo1", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, defaultMode)
c.Assert(err, IsNil)
c.Assert(f.Filename(), Equals, "foo1")
s.testWriteClose(c, f, "bar")

f, err = s.Fs.OpenFile("foo1", os.O_RDONLY, defaultMode)
c.Assert(err, IsNil)
s.testReadClose(c, f, "bar")
}

func (s *FilesystemSuite) testWriteClose(c *C, f File, content string) {
written, err := f.Write([]byte(content))
c.Assert(written, Equals, len(content))
c.Assert(err, IsNil)
c.Assert(f.Close(), IsNil)
}

func (s *FilesystemSuite) testReadClose(c *C, f File, content string) {
read, err := ioutil.ReadAll(f)
c.Assert(err, IsNil)
c.Assert(string(read), Equals, content)
c.Assert(f.Close(), IsNil)
}

func (s *FilesystemSuite) TestReadDirAndDir(c *C) {
Expand Down Expand Up @@ -148,14 +259,12 @@ func (s *FilesystemSuite) TestTempFile(c *C) {
func (s *FilesystemSuite) TestTempFileWithPath(c *C) {
f, err := s.Fs.TempFile("foo", "bar")
c.Assert(err, IsNil)
fmt.Printf("f: %s\n", f.Filename())
c.Assert(strings.HasPrefix(f.Filename(), s.Fs.Join("foo", "bar")), Equals, true)
}

func (s *FilesystemSuite) TestTempFileFullWithPath(c *C) {
f, err := s.Fs.TempFile("/foo", "bar")
c.Assert(err, IsNil)
fmt.Printf("f: %s\n", f.Filename())
c.Assert(strings.HasPrefix(f.Filename(), s.Fs.Join("foo", "bar")), Equals, true)
}

Expand Down