Beispiel #1
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.")
	}

	dbPathWidth := 0
	for _, mount := range mt {
		if len(mount.DatabasePath) > dbPathWidth {
			dbPathWidth = len(mount.DatabasePath)
		}
	}

	for _, mount := range mt {
		fmt.Printf("%-*v\tat\t%v\n", dbPathWidth, mount.DatabasePath, mount.MountPath)
	}

	return nil
}
Beispiel #2
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
}
Beispiel #3
0
func listAllTags(store *storage.Storage, tx *storage.Tx, showCount, onePerLine bool) error {
	log.Info(2, "retrieving all tags.")

	if showCount {
		count, err := store.TagCount(tx)
		if err != nil {
			return fmt.Errorf("could not retrieve tag count: %v", err)
		}

		fmt.Println(count)
	} else {
		tags, err := store.Tags(tx)
		if err != nil {
			return fmt.Errorf("could not retrieve tags: %v", err)
		}

		if onePerLine {
			for _, tag := range tags {
				fmt.Println(escape(tag.Name, '=', ' '))
			}
		} else {
			tagNames := make([]string, len(tags))
			for index, tag := range tags {
				tagNames[index] = escape(tag.Name, '=', ' ')
			}

			terminal.PrintColumns(tagNames)
		}
	}

	return nil
}
Beispiel #4
0
func listAllValues(store *storage.Storage, tx *storage.Tx, showCount, onePerLine bool) error {
	log.Info(2, "retrieving all values.")

	if showCount {
		count, err := store.ValueCount(tx)
		if err != nil {
			return fmt.Errorf("could not retrieve value count: %v", err)
		}

		fmt.Println(count)
	} else {
		values, err := store.Values(tx)
		if err != nil {
			return fmt.Errorf("could not retrieve values: %v", err)
		}

		if onePerLine {
			for _, value := range values {
				fmt.Println(escape(value.Name))
			}
		} else {
			valueNames := make([]string, len(values))
			for index, value := range values {
				valueNames[index] = escape(value.Name)
			}

			terminal.PrintColumns(valueNames)
		}
	}

	return nil
}
Beispiel #5
0
func findDuplicatesInDb(store *storage.Storage, tx *storage.Tx) error {
	log.Info(2, "identifying duplicate files.")

	fileSets, err := store.DuplicateFiles(tx)
	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
}
Beispiel #6
0
func statusDatabase(store *storage.Storage, tx *storage.Tx, dirOnly, followSymlinks bool) (*StatusReport, error) {
	report := NewReport()

	log.Info(2, "retrieving all files from database.")

	files, err := store.Files(tx, "name")
	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, followSymlinks); err != nil {
			return nil, err
		}
	}

	return report, nil
}
Beispiel #7
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
}
Beispiel #8
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", "--database=" + 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 halfSecond = 500000000
	time.Sleep(halfSecond)

	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
}
Beispiel #9
0
func listFilesForQuery(store *storage.Storage, tx *storage.Tx, queryText, path string, dirOnly, fileOnly, print0, showCount, explicitOnly, ignoreCase bool, sort string) (error, warnings) {
	log.Info(2, "parsing query")

	expression, err := query.Parse(queryText)
	if err != nil {
		return fmt.Errorf("could not parse query: %v", err), nil
	}

	log.Info(2, "checking tag names")

	warnings := make(warnings, 0, 10)

	tagNames, err := query.TagNames(expression)
	if err != nil {
		return fmt.Errorf("could not identify tag names: %v", err), nil
	}

	tags, err := store.TagsByCasedNames(tx, tagNames, ignoreCase)
	for _, tagName := range tagNames {
		if err := entities.ValidateTagName(tagName); err != nil {
			warnings = append(warnings, err.Error())
			continue
		}

		if !tags.ContainsCasedName(tagName, ignoreCase) {
			warnings = append(warnings, fmt.Sprintf("no such tag '%v'", tagName))
			continue
		}
	}

	valueNames, err := query.ExactValueNames(expression)
	if err != nil {
		return fmt.Errorf("could not identify value names: %v", err), nil
	}

	values, err := store.ValuesByCasedNames(tx, valueNames, ignoreCase)
	for _, valueName := range valueNames {
		if err := entities.ValidateValueName(valueName); err != nil {
			warnings = append(warnings, err.Error())
			continue
		}

		if !values.ContainsCasedName(valueName, ignoreCase) {
			warnings = append(warnings, fmt.Sprintf("no such value '%v'", valueName))
			continue
		}
	}

	log.Info(2, "querying database")

	files, err := store.FilesForQuery(tx, expression, path, explicitOnly, ignoreCase, sort)
	if err != nil {
		if strings.Index(err.Error(), "parser stack overflow") > -1 {
			return fmt.Errorf("the query is too complex (see the troubleshooting wiki for how to increase the stack size)"), warnings
		} else {
			return fmt.Errorf("could not query files: %v", err), warnings
		}
	}

	if err = listFiles(tx, files, dirOnly, fileOnly, print0, showCount); err != nil {
		return err, warnings
	}

	return nil, warnings
}