Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

More error handling.

  • Loading branch information...
commit 6d39cd1d9141ee0cdf7ee73a6f9acb76a57f5a77 1 parent 5bc20af
@hanwen authored
Showing with 61 additions and 51 deletions.
  1. +35 −14 fs.go
  2. +26 −37 mtp.go
View
49 fs.go
@@ -238,14 +238,19 @@ type folderNode struct {
folders map[string]*File
}
-func (n *folderNode) fetch() {
+// Fetches data from device returns false on failure.
+func (n *folderNode) fetch() bool {
if n.files != nil {
- return
+ return true
+ }
+ l, err := n.fs.dev.FilesAndFolders(n.storageId, n.id)
+ if err != nil {
+ log.Printf("FilesAndFolders failed: %v", err)
+ return false
}
+
n.files = map[string]*File{}
n.folders = map[string]*File{}
-
- l := n.fs.dev.FilesAndFolders(n.storageId, n.id)
for _, f := range l {
if f.Filetype() == FILETYPE_FOLDER {
n.folders[f.Name()] = f
@@ -253,10 +258,13 @@ func (n *folderNode) fetch() {
n.files[f.Name()] = f
}
}
+ return true
}
func (n *folderNode) OpenDir(context *fuse.Context) (stream chan fuse.DirEntry, status fuse.Status) {
- n.fetch()
+ if !n.fetch() {
+ return nil, fuse.EIO
+ }
stream = make(chan fuse.DirEntry, len(n.folders)+len(n.files))
for n := range n.folders {
@@ -274,7 +282,9 @@ func (n *folderNode) GetAttr(file fuse.File, context *fuse.Context) (fi *fuse.At
}
func (n *folderNode) Lookup(name string, context *fuse.Context) (fi *fuse.Attr, node fuse.FsNode, code fuse.Status) {
- n.fetch()
+ if !n.fetch() {
+ return nil, nil, fuse.EIO
+ }
f := n.files[name]
if f != nil {
node = n.fs.newFile(f)
@@ -293,17 +303,20 @@ func (n *folderNode) Lookup(name string, context *fuse.Context) (fi *fuse.Attr,
}
func (n *folderNode) Mkdir(name string, mode uint32, context *fuse.Context) (*fuse.Attr, fuse.FsNode, fuse.Status) {
- n.fetch()
- newId := n.fs.dev.CreateFolder(n.id, name, n.storageId)
- if newId == 0 {
+ if !n.fetch() {
+ return nil, nil, fuse.EIO
+ }
+ newId, err := n.fs.dev.CreateFolder(n.id, name, n.storageId)
+ if err != nil {
+ log.Printf("CreateFolder failed: %v", err)
return nil, nil, fuse.EIO
}
f := n.fs.newFolder(newId, n.storageId)
n.Inode().New(true, f)
- if meta := n.fs.dev.Filemetadata(newId); meta == nil {
- log.Println("could fetch metadata for new directory %q", name)
+ if meta, err := n.fs.dev.Filemetadata(newId); err != nil {
+ log.Printf("Filemetadata failed for directory %q: %v", name, err)
return nil, nil, fuse.EIO
} else {
n.folders[name] = meta
@@ -314,13 +327,16 @@ func (n *folderNode) Mkdir(name string, mode uint32, context *fuse.Context) (*fu
}
func (n *folderNode) Unlink(name string, c *fuse.Context) fuse.Status {
- n.fetch()
+ if !n.fetch() {
+ return fuse.EIO
+ }
f := n.files[name]
if f == nil {
return fuse.ENOENT
}
err := n.fs.dev.DeleteObject(f.Id())
if err != nil {
+ log.Printf("DeleteObject failed: %v", err)
return fuse.EIO
}
n.Inode().RmChild(name)
@@ -329,7 +345,9 @@ func (n *folderNode) Unlink(name string, c *fuse.Context) fuse.Status {
}
func (n *folderNode) Rmdir(name string, c *fuse.Context) fuse.Status {
- n.fetch()
+ if !n.fetch() {
+ return fuse.EIO
+ }
folderObj := n.folders[name]
if folderObj == nil {
@@ -337,6 +355,7 @@ func (n *folderNode) Rmdir(name string, c *fuse.Context) fuse.Status {
}
err := n.fs.dev.DeleteObject(folderObj.Id())
if err != nil {
+ log.Printf("DeleteObject failed: %v", err)
return fuse.EIO
}
n.Inode().RmChild(name)
@@ -345,7 +364,9 @@ func (n *folderNode) Rmdir(name string, c *fuse.Context) fuse.Status {
}
func (n *folderNode) Create(name string, flags uint32, mode uint32, context *fuse.Context) (file fuse.File, fi *fuse.Attr, node fuse.FsNode, code fuse.Status) {
- n.fetch()
+ if !n.fetch() {
+ return nil, nil, nil, fuse.EIO
+ }
f, err := ioutil.TempFile(n.fs.backingDir, "")
if err != nil {
return nil, nil, nil, fuse.ToStatus(err)
View
63 mtp.go
@@ -4,6 +4,7 @@ import (
"fmt"
"log"
"reflect"
+ "strings"
"time"
"unsafe"
)
@@ -20,6 +21,7 @@ never have to call import "C"
*/
type Device C.LIBMTP_mtpdevice_t
+type Error C.LIBMTP_error_t
type MtpError C.LIBMTP_error_number_t
type RawDevice C.LIBMTP_raw_device_t
type DeviceStorage C.LIBMTP_devicestorage_t
@@ -122,47 +124,32 @@ func (d *Device) Release() {
C.LIBMTP_Release_Device(d.me())
}
-func (d *Device) Reset() error {
- code := C.LIBMTP_Reset_Device(d.me())
- if code != 0 {
- return fmt.Errorf("reset: error")
+func (d *Device) ErrorStack() error {
+ var messages []string
+ for p := C.LIBMTP_Get_Errorstack(d.me()); p != nil; p = p.next {
+ messages = append(messages, C.GoString(p.error_text))
}
-
- return nil
-}
-
-func (d *Device) ClearErrorstack() {
- C.LIBMTP_Clear_Errorstack(d.me())
-}
-
-func (d *Device) DumpErrorstack() {
- C.LIBMTP_Dump_Errorstack(d.me())
-}
-
-func (d *Device) FriendlyName() string {
- n := C.LIBMTP_Get_Friendlyname(d.me())
- if n == nil {
- return "(null)"
+ if len(messages) == 0 {
+ return nil
}
-
- // todo free n
- return C.GoString(n)
+ C.LIBMTP_Clear_Errorstack(d.me())
+ return fmt.Errorf("%s", strings.Join(messages, "\n"))
}
func (d *Device) GetStorage(sortOrder int) error {
err := C.LIBMTP_Get_Storage(d.me(), C.int(sortOrder))
if err != 0 {
- return fmt.Errorf("GetStorage: fail")
+ return d.ErrorStack()
}
return nil
}
-func (d *Device) FilesAndFolders(storageId uint32, parentId uint32) (files []*File) {
+func (d *Device) FilesAndFolders(storageId uint32, parentId uint32) (files []*File, err error) {
file := C.LIBMTP_Get_Files_And_Folders(d.me(), C.uint32_t(storageId), C.uint32_t(parentId))
for f := (*File)(file); f != nil; f = (*File)(f.next) {
files = append(files, f)
}
- return files
+ return files, d.ErrorStack()
}
func (d *Device) FolderList(s *DeviceStorage) (folders []*Folder) {
@@ -179,37 +166,39 @@ func (d *Device) ListStorage() (storages []*DeviceStorage) {
}
return
}
-func (d *Device) Filemetadata(id uint32) *File {
- return (*File)(C.LIBMTP_Get_Filemetadata(d.me(), C.uint32_t(id)))
+func (d *Device) Filemetadata(id uint32) (*File, error) {
+ f := (C.LIBMTP_Get_Filemetadata(d.me(), C.uint32_t(id)))
+ return (*File)(f), d.ErrorStack()
}
func (d *Device) GetFileToFileDescriptor(id uint32, fd uintptr) error {
- errno := C.LIBMTP_Get_File_To_File_Descriptor(d.me(), C.uint32_t(id), C.int(fd), nil, nil)
- if errno != 0 {
- return fmt.Errorf("GetFileToFileDescriptor: error")
+ code := C.LIBMTP_Get_File_To_File_Descriptor(d.me(), C.uint32_t(id), C.int(fd), nil, nil)
+ if code != 0 {
+ return d.ErrorStack()
}
return nil
}
func (d *Device) SendFromFileDescriptor(file *File, fd uintptr) error {
- errno := C.LIBMTP_Send_File_From_File_Descriptor(d.me(), C.int(fd), (*C.LIBMTP_file_t)(file), nil, nil)
- if errno != 0 {
- return fmt.Errorf("SendFromFileDescriptor: error")
+ code := C.LIBMTP_Send_File_From_File_Descriptor(d.me(), C.int(fd), (*C.LIBMTP_file_t)(file), nil, nil)
+ if code != 0 {
+ return d.ErrorStack()
}
return nil
}
// TODO should return modified name.
-func (d *Device) CreateFolder(parent uint32, name string, storage uint32) uint32 {
- return uint32(C.LIBMTP_Create_Folder(d.me(), C.CString(name), C.uint32_t(parent), C.uint32_t(storage)))
+func (d *Device) CreateFolder(parent uint32, name string, storage uint32) (uint32, error) {
+ id := C.LIBMTP_Create_Folder(d.me(), C.CString(name), C.uint32_t(parent), C.uint32_t(storage))
+ return uint32(id), d.ErrorStack()
}
func (d *Device) DeleteObject(id uint32) error {
c := C.LIBMTP_Delete_Object(d.me(), C.uint32_t(id))
if c != 0 {
- return fmt.Errorf("DeleteObject failed")
+ return d.ErrorStack()
}
return nil
}
Please sign in to comment.
Something went wrong with that request. Please try again.