mirror of https://github.com/spf13/afero.git
143 lines
3.7 KiB
Go
143 lines
3.7 KiB
Go
|
package swift
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"fmt"
|
||
|
"github.com/ncw/swift"
|
||
|
"log"
|
||
|
"os"
|
||
|
"time"
|
||
|
)
|
||
|
|
||
|
type Fs struct {
|
||
|
Connection *swift.Connection
|
||
|
containerName string
|
||
|
}
|
||
|
|
||
|
func NewSwiftFs(conn *swift.Connection, containerName string) (fs *Fs, err error) {
|
||
|
if containerName == "" {
|
||
|
return fs, fmt.Errorf("container name cannot be empty")
|
||
|
}
|
||
|
fs = &Fs{
|
||
|
Connection: conn,
|
||
|
containerName: containerName,
|
||
|
}
|
||
|
err = fs.Connection.Authenticate()
|
||
|
return
|
||
|
}
|
||
|
|
||
|
func (s *Fs) Name() string {
|
||
|
return "swiftfs"
|
||
|
}
|
||
|
|
||
|
func (s *Fs) Create(name string) (file File, err error) {
|
||
|
objectfile, err := s.Connection.ObjectCreate(s.containerName, name, true, "", "", swift.Headers{})
|
||
|
if err != nil {
|
||
|
return file, err
|
||
|
}
|
||
|
file.objectCreateFile = objectfile
|
||
|
|
||
|
return
|
||
|
}
|
||
|
|
||
|
func (s *Fs) Mkdir(name string, perm os.FileMode) (err error) {
|
||
|
return s.MkdirAll(name, perm)
|
||
|
}
|
||
|
|
||
|
func (s *Fs) MkdirAll(path string, perm os.FileMode) (err error) {
|
||
|
// Swift usually creates all directories deep down, no matter if any of these directories already exist
|
||
|
// Objects created with application/directory are so called "pseudo-directories".
|
||
|
_, err = s.Connection.ObjectPut(s.containerName, path+"/", bytes.NewReader([]byte{}), true, "", "application/directory", swift.Headers{})
|
||
|
return
|
||
|
}
|
||
|
|
||
|
func (s *Fs) Open(name string) (file *File, err error) {
|
||
|
file = new(File)
|
||
|
file.conn = s.Connection
|
||
|
file.containerName = s.containerName
|
||
|
|
||
|
f, headers, err := s.Connection.ObjectOpen(s.containerName, name, true, swift.Headers{})
|
||
|
if err != nil {
|
||
|
return
|
||
|
}
|
||
|
err = file.putFileInfoTogetherFromOpenObject(f, headers, name)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
func (*Fs) OpenFile(name string, flag int, perm os.FileMode) (*File, error) {
|
||
|
return nil, nil
|
||
|
}
|
||
|
|
||
|
func (s *Fs) Remove(name string) error {
|
||
|
return s.Connection.ObjectDelete(s.containerName, name)
|
||
|
}
|
||
|
|
||
|
func (s *Fs) RemoveAll(path string) (err error) {
|
||
|
sinfo, err := s.Connection.QueryInfo()
|
||
|
if err != nil {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// Get all objects we want to delte
|
||
|
objects, err := s.Connection.ObjectsAll(s.containerName, &swift.ObjectsOpts{Prefix: path})
|
||
|
if err != nil {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
var objectnames []string
|
||
|
for _, o := range objects {
|
||
|
// If the server supports bulk delete, add it to a list to bulkdelete the items later,
|
||
|
// otherwise delete them directly
|
||
|
if sinfo.SupportsBulkDelete() {
|
||
|
objectnames = append(objectnames, o.Name)
|
||
|
} else {
|
||
|
err = s.Connection.ObjectDelete(s.containerName, o.Name)
|
||
|
if err != nil {
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if sinfo.SupportsBulkDelete() {
|
||
|
_, err = s.Connection.BulkDelete(s.containerName, objectnames)
|
||
|
if err != nil {
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
func (s *Fs) Rename(oldname, newname string) error {
|
||
|
return s.Connection.ObjectMove(s.containerName, oldname, s.containerName, newname)
|
||
|
}
|
||
|
|
||
|
func (s *Fs) Stat(name string) (os.FileInfo, error) {
|
||
|
file, err := s.Open(name)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
return file.Stat()
|
||
|
}
|
||
|
|
||
|
func (*Fs) Chmod(name string, mode os.FileMode) error {
|
||
|
log.Println("Swift does not support file modes.")
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (s *Fs) Chtimes(name string, _, mtime time.Time) error {
|
||
|
// While the uncommented code should work, the problem is that we have no way to update the time on
|
||
|
// the server without modifying the time. Whenever we send a request to swift to update the last modified time,
|
||
|
// we modify the file thus setting the last modified time to now...
|
||
|
// Maybe I'll find a solution for this in the future, but for now I'll just diable it because of the reasons above.
|
||
|
return nil
|
||
|
/*
|
||
|
_, headers, err := s.Connection.ObjectOpen(s.containerName, name, true, swift.Headers{})
|
||
|
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
headers.ObjectMetadata().SetModTime(mtime) // Swift does not support access time so we won't use that.
|
||
|
return s.Connection.ObjectUpdate(s.containerName, name, headers)
|
||
|
*/
|
||
|
}
|