Skip to content

Commit 67cfddb

Browse files
committed
pkg/codesearch: add dir-index command
dir-index provides a list of subdirectories and files in the given directory in the source tree.
1 parent fc9ef55 commit 67cfddb

File tree

12 files changed

+140
-0
lines changed

12 files changed

+140
-0
lines changed

pkg/aflow/tool/codesearcher/codesearcher.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ import (
1414
)
1515

1616
var Tools = []aflow.Tool{
17+
aflow.NewFuncTool("codesearch-dir-index", dirIndex, `
18+
Tool provides list of source files and subdirectories in the given directory in the source tree.
19+
`),
1720
aflow.NewFuncTool("codesearch-file-index", fileIndex, `
1821
Tool provides list of entities defined in the given source file.
1922
Entity can be function, struct, or global variable.
@@ -54,6 +57,17 @@ type prepareResult struct {
5457
Index index
5558
}
5659

60+
// nolint: lll
61+
type dirIndexArgs struct {
62+
Dir string `jsonschema:"Relative directory in the source tree. Use an empty string for the root of the tree, or paths like 'net/ipv4/' for subdirs."`
63+
}
64+
65+
type dirIndexResult struct {
66+
Missing bool `jsonschema:"Set to true if the requested directory does not exist."`
67+
Subdirs []string `jsonschema:"List of direct subdirectories."`
68+
Files []string `jsonschema:"List of source files."`
69+
}
70+
5771
type fileIndexArgs struct {
5872
SourceFile string `jsonschema:"Source file path."`
5973
}
@@ -130,6 +144,16 @@ func prepare(ctx *aflow.Context, args prepareArgs) (prepareResult, error) {
130144
return prepareResult{index{csIndex}}, err
131145
}
132146

147+
func dirIndex(ctx *aflow.Context, state prepareResult, args dirIndexArgs) (dirIndexResult, error) {
148+
ok, subdirs, files, err := state.Index.DirIndex(args.Dir)
149+
res := dirIndexResult{
150+
Missing: !ok,
151+
Subdirs: subdirs,
152+
Files: files,
153+
}
154+
return res, err
155+
}
156+
133157
func fileIndex(ctx *aflow.Context, state prepareResult, args fileIndexArgs) (fileIndexResult, error) {
134158
ok, entities, err := state.Index.FileIndex(args.SourceFile)
135159
res := fileIndexResult{

pkg/codesearch/codesearch.go

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@ package codesearch
55

66
import (
77
"bytes"
8+
"errors"
89
"fmt"
910
"os"
1011
"path/filepath"
12+
"slices"
1113
"strings"
14+
"syscall"
1215

1316
"github.com/google/syzkaller/pkg/osutil"
1417
)
@@ -26,6 +29,22 @@ type Command struct {
2629

2730
// Commands are used to run unit tests and for the syz-codesearch tool.
2831
var Commands = []Command{
32+
{"dir-index", 1, func(index *Index, args []string) (string, error) {
33+
ok, subdirs, files, err := index.DirIndex(args[0])
34+
if err != nil || !ok {
35+
return notFound, err
36+
}
37+
b := new(strings.Builder)
38+
fmt.Fprintf(b, "directory %v subdirs:\n", args[0])
39+
for _, subdir := range subdirs {
40+
fmt.Fprintf(b, " - %v\n", subdir)
41+
}
42+
fmt.Fprintf(b, "\ndirectory %v files:\n", args[0])
43+
for _, file := range files {
44+
fmt.Fprintf(b, " - %v\n", file)
45+
}
46+
return b.String(), nil
47+
}},
2948
{"file-index", 1, func(index *Index, args []string) (string, error) {
3049
ok, entities, err := index.FileIndex(args[0])
3150
if err != nil || !ok {
@@ -59,6 +78,8 @@ var Commands = []Command{
5978
}},
6079
}
6180

81+
var SourceExtensions = map[string]bool{".c": true, ".h": true, ".S": true, ".rs": true}
82+
6283
const notFound = "not found\n"
6384

6485
func NewIndex(databaseFile string, srcDirs []string) (*Index, error) {
@@ -90,6 +111,32 @@ type Entity struct {
90111
Name string
91112
}
92113

114+
func (index *Index) DirIndex(dir string) (bool, []string, []string, error) {
115+
if err := escaping(dir); err != nil {
116+
return false, nil, nil, nil
117+
}
118+
exists := false
119+
var subdirs, files []string
120+
for _, root := range index.srcDirs {
121+
exists1, subdirs1, files1, err := dirIndex(root, dir)
122+
if err != nil {
123+
return false, nil, nil, err
124+
}
125+
if exists1 {
126+
exists = true
127+
}
128+
subdirs = append(subdirs, subdirs1...)
129+
files = append(files, files1...)
130+
}
131+
slices.Sort(subdirs)
132+
slices.Sort(files)
133+
// Dedup dirs across src/build trees,
134+
// also dedup files, but hopefully there are no duplicates.
135+
subdirs = slices.Compact(subdirs)
136+
files = slices.Compact(files)
137+
return exists, subdirs, files, nil
138+
}
139+
93140
func (index *Index) FileIndex(file string) (bool, []Entity, error) {
94141
var entities []Entity
95142
for _, def := range index.db.Definitions {
@@ -188,3 +235,36 @@ func formatSourceFile(file string, start, end int, includeLines bool) (string, e
188235
}
189236
return b.String(), nil
190237
}
238+
239+
func escaping(path string) error {
240+
if strings.Contains(filepath.Clean(path), "..") {
241+
return errors.New("path is outside of the source tree")
242+
}
243+
return nil
244+
}
245+
246+
func dirIndex(root, subdir string) (bool, []string, []string, error) {
247+
dir := filepath.Join(root, subdir)
248+
entries, err := os.ReadDir(dir)
249+
if err != nil {
250+
if os.IsNotExist(err) {
251+
err = nil
252+
}
253+
var errno syscall.Errno
254+
if errors.As(err, &errno) && errno == syscall.ENOTDIR {
255+
err = nil
256+
}
257+
return false, nil, nil, err
258+
}
259+
var subdirs, files []string
260+
for _, entry := range entries {
261+
if strings.HasPrefix(entry.Name(), ".") {
262+
// These are internal things like .git, etc.
263+
} else if entry.IsDir() {
264+
subdirs = append(subdirs, entry.Name())
265+
} else if SourceExtensions[filepath.Ext(entry.Name())] {
266+
files = append(files, entry.Name())
267+
}
268+
}
269+
return true, subdirs, files, err
270+
}

pkg/codesearch/testdata/mm/.slub.c

Whitespace-only changes.

pkg/codesearch/testdata/mm/slub.c

Whitespace-only changes.

pkg/codesearch/testdata/mm/slub.h

Whitespace-only changes.

pkg/codesearch/testdata/mm/slub.o

Whitespace-only changes.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
dir-index mm/../../
2+
3+
not found
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
dir-index source0.c
2+
3+
not found
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
dir-index mm/foobar
2+
3+
not found
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
dir-index /mm/
2+
3+
directory /mm/ subdirs:
4+
5+
directory /mm/ files:
6+
- slub.c
7+
- slub.h

0 commit comments

Comments
 (0)