Commits

Paul Ruane committed 9f6885f

Updates for weekly.2011-12-06.
Switched from gosqlite to mattn/go-sqlite3 package which appears to be better maintained.

  • Participants
  • Parent commits 7d4c23f

Comments (0)

Files changed (9)

-Go          weekly.2011-10-18
-Goslqite    11:b2b4926fd235
-Gofuse      5183e8663cdb529b899bbcad10e0fa1e3c6deb
+Go                  weekly.2011-11-08
+mattn/go-sqlite3    7d29362424
+hanwen/go-fuse      5183e8663cdb529b899bbcad10e0fa1e3c6deb

src/tmsu/commands/help.go

 	fmt.Println("tmsu")
 	fmt.Println()
 
-	var maxWidth uint = 0
+	var maxWidth int = 0
 	commandNames := make([]string, 0, len(commands))
 	for commandName, _ := range commands {
-		maxWidth = uint(math.Max(float64(maxWidth), float64(len(commandName))))
+		maxWidth = int(math.Max(float64(maxWidth), float64(len(commandName))))
 		commandNames = append(commandNames, commandName)
 	}
 
 			continue
 		}
 
-		fmt.Printf("  %-"+strconv.Uitoa(maxWidth)+"v  %v\n", command.Name(), commandSummary)
+		fmt.Printf("  %-" + strconv.Itoa(maxWidth) + "v  %v\n", command.Name(), commandSummary)
 	}
 }
 

src/tmsu/commands/mount.go

 
 import (
 	"errors"
-	"exec"
 	"os"
+	"os/exec"
 	"time"
 )
 
     fileInfo, error := os.Stat(path)
     if error != nil { return error }
     if fileInfo == nil { return errors.New("Mount point '" + path + "' does not exist.") }
-    if !fileInfo.IsDirectory() { return errors.New("Mount point '" + path + "' is not a directory.") }
+    if !fileInfo.IsDir() { return errors.New("Mount point '" + path + "' is not a directory.") }
     //TODO check permissions on mount path
 
 	mountPath := args[0]

src/tmsu/commands/status.go

             return nil, nil, error
         }
 
-        if fileInfo.IsRegular() {
+        if fileInfo.Mode() & os.ModeType == 0 {
             absPath, error := filepath.Abs(path)
             if error != nil {
                 return nil, nil, error
             } else {
                 tagged = append(tagged, absPath)
             }
-        } else if fileInfo.IsDirectory() {
+        } else if fileInfo.IsDir() {
             file, error := os.Open(path)
             if error != nil {
                 return nil, nil, error

src/tmsu/commands/tags.go

         fileInfo, error := os.Lstat(paths[0])
         if error != nil { return error }
 
-        if fileInfo.IsRegular() {
+        if fileInfo.Mode() & os.ModeType == 0 {
             tags, error := this.tagsForPath(db, paths[0])
             if error != nil { return error }
             if tags == nil { return nil }
         fileInfo, error := os.Lstat(path)
         if error != nil { return error }
 
-        if fileInfo.IsRegular() {
+        if fileInfo.Mode() & os.ModeType == 0 {
             tags, error := this.tagsForPath(db, path)
             if error != nil { return error }
             if tags == nil { continue }
 
                 fmt.Println()
             }
-        } else if fileInfo.IsDirectory() {
+        } else if fileInfo.IsDir() {
             file, error := os.Open(path)
             if error != nil { return error }
             defer file.Close()

src/tmsu/commands/unmount.go

 
 import (
 	"errors"
-	"exec"
 	"os"
+	"os/exec"
 )
 
 type UnmountCommand struct{}

src/tmsu/database.go

 package main
 
 import (
+    "exp/sql"
 	"strconv"
 	"strings"
-	"gosqlite.googlecode.com/hg/sqlite"
+	_ "github.com/mattn/go-sqlite3"
 )
 
+//TODO handle iteration errors
+//TODO handle scan errors
+//TODO check rows affected
+
 type Database struct {
-	connection *sqlite.Conn
+	connection *sql.DB
 }
 
 func OpenDatabase(path string) (*Database, error) {
-	connection, error := sqlite.Open(path)
+	connection, error := sql.Open("sqlite3", path)
 	if error != nil { return nil, error }
 
 	database := Database{connection}
             FROM tag
             ORDER BY name`
 
-	statement, error := this.connection.Prepare(sql)
+	rows, error := this.connection.Query(sql)
 	if error != nil { return nil, error }
-	defer statement.Finalize()
+	defer rows.Close()
 
 	tags := make([]Tag, 0, 10)
-	for statement.Next() {
-		var id int
+	for rows.Next() {
+		var id uint
 		var name string
-		statement.Scan(&id, &name)
+		rows.Scan(&id, &name)
 
-		tags = append(tags, Tag{uint(id), name})
+		tags = append(tags, Tag{id, name})
 	}
 
 	return &tags, nil
 	        FROM tag
 	        WHERE name = ?`
 
-	statement, error := this.connection.Prepare(sql)
+	rows, error := this.connection.Query(sql, name)
 	if error != nil { return nil, error }
-	defer statement.Finalize()
+	defer rows.Close()
 
-	error = statement.Exec(name)
-	if error != nil { return nil, error }
+	if !rows.Next() { return nil, nil }
 
-	if !statement.Next() {
-	    if statement.Error() != nil {
-	        return nil, statement.Error()
-        }
+	var id uint
+	rows.Scan(&id)
 
-		return nil, nil
-	}
-
-	var id int
-	statement.Scan(&id)
-
-	return &Tag{uint(id), name}, nil
+	return &Tag{id, name}, nil
 }
 
 func (this Database) TagsByFileId(fileId uint) (*[]Tag, error) {
             )
             ORDER BY name`
 
-	statement, error := this.connection.Prepare(sql)
+	rows, error := this.connection.Query(sql, fileId)
 	if error != nil { return nil, error }
-	defer statement.Finalize()
-
-	error = statement.Exec(int(fileId))
-	if error != nil { return nil, error }
+	defer rows.Close()
 
 	tags := make([]Tag, 0, 10)
-	for statement.Next() {
-		var tagId int
+	for rows.Next() {
+		var tagId uint
 		var tagName string
-		statement.Scan(&tagId, &tagName)
+		rows.Scan(&tagId, &tagName)
 
-		tags = append(tags, Tag{uint(tagId), tagName})
+		tags = append(tags, Tag{tagId, tagName})
 	}
 
-	if statement.Error() != nil { return nil, statement.Error() }
-
-	return &tags, error
+	return &tags, nil
 }
 
 func (this Database) TagsForTags(tagNames []string) (*[]Tag, error) {
             )
             ORDER BY name`
 
-	statement, error := this.connection.Prepare(sql)
-	if error != nil { return nil, error }
-	defer statement.Finalize()
-
 	// convert string array to empty-interface array
 	castTagNames := make([]interface{}, len(tagNames))
 	for index, tagName := range tagNames {
 		castTagNames[index] = tagName
 	}
 
-	error = statement.Exec(castTagNames...)
+	rows, error := this.connection.Query(sql, castTagNames...)
 	if error != nil { return nil, error }
+	defer rows.Close()
 
 	tags := make([]Tag, 0, 10)
-	for statement.Next() {
-		var tagId int
+	for rows.Next() {
+		var tagId uint
 		var tagName string
-		statement.Scan(&tagId, &tagName)
+		rows.Scan(&tagId, &tagName)
 
 		if !this.contains(tagNames, tagName) {
-			tags = append(tags, Tag{uint(tagId), tagName})
+			tags = append(tags, Tag{tagId, tagName})
 		}
 	}
 
-	if statement.Error() != nil { return nil, statement.Error() }
-
 	return &tags, nil
 }
 
 	sql := `INSERT INTO tag (name)
 	        VALUES (?)`
 
-	statement, error := this.connection.Prepare(sql)
-	if error != nil { return nil, error }
-	defer statement.Finalize()
-
-	error = statement.Exec(name)
+	result, error := this.connection.Exec(sql, name)
 	if error != nil { return nil, error }
 
-	statement.Next()
-	if statement.Error() != nil { return nil, statement.Error() }
-
-	id := this.connection.LastInsertRowId()
+	id, error := result.LastInsertId()
+	if error != nil { return nil, error }
 
 	return &Tag{uint(id), name}, nil
 }
 	        SET name = ?
 	        WHERE id = ?`
 
-	statement, error := this.connection.Prepare(sql)
+	_, error := this.connection.Exec(sql, name, tagId)
 	if error != nil { return nil, error }
-	defer statement.Finalize()
-
-	error = statement.Exec(name, int(tagId))
-	if error != nil { return nil, error }
-
-	statement.Next()
-	if statement.Error() != nil { return nil, statement.Error() }
 
 	return &Tag{tagId, name}, nil
 }
 	sql := `DELETE FROM tag
 	        WHERE id = ?`
 
-	statement, error := this.connection.Prepare(sql)
+	_, error := this.connection.Exec(sql, tagId)
 	if error != nil { return error }
-	defer statement.Finalize()
-
-	error = statement.Exec(int(tagId))
-	if error != nil { return error }
-
-	statement.Next()
-	if statement.Error() != nil { return statement.Error() }
 
 	return nil
 }
 	sql := `SELECT id, path, fingerprint
 	        FROM file`
 
-	statement, error := this.connection.Prepare(sql)
+	rows, error := this.connection.Query(sql)
 	if error != nil { return nil, error }
-	defer statement.Finalize()
-
-	error = statement.Exec()
-	if error != nil { return nil, error }
+	defer rows.Close()
 
 	files := make([]File, 0, 10)
-	for statement.Next() {
-		var fileId int
+	for rows.Next() {
+		var fileId uint
 		var path string
 		var fingerprint string
-		statement.Scan(&fileId, &path, &fingerprint)
+		rows.Scan(&fileId, &path, &fingerprint)
 
-		files = append(files, File{uint(fileId), path, fingerprint})
+		files = append(files, File{fileId, path, fingerprint})
 	}
 
-	if statement.Error() != nil { return nil, statement.Error() }
-
 	return &files, nil
 }
 
 	        FROM file
 	        WHERE id = ?`
 
-	statement, error := this.connection.Prepare(sql)
+	rows, error := this.connection.Query(sql, id)
 	if error != nil { return nil, error }
-	defer statement.Finalize()
+	defer rows.Close()
 
-	error = statement.Exec(int(id))
-	if error != nil { return nil, error }
-
-	if !statement.Next() {
-	    if statement.Error() != nil {
-	        return nil, statement.Error()
-        }
-
+	if !rows.Next() {
 		return nil, nil
 	}
 
 	var path string
 	var fingerprint string
-	statement.Scan(&path, &fingerprint)
+	rows.Scan(&path, &fingerprint)
 
 	return &File{id, path, fingerprint}, nil
 }
 	        FROM file
 	        WHERE path = ?`
 
-	statement, error := this.connection.Prepare(sql)
+	rows, error := this.connection.Query(sql, path)
 	if error != nil { return nil, error }
-	defer statement.Finalize()
+	defer rows.Close()
 
-	error = statement.Exec(path)
-	if error != nil { return nil, error }
-
-	if !statement.Next() {
-	    if statement.Error() != nil { return nil, statement.Error() }
-
+	if !rows.Next() {
 		return nil, nil
 	}
 
-	var id int
+	var id uint
 	var fingerprint string
-	statement.Scan(&id, &fingerprint)
+	rows.Scan(&id, &fingerprint)
 
-	return &File{uint(id), path, fingerprint}, nil
+	return &File{id, path, fingerprint}, nil
 }
 
 func (this Database) FileByFingerprint(fingerprint string) (*File, error) {
 	        FROM file
 	        WHERE fingerprint = ?`
 
-	statement, error := this.connection.Prepare(sql)
+	rows, error := this.connection.Query(sql, fingerprint)
 	if error != nil { return nil, error }
-	defer statement.Finalize()
+	defer rows.Close()
 
-	error = statement.Exec(fingerprint)
-	if error != nil { return nil, error }
-
-	if !statement.Next() {
-	    if statement.Error() != nil { return nil, statement.Error() }
-
+	if !rows.Next() {
 		return nil, nil
 	}
 
-	var id int
+	var id uint
 	var path string
-	statement.Scan(&id, &path)
+	rows.Scan(&id, &path)
 
-	return &File{uint(id), path, fingerprint}, nil
+	return &File{id, path, fingerprint}, nil
 }
 
 func (this Database) AddFile(path string, fingerprint string) (*File, error) {
 	sql := `INSERT INTO file (path, fingerprint)
 	        VALUES (?,?)`
 
-	statement, error := this.connection.Prepare(sql)
-	if error != nil { return nil, error }
-	defer statement.Finalize()
-
-	error = statement.Exec(path, fingerprint)
+	result, error := this.connection.Exec(sql, path, fingerprint)
 	if error != nil { return nil, error }
 
-	statement.Next()
-	if statement.Error() != nil { return nil, statement.Error() }
-
-	id := this.connection.LastInsertRowId()
+	id, error := result.LastInsertId()
+	if error != nil { return nil, error }
 
 	return &File{uint(id), path, fingerprint}, nil
 }
                 HAVING count(*) = ` + strconv.Itoa(len(tagNames)) + `
             )`
 
-	statement, error := this.connection.Prepare(sql)
-	if error != nil { return nil, error }
-	defer statement.Finalize()
-
 	// convert string array to empty-interface array
 	castTagNames := make([]interface{}, len(tagNames))
 	for index, tagName := range tagNames {
 		castTagNames[index] = tagName
 	}
 
-	error = statement.Exec(castTagNames...)
+	rows, error := this.connection.Query(sql, castTagNames)
 	if error != nil { return nil, error }
+	defer rows.Close()
 
 	files := make([]File, 0, 10)
-	for statement.Next() {
-		var fileId int
+	for rows.Next() {
+		var fileId uint
 		var path string
 		var fingerprint string
-		statement.Scan(&fileId, &path, &fingerprint)
+		rows.Scan(&fileId, &path, &fingerprint)
 
-		files = append(files, File{uint(fileId), path, fingerprint})
+		files = append(files, File{fileId, path, fingerprint})
 	}
 
-	if statement.Error() != nil { return nil, statement.Error() }
-
 	return &files, nil
 }
 
 	        SET fingerprint = ?
 	        WHERE id = ?`
 
-	statement, error := this.connection.Prepare(sql)
+	_, error := this.connection.Exec(sql, fingerprint, int(fileId))
 	if error != nil { return error }
-	defer statement.Finalize()
-
-	error = statement.Exec(fingerprint, int(fileId))
-	if error != nil { return error }
-
-	statement.Next()
-	if statement.Error() != nil { return statement.Error() }
 
 	return nil
 }
 	sql := `DELETE FROM file
 	        WHERE id = ?`
 
-	statement, error := this.connection.Prepare(sql)
+	_, error := this.connection.Exec(sql, fileId)
 	if error != nil { return error }
-	defer statement.Finalize()
-
-	error = statement.Exec(int(fileId))
-	if error != nil { return error }
-
-	statement.Next()
-	if statement.Error() != nil { return statement.Error() }
 
 	return nil
 }
 	sql := `SELECT id, file_id, tag_id
 	        FROM file_tag`
 
-	statement, error := this.connection.Prepare(sql)
+	rows, error := this.connection.Query(sql)
 	if error != nil { return nil, error }
-	defer statement.Finalize()
-
-	error = statement.Exec()
-	if error != nil { return nil, error }
+	defer rows.Close()
 
 	fileTags := make([]FileTag, 0, 10)
-	for statement.Next() {
-		var fileTagId int
-		var fileId int
-		var tagId int
-		statement.Scan(&fileTagId, &fileId, &tagId)
+	for rows.Next() {
+		var fileTagId uint
+		var fileId uint
+		var tagId uint
+		rows.Scan(&fileTagId, &fileId, &tagId)
 
-		fileTags = append(fileTags, FileTag{uint(fileTagId), uint(fileId), uint(tagId)})
+		fileTags = append(fileTags, FileTag{fileTagId, fileId, tagId})
 	}
 
-	if statement.Error() != nil { return nil, statement.Error() }
-
 	return &fileTags, nil
 }
 
 	        WHERE file_id = ?
 	        AND tag_id = ?`
 
-	statement, error := this.connection.Prepare(sql)
+	rows, error := this.connection.Query(sql, fileId, tagId)
 	if error != nil { return nil, error }
-	defer statement.Finalize()
+	defer rows.Close()
 
-	error = statement.Exec(int(fileId), int(tagId))
-	if error != nil { return nil, error }
-
-	if !statement.Next() {
-	    if statement.Error() != nil { return nil, statement.Error() }
-
+	if !rows.Next() {
 		return nil, nil
 	}
 
-	var fileTagId int
-	statement.Scan(&fileTagId)
+	var fileTagId uint
+	rows.Scan(&fileTagId)
 
-	return &FileTag{uint(fileTagId), fileId, tagId}, nil
+	return &FileTag{fileTagId, fileId, tagId}, nil
 }
 
 func (this Database) FileTagsByTagId(tagId uint) (*[]FileTag, error) {
 	        FROM file_tag
 	        WHERE tag_id = ?`
 
-	statement, error := this.connection.Prepare(sql)
+	rows, error := this.connection.Query(sql, tagId)
 	if error != nil { return nil, error }
-	defer statement.Finalize()
-
-	error = statement.Exec(int(tagId))
-	if error != nil { return nil, error }
+	defer rows.Close()
 
 	fileTags := make([]FileTag, 0, 10)
-	for statement.Next() {
-		var fileTagId int
-		var fileId int
-		statement.Scan(&fileTagId, &fileId)
+	for rows.Next() {
+		var fileTagId uint
+		var fileId uint
+		rows.Scan(&fileTagId, &fileId)
 
-		fileTags = append(fileTags, FileTag{uint(fileTagId), uint(fileId), tagId})
+		fileTags = append(fileTags, FileTag{fileTagId, fileId, tagId})
 	}
 
-    if statement.Error() != nil { return nil, statement.Error() }
-
 	return &fileTags, nil
 }
 
             WHERE file_id = ?
             LIMIT 1`
 
-	statement, error := this.connection.Prepare(sql)
+	rows, error := this.connection.Query(sql, fileId)
 	if error != nil { return false, error }
-	defer statement.Finalize()
+	defer rows.Close()
 
-	error = statement.Exec(int(fileId))
-	if error != nil { return false, error }
-    if statement.Next() { return true, nil }
-    if statement.Error() != nil { return false, statement.Error() }
+    if rows.Next() { return true, nil }
 
     return false, nil
 }
 	sql := `INSERT INTO file_tag (file_id, tag_id)
 	        VALUES (?, ?)`
 
-	statement, error := this.connection.Prepare(sql)
-	if error != nil { return nil, error }
-	defer statement.Finalize()
-
-	error = statement.Exec(int(fileId), int(tagId))
+	result, error := this.connection.Exec(sql, fileId, tagId)
 	if error != nil { return nil, error }
 
-	if !statement.Next() {
-	    if statement.Error() != nil { return nil, statement.Error() }
-
-		return nil, nil
-	}
-
-	id := this.connection.LastInsertRowId()
+	id, error := result.LastInsertId()
+	if error != nil { return nil, error }
 
 	return &FileTag{uint(id), fileId, tagId}, nil
 }
 	        WHERE file_id = ?
 	        AND tag_id = ?`
 
-	statement, error := this.connection.Prepare(sql)
+	_, error := this.connection.Exec(sql, fileId, tagId)
 	if error != nil { return error }
-	defer statement.Finalize()
-
-	error = statement.Exec(int(fileId), int(tagId))
-	if error != nil { return error }
-
-	statement.Next()
-	if statement.Error() != nil { return statement.Error() }
 
 	return nil
 }
 	sql := `DELETE FROM file_tag
 	        WHERE file_id = ?`
 
-	statement, error := this.connection.Prepare(sql)
+	_, error := this.connection.Exec(sql, fileId)
 	if error != nil { return error }
-	defer statement.Finalize()
-
-	error = statement.Exec(int(fileId))
-	if error != nil { return error }
-
-	statement.Next()
-	if statement.Error() != nil { return statement.Error() }
 
 	return nil
 }
 	sql := `DELETE FROM file_tag
 	        WHERE tag_id = ?`
 
-	statement, error := this.connection.Prepare(sql)
+	_, error := this.connection.Exec(sql, tagId)
 	if error != nil { return error }
-	defer statement.Finalize()
-
-	error = statement.Exec(int(tagId))
-	if error != nil { return error }
-
-	statement.Next()
-	if statement.Error() != nil { return statement.Error() }
 
 	return nil
 }
 	        SET tag_id = ?
 	        WHERE tag_id = ?`
 
-	statement, error := this.connection.Prepare(sql)
+	_, error := this.connection.Exec(sql, newTagId, oldTagId)
 	if error != nil { return error }
-	defer statement.Finalize()
-
-	error = statement.Exec(int(newTagId), int(oldTagId))
-	if error != nil { return error }
-
-	statement.Next()
-	if statement.Error() != nil { return statement.Error() }
 
 	return nil
 }
                 name TEXT NOT NULL
             )`
 
-	error := this.exec(sql)
+	_, error := this.connection.Exec(sql)
 	if error != nil { return error }
 
     sql = `CREATE INDEX IF NOT EXISTS idx_tag_name
            ON tag(name)`
 
-	error = this.exec(sql)
+	_, error = this.connection.Exec(sql)
 	if error != nil { return error }
 
     sql = `CREATE TABLE IF NOT EXISTS file (
                fingerprint TEXT NOT NULL
            )`
 
-	error = this.exec(sql)
+	_, error = this.connection.Exec(sql)
 	if error != nil { return error }
 
     sql = `CREATE INDEX IF NOT EXISTS idx_file_fingerprint
            ON file(fingerprint)`
 
-	error = this.exec(sql)
+	_, error = this.connection.Exec(sql)
 	if error != nil { return error }
 
     sql = `CREATE INDEX IF NOT EXISTS idx_file_path
            ON file(path)`
 
-	error = this.exec(sql)
+	_, error = this.connection.Exec(sql)
 	if error != nil { return error }
 
     sql = `CREATE TABLE IF NOT EXISTS file_tag (
                FOREIGN KEY (tag_id) REFERENCES tag(id)
            )`
 
-	error = this.exec(sql)
+	_, error = this.connection.Exec(sql)
 	if error != nil { return error }
 
     sql = `CREATE INDEX IF NOT EXISTS idx_file_tag_file_id
            ON file_tag(file_id)`
 
-	error = this.exec(sql)
+	_, error = this.connection.Exec(sql)
 	if error != nil { return error }
 
     sql = `CREATE INDEX IF NOT EXISTS idx_file_tag_tag_id
            ON file_tag(tag_id)`
 
-	error = this.exec(sql)
+	_, error = this.connection.Exec(sql)
 	if error != nil { return error }
 
 	return nil
 
 	return false
 }
-
-func (this *Database) exec(sql string) error {
-	statement, error := this.connection.Prepare(sql)
-	if error != nil { return error }
-	defer statement.Finalize()
-
-	error = statement.Exec()
-	if error != nil { return error }
-
-	statement.Next()
-	if statement.Error() != nil { return statement.Error() }
-
-	return nil
-}

src/tmsu/fingerprinter.go

 		hash.Write(buffer[:count])
 	}
 
-	sum := hash.Sum()
+	sum := hash.Sum(make([]byte, 0, 64))
 	fingerprint := hex.EncodeToString(sum)
 
 	return fingerprint, nil

src/tmsu/fusevfs.go

 	"os"
 	"strings"
 	"strconv"
-	"time"
 	"github.com/hanwen/go-fuse/fuse"
 )
 
 // Mount the VFS.
 func MountVfs(databasePath string, mountPath string) (*FuseVfs, error) {
 	fuseVfs := FuseVfs{}
-
-	state, _, error := fuse.MountPathFileSystem(mountPath, &fuseVfs, nil)
+    pathNodeFs := fuse.NewPathNodeFs(&fuseVfs, nil)
+	state, _, error := fuse.MountNodeFileSystem(mountPath, pathNodeFs, nil)
 	if error != nil { return nil, error }
 
 	fuseVfs.databasePath = databasePath
 }
 
 // Get entry attributes.
-func (this FuseVfs) GetAttr(name string, context *fuse.Context) (*os.FileInfo, fuse.Status) {
+func (this FuseVfs) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse.Status) {
 	switch name {
 	case "":
 		fallthrough
 	case "tags":
-        now := time.Nanoseconds()
-		return &os.FileInfo{Mode: fuse.S_IFDIR | 0755, Atime_ns: now, Mtime_ns: now, Ctime_ns: now}, fuse.OK
+		return &fuse.Attr{Mode: fuse.S_IFDIR | 0755}, fuse.OK
 	}
 
 	path := this.splitPath(name)
 
 	if count == 1 { return 0, nil }
 
-	id, error := strconv.Atoui(parts[count-2])
-	if error != nil { id, error = strconv.Atoui(parts[count-1]) }
+	id, error := Atoui(parts[count - 2])
+	if error != nil { id, error = Atoui(parts[count - 1]) }
 	if error != nil { return 0, nil }
 
 	return id, nil
 	return channel, fuse.OK
 }
 
-func (this FuseVfs) getTaggedEntryAttr(path []string) (*os.FileInfo, fuse.Status) {
+func (this FuseVfs) getTaggedEntryAttr(path []string) (*fuse.Attr, fuse.Status) {
 	pathLength := len(path)
 	name := path[pathLength-1]
 
 
 	if fileId == 0 {
 	    // if no file ID then it is a tag directory
-        now := time.Nanoseconds()
-		return &os.FileInfo{Mode: fuse.S_IFDIR | 0755, Atime_ns: now, Mtime_ns: now, Ctime_ns: now}, fuse.OK
+		return &fuse.Attr{Mode: fuse.S_IFDIR | 0755}, fuse.OK
 	}
 
 	db, error := OpenDatabase(this.databasePath)
 
     file, error := db.File(fileId)
     if error != nil { log.Fatalf("Could not retrieve file #%v: %v", fileId, error) }
-    if file == nil { return &os.FileInfo{Mode: fuse.S_IFREG}, fuse.ENOENT }
+    if file == nil { return &fuse.Attr{Mode: fuse.S_IFREG}, fuse.ENOENT }
 
     fileInfo, error := os.Stat(file.Path)
-    var atime, mtime, ctime, size int64
+    var size int64
     if error == nil {
-        atime = fileInfo.Atime_ns
-        mtime = fileInfo.Mtime_ns
-        ctime = fileInfo.Ctime_ns
-        size = fileInfo.Size
+        size = fileInfo.Size()
     } else {
-        now := time.Nanoseconds()
-        atime = now
-        mtime = now
-        ctime = now
         size = 0
     }
 
-	return &os.FileInfo{Mode: fuse.S_IFLNK | 0755, Atime_ns: atime, Mtime_ns: mtime, Ctime_ns: ctime, Size: size}, fuse.OK
+	return &fuse.Attr{Mode: fuse.S_IFLNK | 0755, Size: uint64(size)}, fuse.OK
 }
 
 func (this FuseVfs) openTaggedEntryDir(path []string) (chan fuse.DirEntry, fuse.Status) {
     extension := filepath.Ext(file.Path)
     fileName := filepath.Base(file.Path)
     linkName := fileName[0 : len(fileName) - len(extension)]
-    suffix := "." + strconv.Uitoa(file.Id) + extension
+    suffix := "." + Uitoa(file.Id) + extension
 
     if len(linkName) + len(suffix) > 255 {
         linkName = linkName[0 : 255 - len(suffix)]
 
     return linkName + suffix
 }
+
+func Uitoa(ui uint) string {
+    return strconv.FormatUint(uint64(ui), 10)
+}
+
+func Atoui(str string) (uint, error) {
+    ui64, error := strconv.ParseUint(str, 10, 0)
+    return uint(ui64), error
+}