go-perm-test/main_windows.go

134 lines
2.9 KiB
Go
Raw Normal View History

2024-08-19 22:30:30 +00:00
package main
import (
"fmt"
"io/fs"
"os"
"strings"
"zombiezen.com/go/sqlite"
"zombiezen.com/go/sqlite/sqlitex"
)
type Result struct{ Expected, Actual fs.FileMode }
type SQLiteEmitter struct {
conn *sqlite.Conn
}
func (s *SQLiteEmitter) Close() error {
return s.conn.Close()
}
func sqlViewColSpec() string {
var cols []string
var whos = []rune{'o', 'g', 'u'}
var whats = []rune{'x', 'w', 'r'}
for _, fieldName := range []string{"expected", "actual"} {
cols = append(cols, fmt.Sprintf("%s", fieldName))
for iwho, who := range whos {
cols = append(cols, fmt.Sprintf("%[1]s & (7 << %[3]d * 3) >> (%[3]d * 3) AS %[1]s_%[2]c", fieldName, who, iwho))
for iwhat, what := range whats {
cols = append(cols, fmt.Sprintf("%[1]s & (1 << %[3]d * 3 + %[5]d) >> (%[3]d * 3 + %[5]d) AS %[1]s_%[2]c%[4]c", fieldName, who, iwho, what, iwhat))
}
}
}
return strings.Join(cols, ",\n")
}
const createTable = `CREATE TABLE result_raw (
expected INT NOT NULL,
actual INT NOT NULL
);`
var createView string = `CREATE VIEW result AS
SELECT
` + sqlViewColSpec() + `
FROM result_raw;`
func NewSQLite(path string) (*SQLiteEmitter, error) {
conn, err := sqlite.OpenConn(path, sqlite.OpenCreate|sqlite.OpenReadWrite|sqlite.OpenWAL)
if err != nil {
return nil, err
}
fmt.Println(createView)
err = sqlitex.Execute(conn, createTable, &sqlitex.ExecOptions{})
if err != nil {
return nil, fmt.Errorf("NewSQLite: cannot create table: %w", err)
}
err = sqlitex.Execute(conn, createView, &sqlitex.ExecOptions{})
if err != nil {
return nil, fmt.Errorf("NewSQLite: cannot create view: %w", err)
}
return &SQLiteEmitter{
conn: conn,
}, nil
}
func (s *SQLiteEmitter) Emit(r Result) error {
return sqlitex.Execute(s.conn, "INSERT INTO result_raw(expected, actual) VALUES (?, ?)", &sqlitex.ExecOptions{
Args: []any{r.Expected, r.Actual},
})
}
func emitCSV(r Result) error {
_, err := fmt.Printf("%03o,%03o\n", r.Expected, r.Actual)
if err != nil {
return fmt.Errorf("emitCSV: %w", err)
}
return nil
}
func getData(emit func(Result) error) (err error) {
f, err := os.CreateTemp("", "go-perm-test-*")
if err != nil {
return err
}
path := f.Name()
f.Close()
for mode := fs.FileMode(0); mode <= os.ModePerm; mode++ {
err := os.Chmod(path, mode)
if err != nil {
return fmt.Errorf("cannot set mode 0%03o on %s: %w", mode, path, err)
}
info, err := os.Stat(path)
if err != nil {
return fmt.Errorf("cannot stat %s: %w", path, err)
}
result := Result{
Expected: mode,
Actual: info.Mode(),
}
err = emit(result)
if err != nil {
return err
}
}
return nil
}
func run() error {
var emit func(Result) error
if len(os.Args) < 2 {
emit = emitCSV
} else {
dbPath := os.Args[1]
db, err := NewSQLite(dbPath)
if err != nil {
return err
}
defer db.Close()
emit = db.Emit
}
return getData(emit)
}
func main() {
err := run()
if err != nil {
fmt.Fprintf(os.Stderr, "%s: %s\n", os.Args[0], err)
os.Exit(1)
}
}