Esempio n. 1
0
func (command UnmountCommand) unmount(path string) error {
	if command.verbose {
		log.Info("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)
	}

	if command.verbose {
		log.Infof("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)
	}

	if command.verbose {
		log.Info("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
}
Esempio n. 2
0
func (command DupesCommand) findDuplicatesInDb() error {
	store, err := storage.Open()
	if err != nil {
		return fmt.Errorf("could not open storage: %v", err)
	}
	defer store.Close()

	if command.verbose {
		log.Info("identifying duplicate files.")
	}

	fileSets, err := store.DuplicateFiles()
	if err != nil {
		return fmt.Errorf("could not identify duplicate files: %v", err)
	}

	if command.verbose {
		log.Infof("found %v sets of duplicate files.", len(fileSets))
	}

	for index, fileSet := range fileSets {
		if index > 0 {
			log.Print()
		}

		log.Printf("Set of %v duplicates:", len(fileSet))

		for _, file := range fileSet {
			relPath := _path.Rel(file.Path())
			log.Printf("  %v", relPath)
		}
	}

	return nil
}
Esempio n. 3
0
func (command TagsCommand) listAllTags() error {
	store, err := storage.Open()
	if err != nil {
		return fmt.Errorf("could not open storage: %v", err)
	}
	defer store.Close()

	if command.verbose {
		log.Info("retrieving all tags.")
	}

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

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

		for _, tag := range tags {
			log.Print(tag.Name)
		}
	}

	return nil
}
Esempio n. 4
0
func (command RepairCommand) repairModified(store *storage.Storage, modified fileIdAndInfoMap) error {
	if command.verbose {
		log.Info("repairing modified files")
	}

	for path, fileIdAndStat := range modified {
		fileId := fileIdAndStat.fileId
		stat := fileIdAndStat.stat

		log.Infof("%v: modified", path)

		fingerprint, err := fingerprint.Create(path)
		if err != nil {
			return fmt.Errorf("%v: could not create fingerprint: %v", path, err)
		}

		if !command.pretend {
			_, err := store.UpdateFile(fileId, path, fingerprint, stat.ModTime(), stat.Size(), stat.IsDir())
			if err != nil {
				return fmt.Errorf("%v: could not update file in database: %v", path, err)
			}
		}

	}

	return nil
}
Esempio n. 5
0
func (command RepairCommand) determineStatuses(fsPaths fileInfoMap, dbPaths databaseFileMap) (tagged databaseFileMap, untagged fileInfoMap, modified fileIdAndInfoMap, missing databaseFileMap) {
	if command.verbose {
		log.Info("determining file statuses")
	}

	tagged = make(databaseFileMap, 100)
	untagged = make(fileInfoMap, 100)
	modified = make(fileIdAndInfoMap, 100)
	missing = make(databaseFileMap, 100)

	for path, stat := range fsPaths {
		if dbFile, isTagged := dbPaths[path]; isTagged {
			if dbFile.ModTime == stat.ModTime().UTC() && dbFile.Size == stat.Size() {
				tagged[path] = dbFile
			} else {
				modified[path] = struct {
					fileId uint
					stat   os.FileInfo
				}{dbFile.Id, stat}
			}
		} else {
			untagged[path] = stat
		}
	}

	for path, dbFile := range dbPaths {
		if _, found := fsPaths[path]; !found {
			missing[path] = dbFile
		}
	}

	return tagged, untagged, modified, missing
}
Esempio n. 6
0
func (command FilesCommand) listFilesForTags(args []string) error {
	if len(args) == 0 {
		return fmt.Errorf("at least one tag 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()

	includeTagIds := make([]uint, 0)
	excludeTagIds := make([]uint, 0)
	for _, arg := range args {
		var tagName string
		var include bool

		if arg[0] == '-' {
			tagName = arg[1:]
			include = false
		} else {
			tagName = arg
			include = true
		}

		tag, err := store.TagByName(tagName)
		if err != nil {
			return fmt.Errorf("could not retrieve tag '%v': %v", tagName, err)
		}
		if tag == nil {
			log.Fatalf("no such tag '%v'.", tagName)
		}

		if include {
			includeTagIds = append(includeTagIds, tag.Id)
		} else {
			excludeTagIds = append(excludeTagIds, tag.Id)
		}
	}

	if command.verbose {
		log.Info("retrieving set of tagged files from the database.")
	}

	files, err := store.FilesWithTags(includeTagIds, excludeTagIds)
	if err != nil {
		return fmt.Errorf("could not retrieve files with tags %v and without tags %v: %v", includeTagIds, excludeTagIds, err)
	}

	return command.listFiles(files)
}
Esempio n. 7
0
func (command UnmountCommand) unmountAll() error {
	if command.verbose {
		log.Info("retrieving mount table.")
	}

	mt, err := vfs.GetMountTable()
	if err != nil {
		return fmt.Errorf("could not get mount table: %v", err)
	}

	if command.verbose && len(mt) == 0 {
		log.Info("mount table is empty.")
	}

	for _, mount := range mt {
		err = command.unmount(mount.MountPath)
		if err != nil {
			return err
		}
	}

	return nil
}
Esempio n. 8
0
func (command RepairCommand) repairMoved(store *storage.Storage, missing databaseFileMap, untagged fileInfoMap) error {
	if command.verbose {
		log.Info("repairing moved files")
	}

	moved := make([]string, 0, 10)

	for path, dbFile := range missing {
		if command.verbose {
			log.Infof("%v: searching for new location", path)
		}

		for candidatePath, stat := range untagged {
			if stat.Size() == dbFile.Size {
				fingerprint, err := fingerprint.Create(candidatePath)
				if err != nil {
					return fmt.Errorf("%v: could not create fingerprint: %v", path, err)
				}

				if fingerprint == dbFile.Fingerprint {
					log.Infof("%v: moved to %v", path, candidatePath)

					moved = append(moved, path)

					if !command.pretend {
						_, err := store.UpdateFile(dbFile.Id, candidatePath, dbFile.Fingerprint, stat.ModTime(), dbFile.Size, dbFile.IsDir)
						if err != nil {
							return fmt.Errorf("%v: could not update file in database: %v", path, err)
						}
					}

					delete(untagged, candidatePath)

					break
				}
			}
		}
	}

	for _, path := range moved {
		delete(missing, path)
	}

	return nil
}
Esempio n. 9
0
func (command FilesCommand) listAllFiles() error {
	store, err := storage.Open()
	if err != nil {
		return fmt.Errorf("could not open storage: %v", err)
	}
	defer store.Close()

	if command.verbose {
		log.Info("retrieving all files from database.")
	}

	files, err := store.Files()
	if err != nil {
		return fmt.Errorf("could not retrieve files: %v", err)
	}

	return command.listFiles(files)
}
Esempio n. 10
0
func (command StatusCommand) statusDatabase() (*StatusReport, error) {
	report := NewReport()

	store, err := storage.Open()
	if err != nil {
		return nil, fmt.Errorf("could not open storage: %v", err)
	}
	defer store.Close()

	if command.verbose {
		log.Info("retrieving all files from database.")
	}

	files, err := store.Files()
	if err != nil {
		return nil, fmt.Errorf("could not retrieve files: %v", err)
	}

	err = command.checkFiles(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 = command.findNewFiles(path, report); err != nil {
			return nil, err
		}
	}

	return report, nil
}
Esempio n. 11
0
func (command RepairCommand) repairDatabase(store *storage.Storage) error {
	if command.verbose {
		log.Info("retrieving all files from the database.")
	}

	files, err := store.Files()
	if err != nil {
		return fmt.Errorf("could not retrieve paths from storage: %v", err)
	}

	paths := make([]string, len(files))
	for index := 0; index < len(files); index++ {
		paths[index] = files[index].Path()
	}

	err = command.checkFiles(store, paths)
	if err != nil {
		return err
	}

	return nil
}