Initial Commit
This commit is contained in:
		
							
								
								
									
										83
									
								
								asink.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								asink.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,83 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"flag"
 | 
			
		||||
	"path"
 | 
			
		||||
	"os/user"
 | 
			
		||||
	"github.com/howeyc/fsnotify"
 | 
			
		||||
	"code.google.com/p/goconf/conf"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var configFileName string
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	const config_usage = "Config File to use"
 | 
			
		||||
	userHomeDir := "~"
 | 
			
		||||
 | 
			
		||||
	u, err := user.Current()
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		userHomeDir = u.HomeDir
 | 
			
		||||
	} 
 | 
			
		||||
 | 
			
		||||
	flag.StringVar(&configFileName, "config", path.Join(userHomeDir, ".asink", "config"), config_usage)
 | 
			
		||||
	flag.StringVar(&configFileName, "c", path.Join(userHomeDir, ".asink", "config"), config_usage+" (shorthand)")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
	flag.Parse()
 | 
			
		||||
	fmt.Println("config file:", configFileName)
 | 
			
		||||
 | 
			
		||||
	config, err := conf.ReadConfigFile(configFileName)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		fmt.Println(err)
 | 
			
		||||
		fmt.Println("Error reading config file at ", configFileName, ". Does it exist?")
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	storage, err := GetStorage(config)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		fmt.Println(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	syncdir, err := config.GetString("local", "syncdir")
 | 
			
		||||
	cachedir, err := config.GetString("local", "cachedir")
 | 
			
		||||
 | 
			
		||||
	fmt.Println(syncdir)
 | 
			
		||||
	fmt.Println(cachedir)
 | 
			
		||||
	fmt.Println(storage)
 | 
			
		||||
 | 
			
		||||
	setup_watchers()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func setup_watchers() {
 | 
			
		||||
	watcher, err := fsnotify.NewWatcher()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		fmt.Println("Failed to create fsnotify watcher")
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	fmt.Println("Created new fsnotify watcher!")
 | 
			
		||||
 | 
			
		||||
	err = watcher.Watch("/home/aclindsa/.asink")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		fmt.Println("Failed to watch /home/aclindsa/.asink")
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for {
 | 
			
		||||
		select {
 | 
			
		||||
		case ev := <-watcher.Event:
 | 
			
		||||
			fmt.Println("event:", ev)
 | 
			
		||||
			hash, err := HashFile(ev.Name)
 | 
			
		||||
			//TODO if creating a directory, start watching it (and then initiate a full scan of it so we're sure nothing slipped through the cracks)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				fmt.Println(err)
 | 
			
		||||
			} else  {
 | 
			
		||||
				fmt.Println(hash)
 | 
			
		||||
			}
 | 
			
		||||
		case err := <-watcher.Error:
 | 
			
		||||
			fmt.Println("error:", err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										21
									
								
								hash.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								hash.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"io"
 | 
			
		||||
	"os"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"crypto/sha256"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func HashFile(filename string) (string, error) {
 | 
			
		||||
	hashfn := sha256.New()
 | 
			
		||||
 | 
			
		||||
	infile, err := os.Open(filename)
 | 
			
		||||
	if err != nil { return "", err }
 | 
			
		||||
	defer infile.Close()
 | 
			
		||||
 | 
			
		||||
	_, err = io.Copy(hashfn, infile)
 | 
			
		||||
	if err != nil { return "", err }
 | 
			
		||||
 | 
			
		||||
	return fmt.Sprintf("%x", hashfn.Sum(nil)), nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										32
									
								
								storage.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								storage.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"code.google.com/p/goconf/conf"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Storage interface {
 | 
			
		||||
	Put(filename string, hash string) error
 | 
			
		||||
	Get(filename string, hash string) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetStorage(config *conf.ConfigFile) (*Storage, error) {
 | 
			
		||||
	storageMethod, err := config.GetString("storage", "method")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.New("Error: storage method not specified in config file.")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var storage Storage
 | 
			
		||||
 | 
			
		||||
	switch storageMethod {
 | 
			
		||||
		case "local":
 | 
			
		||||
			storage, err = NewLocalStorage(config)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
		default:
 | 
			
		||||
			return nil, errors.New("Error: storage method '" + storageMethod + "' not implemented.")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &storage, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										69
									
								
								storage_local.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								storage_local.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,69 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"os"
 | 
			
		||||
	"io"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"path"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"code.google.com/p/goconf/conf"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type LocalStorage struct {
 | 
			
		||||
	storageDir string
 | 
			
		||||
	tmpSubdir string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewLocalStorage(config *conf.ConfigFile) (*LocalStorage, error) {
 | 
			
		||||
	storageDir, err := config.GetString("storage", "dir")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.New("Error: LocalStorage indicated in config file, but lacking local storage directory ('dir = some/dir').")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ls := new(LocalStorage)
 | 
			
		||||
	ls.storageDir = storageDir
 | 
			
		||||
	ls.tmpSubdir = path.Join(storageDir, ".asink-tmpdir")
 | 
			
		||||
	return ls, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ls *LocalStorage) copyToTmp(src string) (string, error) {
 | 
			
		||||
	infile, err := os.Open(src)
 | 
			
		||||
	if err != nil { return "", err }
 | 
			
		||||
	defer infile.Close()
 | 
			
		||||
	
 | 
			
		||||
	outfile, err := ioutil.TempFile(ls.tmpSubdir, "asink")
 | 
			
		||||
	if err != nil { return "", err }
 | 
			
		||||
	defer outfile.Close()
 | 
			
		||||
 | 
			
		||||
	_, err = io.Copy(outfile, infile)
 | 
			
		||||
	if err != nil { return "", err }
 | 
			
		||||
 | 
			
		||||
	return outfile.Name(), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ls *LocalStorage) Put(filename string, hash string) (e error) {
 | 
			
		||||
	tmpfile, err := ls.copyToTmp(filename)
 | 
			
		||||
	if err != nil { return err }
 | 
			
		||||
	defer func() {
 | 
			
		||||
		err := os.Remove(tmpfile)
 | 
			
		||||
		if err != nil && e == nil { e = err }
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	err = os.Rename(tmpfile, path.Join(ls.storageDir, hash))
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ls *LocalStorage) Get(filename string, hash string) error {
 | 
			
		||||
	infile, err := os.Open(path.Join(ls.storageDir, hash))
 | 
			
		||||
	if err != nil { return err }
 | 
			
		||||
	defer infile.Close()
 | 
			
		||||
 | 
			
		||||
	outfile, err := os.Open(filename)
 | 
			
		||||
	if err != nil { return err }
 | 
			
		||||
	defer outfile.Close()
 | 
			
		||||
 | 
			
		||||
	_, err = io.Copy(outfile, infile)
 | 
			
		||||
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user