Пример #1
0
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
}
Пример #2
0
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
}
Пример #3
0
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
}
Пример #4
0
// 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
}
Пример #5
0
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
}
Пример #6
0
// 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...)
}
Пример #7
0
// 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...)
}
Пример #8
0
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
}
Пример #9
0
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")
	}
}
Пример #10
0
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)
}
Пример #11
0
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
}
Пример #12
0
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
}
Пример #13
0
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
}
Пример #14
0
// Closes the database connection
func (db *Database) Close() error {
	log.Info(3, "closing database")

	return db.connection.Close()
}
Пример #15
0
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
}