Beispiel #1
0
func statusCheckFile(absPath string, file *entities.File, report *StatusReport) error {
	log.Infof(2, "%v: checking file status.", absPath)

	stat, err := os.Stat(file.Path())
	if err != nil {
		switch {
		case os.IsNotExist(err):
			log.Infof(2, "%v: file is missing.", absPath)

			report.AddRow(Row{absPath, MISSING})
			return nil
		case os.IsPermission(err):
			log.Warnf("%v: permission denied.", absPath)
		case strings.Contains(err.Error(), "not a directory"): //TODO improve
			report.AddRow(Row{file.Path(), MISSING})
			return nil
		default:
			return fmt.Errorf("%v: could not stat: %v", file.Path(), err)
		}
	} else {
		if stat.Size() != file.Size || !stat.ModTime().UTC().Equal(file.ModTime) {
			log.Infof(2, "%v: file is modified.", absPath)

			report.AddRow(Row{absPath, MODIFIED})
		} else {
			log.Infof(2, "%v: file is unchanged.", absPath)

			report.AddRow(Row{absPath, TAGGED})
		}
	}

	return nil
}
Beispiel #2
0
func repairModified(store *storage.Storage, tx *storage.Tx, modified entities.Files, pretend bool, settings entities.Settings) error {
	log.Infof(2, "repairing modified files")

	for _, dbFile := range modified {
		stat, err := os.Stat(dbFile.Path())
		if err != nil {
			return err
		}

		fingerprint, err := fingerprint.Create(dbFile.Path(), settings.FileFingerprintAlgorithm(), settings.DirectoryFingerprintAlgorithm(), settings.SymlinkFingerprintAlgorithm())
		if err != nil {
			log.Warnf("%v: could not create fingerprint: %v", dbFile.Path(), err)
			continue
		}

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

		fmt.Printf("%v: updated fingerprint\n", dbFile.Path())
	}

	return nil
}
Beispiel #3
0
func determineStatuses(dbFiles entities.Files) (unmodified, modified, missing entities.Files) {
	log.Infof(2, "determining file statuses")

	unmodified = make(entities.Files, 0, 10)
	modified = make(entities.Files, 0, 10)
	missing = make(entities.Files, 0, 10)

	for _, dbFile := range dbFiles {
		stat, err := os.Stat(dbFile.Path())
		if err != nil {
			switch {
			case os.IsPermission(err):
				//TODO return as warning
				log.Warnf("%v: permission denied", dbFile.Path())
				continue
			case os.IsNotExist(err):
				//TODO return as warning
				log.Infof(2, "%v: missing", dbFile.Path())
				missing = append(missing, dbFile)
				continue
			}
		}

		if dbFile.ModTime.Equal(stat.ModTime().UTC()) && dbFile.Size == stat.Size() {
			log.Infof(2, "%v: unmodified", dbFile.Path())
			unmodified = append(unmodified, dbFile)
		} else {
			log.Infof(2, "%v: modified", dbFile.Path())
			modified = append(modified, dbFile)
		}
	}

	return
}
Beispiel #4
0
func createValue(store *storage.Storage, tx *storage.Tx, valueName string) (*entities.Value, error) {
	value, err := store.AddValue(tx, valueName)
	if err != nil {
		return nil, err
	}

	log.Warnf("new value '%v'", valueName)

	return value, nil
}
Beispiel #5
0
func createTag(store *storage.Storage, tx *storage.Tx, tagName string) (*entities.Tag, error) {
	tag, err := store.AddTag(tx, tagName)
	if err != nil {
		return nil, err
	}

	log.Warnf("new tag '%v'", tagName)

	return tag, nil
}
Beispiel #6
0
func initializeDatabase(path string) error {
	log.Warnf("%v: creating database", path)

	tmsuPath := filepath.Join(path, ".tmsu")
	os.Mkdir(tmsuPath, 0755)

	dbPath := filepath.Join(tmsuPath, "db")

	return storage.CreateAt(dbPath)
}
Beispiel #7
0
func directoryEntries(path string) ([]string, error) {
	stat, err := os.Stat(path)
	if err != nil {
		switch {
		case os.IsNotExist(err):
			//TODO return as warning
			log.Warnf("%v: does not exist", path)
			return []string{}, nil
		case os.IsPermission(err):
			//TODO return as warning
			log.Warnf("%v: permission denied", path)
			return []string{}, nil
		default:
			return nil, fmt.Errorf("%v: could not stat", path, err)
		}
	}

	if !stat.IsDir() {
		return []string{}, nil
	}

	dir, err := os.Open(path)
	if err != nil {
		return nil, fmt.Errorf("%v could not open directory", path, err)
	}

	names, err := dir.Readdirnames(0)
	dir.Close()
	if err != nil {
		return nil, fmt.Errorf("%v: could not read directory entries", path, err)
	}

	entries := make([]string, len(names))
	for index, name := range names {
		entries[index] = filepath.Join(path, name)
	}

	return entries, nil
}
Beispiel #8
0
func findNewFiles(searchPath string, report *StatusReport, dirOnly bool) error {
	log.Infof(2, "%v: finding new files.", searchPath)

	relPath := path.Rel(searchPath)

	if !report.ContainsRow(relPath) {
		report.AddRow(Row{relPath, UNTAGGED})
	}

	absPath, err := filepath.Abs(searchPath)
	if err != nil {
		return fmt.Errorf("%v: could not get absolute path: %v", searchPath, err)
	}

	stat, err := os.Stat(absPath)
	if err != nil {
		switch {
		case os.IsNotExist(err):
			return nil
		case os.IsPermission(err):
			log.Warnf("%v: permission denied.", searchPath)
			return nil
		default:
			return fmt.Errorf("%v: could not stat: %v", searchPath, err)
		}
	}

	if !dirOnly && stat.IsDir() {
		dir, err := os.Open(absPath)
		if err != nil {
			return fmt.Errorf("%v: could not open file: %v", searchPath, err)
		}

		dirNames, err := dir.Readdirnames(0)
		if err != nil {
			return fmt.Errorf("%v: could not read directory listing: %v", searchPath, err)
		}

		sort.Strings(dirNames)

		for _, dirName := range dirNames {
			dirPath := filepath.Join(searchPath, dirName)
			err = findNewFiles(dirPath, report, dirOnly)
			if err != nil {
				return err
			}
		}
	}

	return nil
}
Beispiel #9
0
func buildPathBySizeMapRecursive(path string, pathBySizeMap map[int64][]string) error {
	absPath, err := filepath.Abs(path)
	if err != nil {
		return fmt.Errorf("%v: could not get absolute path", path)
	}

	stat, err := os.Stat(absPath)
	if err != nil {
		switch {
		case os.IsPermission(err):
			log.Warnf("%v: permission denied", path)
		default:
			return err
		}
	}

	if stat.IsDir() {
		log.Infof(3, "%v: examining directory contents", absPath)

		dir, err := os.Open(absPath)
		if err != nil {
			return fmt.Errorf("%v: could not open directory: %v", path, err)
		}

		names, err := dir.Readdirnames(0)
		dir.Close()
		if err != nil {
			return fmt.Errorf("%v: could not read directory entries: %v", path, err)
		}

		for _, name := range names {
			childPath := filepath.Join(path, name)
			if err := buildPathBySizeMapRecursive(childPath, pathBySizeMap); err != nil {
				return err
			}
		}
	} else {
		log.Infof(3, "%v: file is of size %v", absPath, stat.Size())

		filesOfSize, ok := pathBySizeMap[stat.Size()]
		if ok {
			pathBySizeMap[stat.Size()] = append(filesOfSize, absPath)
		} else {
			pathBySizeMap[stat.Size()] = []string{absPath}
		}
	}

	return nil
}
Beispiel #10
0
func enumerate(path string, files []FileSystemFile) ([]FileSystemFile, error) {
	stat, err := os.Stat(path)
	if err != nil {
		switch {
		case os.IsNotExist(err):
			return files, nil
		case os.IsPermission(err):
			log.Warnf("%v: permission denied", path)
			return files, nil
		default:
			return nil, fmt.Errorf("%v: could not stat: %v", path, err)
		}
	}

	files = append(files, FileSystemFile{path, stat.IsDir()})

	if stat.IsDir() {
		dir, err := os.Open(path)
		if err != nil {
			return nil, fmt.Errorf("%v: could not open directory: %v", path, err)
		}

		names, err := dir.Readdirnames(0)
		dir.Close()
		if err != nil {
			return nil, fmt.Errorf("%v: could not read directory entries: %v", path, err)
		}

		for _, name := range names {
			childPath := filepath.Join(path, name)
			files, err = enumerate(childPath, files)
			if err != nil {
				return nil, err
			}
		}
	}

	return files, nil
}
Beispiel #11
0
func tagPath(store *storage.Storage, tx *storage.Tx, path string, pairs []entities.TagIdValueIdPair, explicit, recursive, force bool, fileFingerprintAlg, dirFingerprintAlg, symlinkFingerprintAlg string, reportDuplicates bool) error {
	absPath, err := filepath.Abs(path)
	if err != nil {
		return fmt.Errorf("%v: could not get absolute path: %v", path, err)
	}

	stat, err := os.Stat(path)
	if err != nil {
		switch {
		case os.IsNotExist(err), os.IsPermission(err):
			if !force {
				return err
			} else {
				stat = emptyStat{}
			}
		default:
			return err
		}
	}

	log.Infof(2, "%v: checking if file exists in database", path)

	file, err := store.FileByPath(tx, absPath)
	if err != nil {
		return fmt.Errorf("%v: could not retrieve file: %v", path, err)
	}
	if file == nil {
		log.Infof(2, "%v: creating fingerprint", path)

		fp, err := fingerprint.Create(path, fileFingerprintAlg, dirFingerprintAlg, symlinkFingerprintAlg)
		if err != nil {
			if !force || !(os.IsNotExist(err) || os.IsPermission(err)) {
				return fmt.Errorf("%v: could not create fingerprint: %v", path, err)
			}
		}

		if fp != fingerprint.Empty && reportDuplicates {
			log.Infof(2, "%v: checking for duplicates", path)

			count, err := store.FileCountByFingerprint(tx, fp)
			if err != nil {
				return fmt.Errorf("%v: could not identify duplicates: %v", path, err)
			}
			if count != 0 {
				log.Warnf("'%v' is a duplicate", path)
			}
		}

		log.Infof(2, "%v: adding file", path)

		file, err = store.AddFile(tx, path, fp, stat.ModTime(), int64(stat.Size()), stat.IsDir())
		if err != nil {
			return fmt.Errorf("%v: could not add file to database: %v", path, err)
		}
	}

	if !explicit {
		pairs, err = removeAlreadyAppliedTagValuePairs(store, tx, pairs, file)
		if err != nil {
			return fmt.Errorf("%v: could not remove applied tags: %v", path, err)
		}
	}

	log.Infof(2, "%v: applying tags.", path)

	for _, pair := range pairs {
		if _, err = store.AddFileTag(tx, file.Id, pair.TagId, pair.ValueId); err != nil {
			return fmt.Errorf("%v: could not apply tags: %v", file.Path(), err)
		}
	}

	if recursive && stat.IsDir() {
		if err = tagRecursively(store, tx, path, pairs, explicit, force, fileFingerprintAlg, dirFingerprintAlg, symlinkFingerprintAlg, reportDuplicates); err != nil {
			return err
		}
	}

	return nil
}