blob: b53c9e1d21da16625b15ebc21997bf3b9200334a [file] [edit]
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package scanapi defines the Localtoast scan API
// used to provide access to a local or remote filesystem and database to perform scans.
package scanapi
import (
"context"
"errors"
"io"
apb "github.com/google/localtoast/scannerlib/proto/api_go_proto"
ipb "github.com/google/localtoast/scannerlib/proto/scan_instructions_go_proto"
)
var (
// ErrEntryBeforeNext is the error returned if Entry() is called
// and Next() was never called for a DirReader.
ErrEntryBeforeNext = errors.New("Entry called before Next")
// ErrNoMoreEntries is the error returned if Entry() is called
// after Next() returned false for a DirReader.
ErrNoMoreEntries = errors.New("Entry called with no more entries")
)
// Filesystem is an interface that gives read access to the filesystem of the machine to scan.
type Filesystem interface {
// OpenFile opens the specified file for reading.
// It should return an os.IsNotExist error if the file doesn't exist.
OpenFile(ctx context.Context, path string) (io.ReadCloser, error)
// FilePermissions returns unix permission-related data for the specified file or directory.
FilePermissions(ctx context.Context, path string) (*apb.PosixPermissions, error)
// OpenDir opens the specified directory to list its content.
OpenDir(ctx context.Context, path string) (DirReader, error)
}
// SQLQuerier is an interface that supports SQL queries to a target SQL database.
type SQLQuerier interface {
// SQLQuery executes SQL queries to a target SQL database and returns the number of result rows.
SQLQuery(ctx context.Context, query string) (int, error)
// SQLQueryWithResponse execute Query and returns the Response as string
SQLQueryWithResponse(ctx context.Context, query string) (string, error)
// Returns the supported database type
SupportedDatabase() (ipb.SQLCheck_SQLDatabase, error)
}
// ScanAPI is an interface that gives read access to the filesystem of
// the machine to scan and can execute SQL queries on a single database.
type ScanAPI interface {
Filesystem
SQLQuerier
}
// DirReader is an interface to iterate the entries inside a directory.
type DirReader interface {
// Next reads the next entry in the directory which can then be accessed using Entry.
// It must be called at least once before calling Entry.
// Returns false if there are no more entries in the directory.
Next() bool
// Entry returns the last entry read using Next or an error if it failed.
Entry() (*apb.DirContent, error)
// Close must be called to correctly dispose of the underlying reader.
Close() error
}
type sliceDirReader struct {
entries []*apb.DirContent
idx int
}
func (s *sliceDirReader) Next() bool {
s.idx++
return s.idx < len(s.entries)
}
func (s *sliceDirReader) Entry() (*apb.DirContent, error) {
if s.idx == -1 {
return nil, ErrEntryBeforeNext
}
if s.idx >= len(s.entries) {
return nil, ErrNoMoreEntries
}
return s.entries[s.idx], nil
}
func (s *sliceDirReader) Close() error {
s.idx = len(s.entries)
return nil
}
// SliceToDirReader returns a DirReader given a slice of entries.
func SliceToDirReader(entries []*apb.DirContent) DirReader {
return &sliceDirReader{entries: entries, idx: -1}
}
// DirReaderToSlice returns a slice of all the entries left in the given DirReader.
// The DirReader is automatically disposed of by calling Close() at the end.
func DirReaderToSlice(d DirReader) ([]*apb.DirContent, error) {
defer d.Close()
entries := make([]*apb.DirContent, 0)
for d.Next() {
e, err := d.Entry()
if err != nil {
return nil, err
}
entries = append(entries, e)
}
return entries, nil
}