func unmount(path string) error { log.Info(2, "searching path for fusermount.") fusermountPath, err := exec.LookPath("fusermount") if err != nil { return fmt.Errorf("could not find 'fusermount': ensure fuse is installed: %v", err) } log.Infof(2, "running: %v -u %v.", fusermountPath, path) process, err := os.StartProcess(fusermountPath, []string{fusermountPath, "-u", path}, &os.ProcAttr{}) if err != nil { return fmt.Errorf("could not start 'fusermount': %v", err) } log.Info(2, "waiting for process to exit.") processState, err := process.Wait() if err != nil { return fmt.Errorf("error waiting for process to exit: %v", err) } if !processState.Success() { return fmt.Errorf("could not unmount virtual filesystem.") } return nil }
func listFilesForQuery(queryText string, dirOnly, fileOnly, topOnly, leafOnly, recursive, print0, showCount, onePerLine bool) error { if queryText == "" { return fmt.Errorf("query must be specified. Use --all to show all files.") } store, err := storage.Open() if err != nil { return fmt.Errorf("could not open storage: %v", err) } defer store.Close() log.Info(2, "parsing query") expression, err := query.Parse(queryText) if err != nil { return err } log.Info(2, "checking tag names") wereErrors := false tagNames := query.TagNames(expression) tags, err := store.TagsByNames(tagNames) for _, tagName := range tagNames { if !tags.ContainsName(tagName) { log.Warnf("no such tag '%v'.", tagName) wereErrors = true continue } } if wereErrors { return blankError } log.Info(2, "querying database") files, err := store.QueryFiles(expression) if err != nil { return fmt.Errorf("could not query files: %v", err) } if err = listFiles(files, dirOnly, fileOnly, topOnly, leafOnly, recursive, print0, showCount, onePerLine); err != nil { return err } return nil }
func findDuplicatesInDb() error { store, err := storage.Open() if err != nil { return fmt.Errorf("could not open storage: %v", err) } defer store.Close() log.Info(2, "identifying duplicate files.") fileSets, err := store.DuplicateFiles() if err != nil { return fmt.Errorf("could not identify duplicate files: %v", err) } log.Infof(2, "found %v sets of duplicate files.", len(fileSets)) for index, fileSet := range fileSets { if index > 0 { fmt.Println() } fmt.Printf("Set of %v duplicates:\n", len(fileSet)) for _, file := range fileSet { relPath := _path.Rel(file.Path()) fmt.Printf(" %v\n", relPath) } } return nil }
// Commits the current transaction func (db *Database) Commit() error { log.Info(2, "committing transaction") if err := db.transaction.Commit(); err != nil { return fmt.Errorf("could not commit transaction: %v", err) } log.Info(2, "beginning new transaction") transaction, err := db.connection.Begin() if err != nil { return fmt.Errorf("could not begin new transaction: %v", err) } db.transaction = transaction return nil }
func listMounts() error { log.Info(2, "retrieving mount table.") mt, err := vfs.GetMountTable() if err != nil { return fmt.Errorf("could not get mount table: %v", err) } if len(mt) == 0 { log.Info(2, "mount table is empty.") } for _, mount := range mt { fmt.Printf("'%v' at '%v'\n", mount.DatabasePath, mount.MountPath) } return nil }
// Executes a SQL query returning rows. func (db *Database) ExecQuery(sql string, args ...interface{}) (*sql.Rows, error) { if log.Verbosity >= 3 { log.Infof(3, "executing query\n"+sql) for index, arg := range args { log.Info(3, "Arg %v = %v", index, arg) } } return db.transaction.Query(sql, args...) }
// Executes a SQL query. func (db *Database) Exec(sql string, args ...interface{}) (sql.Result, error) { if log.Verbosity >= 3 { log.Infof(3, "executing update\n"+sql) for index, arg := range args { log.Info(3, "Arg %v = %v", index, arg) } } return db.transaction.Exec(sql, args...) }
func unmountAll() error { log.Info(2, "retrieving mount table.") mt, err := vfs.GetMountTable() if err != nil { return fmt.Errorf("could not get mount table: %v", err) } if len(mt) == 0 { log.Info(2, "mount table is empty.") } for _, mount := range mt { err = unmount(mount.MountPath) if err != nil { return err } } return nil }
func init() { if path := os.Getenv("TMSU_DB"); path != "" { log.Info(3, "TMSU_DB=", path) Path = path } else { u, err := user.Current() if err != nil { log.Fatalf("could not identify current user: %v", err) } Path = filepath.Join(u.HomeDir, ".tmsu", "default.db") } }
func listAllFiles(dirOnly, fileOnly, topOnly, leafOnly, recursive, print0, showCount, onePerLine bool) error { store, err := storage.Open() if err != nil { return fmt.Errorf("could not open storage: %v", err) } defer store.Close() log.Info(2, "retrieving all files from database.") files, err := store.Files() if err != nil { return fmt.Errorf("could not retrieve files: %v", err) } return listFiles(files, dirOnly, fileOnly, topOnly, leafOnly, recursive, print0, showCount, onePerLine) }
func statusDatabase(dirOnly bool) (*StatusReport, error) { report := NewReport() store, err := storage.Open() if err != nil { return nil, fmt.Errorf("could not open storage: %v", err) } defer store.Close() log.Info(2, "retrieving all files from database.") files, err := store.Files() if err != nil { return nil, fmt.Errorf("could not retrieve files: %v", err) } err = statusCheckFiles(files, report) if err != nil { return nil, err } tree := path.NewTree() for _, file := range files { tree.Add(file.Path(), file.IsDir) } topLevelPaths := tree.TopLevel().Paths() if err != nil { return nil, err } for _, path := range topLevelPaths { if err = findNewFiles(path, report, dirOnly); err != nil { return nil, err } } return report, nil }
func listAllTags(showCount, onePerLine bool) error { store, err := storage.Open() if err != nil { return fmt.Errorf("could not open storage: %v", err) } defer store.Close() log.Info(2, "retrieving all tags.") if showCount { count, err := store.TagCount() if err != nil { return fmt.Errorf("could not retrieve tag count: %v", err) } fmt.Println(count) } else { tags, err := store.Tags() if err != nil { return fmt.Errorf("could not retrieve tags: %v", err) } if onePerLine { for _, tag := range tags { fmt.Println(tag.Name) } } else { tagNames := make([]string, len(tags)) for index, tag := range tags { tagNames[index] = tag.Name } format.Columns(tagNames, terminalWidth()) } } return nil }
func listAllValues(showCount, onePerLine bool) error { store, err := storage.Open() if err != nil { return fmt.Errorf("could not open storage: %v", err) } defer store.Close() log.Info(2, "retrieving all values.") if showCount { count, err := store.ValueCount() if err != nil { return fmt.Errorf("could not retrieve value count: %v", err) } fmt.Println(count) } else { values, err := store.Values() if err != nil { return fmt.Errorf("could not retrieve values: %v", err) } if onePerLine { for _, value := range values { fmt.Println(value.Name) } } else { valueNames := make([]string, len(values)) for index, value := range values { valueNames[index] = value.Name } format.Columns(valueNames, terminalWidth()) } } return nil }
// Closes the database connection func (db *Database) Close() error { log.Info(3, "closing database") return db.connection.Close() }
func mountExplicit(databasePath string, mountPath string, mountOptions string) error { if alreadyMounted(mountPath) { return fmt.Errorf("%v: mount path already in use", mountPath) } stat, err := os.Stat(mountPath) if err != nil { return fmt.Errorf("%v: could not stat: %v", mountPath, err) } if stat == nil { return fmt.Errorf("%v: mount point does not exist.", mountPath) } if !stat.IsDir() { return fmt.Errorf("%v: mount point is not a directory.", mountPath) } stat, err = os.Stat(databasePath) if err != nil { return fmt.Errorf("%v: could not stat: %v", databasePath, err) } if stat == nil { return fmt.Errorf("%v: database does not exist.") } log.Infof(2, "spawning daemon to mount VFS for database '%v' at '%v'.", databasePath, mountPath) args := []string{"vfs", databasePath, mountPath, "--options=" + mountOptions} daemon := exec.Command(os.Args[0], args...) errorPipe, err := daemon.StderrPipe() if err != nil { return fmt.Errorf("could not open standard error pipe: %v", err) } err = daemon.Start() if err != nil { return fmt.Errorf("could not start daemon: %v", err) } log.Info(2, "sleeping.") const HALF_SECOND = 500000000 time.Sleep(HALF_SECOND) log.Info(2, "checking whether daemon started successfully.") var waitStatus syscall.WaitStatus var rusage syscall.Rusage _, err = syscall.Wait4(daemon.Process.Pid, &waitStatus, syscall.WNOHANG, &rusage) if err != nil { return fmt.Errorf("could not check daemon status: %v", err) } if waitStatus.Exited() { if waitStatus.ExitStatus() != 0 { buffer := make([]byte, 1024) count, err := errorPipe.Read(buffer) if err != nil { return fmt.Errorf("could not read from error pipe: %v", err) } return fmt.Errorf("virtual filesystem mount failed: %v", string(buffer[0:count])) } } return nil }