1
0
Fork 0
golang-modernc-libc/strace.go
Daniel Baumann 32b8eb3fd7
Adding upstream version 1.65.7.
Signed-off-by: Daniel Baumann <daniel@debian.org>
2025-05-19 21:29:57 +02:00

305 lines
6.2 KiB
Go

// Copyright 2023 The Libc Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build ignore
// +build ignore
package main
import (
"bufio"
"fmt"
"io"
"os"
"os/exec"
"path/filepath"
"strings"
)
func fail(rc int, msg string, args ...any) {
fmt.Fprintln(os.Stderr, strings.TrimSpace(fmt.Sprintf(msg, args...)))
os.Exit(rc)
}
func main() {
m, err := filepath.Glob("*.go")
if err != nil {
fail(1, "%s\n", err)
}
format := false
for _, fn := range m {
b, err := os.ReadFile(fn)
if err != nil {
fail(1, "%s\n", err)
}
a := strings.Split(string(b), "\n")
w := false
for i, v := range a {
if strings.HasPrefix(v, "func X") &&
strings.Contains(v, "*TLS") &&
!strings.Contains(v, "struct") &&
!strings.Contains(v, "interface{") &&
!strings.HasSuffix(v, ",") {
switch {
case strings.Contains(v, "}"):
x := strings.Index(v, "{")
if x < 0 {
panic(fmt.Errorf("%s: %q", fn, v))
}
h := v[:x+1]
t := v[x+1:]
ok, tl := traceLine(fn, h)
if !ok {
continue
}
a[i] = "\n\n" + h + "\n\t" + tl + "\n" + t
w = true
format = true
default:
if i+1 < len(a) && !strings.Contains(a[i+1], "__ccgo_strace") {
ok, tl := traceLine(fn, v)
if !ok {
continue
}
a[i] += "\n\t" + tl
w = true
format = true
}
}
}
}
if w {
if err := os.WriteFile(fn, []byte(strings.Join(a, "\n")), 0660); err != nil {
fail(1, "%s\n", err)
}
}
}
if format {
if out, err := exec.Command("sh", "-c", "gofmt -w *.go").CombinedOutput(); err != nil {
fail(1, "%s FAIL err=%v\n", out, err)
}
}
}
// func Xaio_fsync(tls *TLS, op int32, cb uintptr) (r int32) {
func traceLine(fn, s string) (ok bool, _ string) {
ok = true
var b strings.Builder
parts := strings.Split(s, "(")
for i, v := range parts {
switch i {
case 0:
// "func Xaio_fsync"
case 1:
// "tls *TLS, op int32, cb uintptr) "
a := strings.Split(v, ",") // ["tls *TLS" "op int32" "cb uintptr) "]
b.WriteString(`if __ccgo_strace { trc("`)
var vals []string
for j, w := range a {
w = strings.TrimSpace(w)
if x := strings.Index(w, " "); x > 0 {
w := w[:x]
if w == "_" {
ok = false
}
if j != 0 {
b.WriteString(" ")
}
fmt.Fprintf(&b, "%s=%%v", w)
vals = append(vals, w)
}
}
fmt.Fprintf(&b, `, (%%v:)", %s, origin(2))`, strings.Join(vals, ", "))
case 2:
// "r int32) {"
x := strings.Index(v, " ")
if x < 1 {
panic(fmt.Errorf("%s: %q", fn, s))
}
r := v[:x]
fmt.Fprintf(&b, `; defer func() { trc("-> %%v", %s)}()`, r)
}
}
b.WriteString("}")
return ok, b.String()
}
func mustCopyDir(dst, src string, canOverwrite func(fn string, fi os.FileInfo) bool, srcNotExistsOk bool) (files int, bytes int64) {
file, bytes, err := copyDir(dst, src, canOverwrite, srcNotExistsOk)
if err != nil {
fail(1, "%s\n", err)
}
return file, bytes
}
func copyDir(dst, src string, canOverwrite func(fn string, fi os.FileInfo) bool, srcNotExistsOk bool) (files int, bytes int64, rerr error) {
dst = filepath.FromSlash(dst)
src = filepath.FromSlash(src)
si, err := os.Stat(src)
if err != nil {
if os.IsNotExist(err) && srcNotExistsOk {
err = nil
}
return 0, 0, err
}
if !si.IsDir() {
return 0, 0, fmt.Errorf("cannot copy a file: %s", src)
}
return files, bytes, filepath.Walk(src, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.Mode()&os.ModeSymlink != 0 {
target, err := filepath.EvalSymlinks(path)
if err != nil {
return fmt.Errorf("cannot evaluate symlink %s: %v", path, err)
}
if info, err = os.Stat(target); err != nil {
return fmt.Errorf("cannot stat %s: %v", target, err)
}
if info.IsDir() {
rel, err := filepath.Rel(src, path)
if err != nil {
return err
}
dst2 := filepath.Join(dst, rel)
if err := os.MkdirAll(dst2, 0770); err != nil {
return err
}
f, b, err := copyDir(dst2, target, canOverwrite, srcNotExistsOk)
files += f
bytes += b
return err
}
path = target
}
rel, err := filepath.Rel(src, path)
if err != nil {
return err
}
if info.IsDir() {
return os.MkdirAll(filepath.Join(dst, rel), 0770)
}
n, err := copyFile(filepath.Join(dst, rel), path, canOverwrite)
if err != nil {
return err
}
files++
bytes += n
return nil
})
}
func mustCopyFile(dst, src string, canOverwrite func(fn string, fi os.FileInfo) bool) int64 {
n, err := copyFile(dst, src, canOverwrite)
if err != nil {
fail(1, "%s\n", err)
}
return n
}
func copyFile(dst, src string, canOverwrite func(fn string, fi os.FileInfo) bool) (n int64, rerr error) {
src = filepath.FromSlash(src)
si, err := os.Stat(src)
if err != nil {
return 0, err
}
if si.IsDir() {
return 0, fmt.Errorf("cannot copy a directory: %s", src)
}
dst = filepath.FromSlash(dst)
if si.Size() == 0 {
return 0, os.Remove(dst)
}
dstDir := filepath.Dir(dst)
di, err := os.Stat(dstDir)
switch {
case err != nil:
if !os.IsNotExist(err) {
return 0, err
}
if err := os.MkdirAll(dstDir, 0770); err != nil {
return 0, err
}
case err == nil:
if !di.IsDir() {
return 0, fmt.Errorf("cannot create directory, file exists: %s", dst)
}
}
di, err = os.Stat(dst)
switch {
case err != nil && !os.IsNotExist(err):
return 0, err
case err == nil:
if di.IsDir() {
return 0, fmt.Errorf("cannot overwite a directory: %s", dst)
}
if canOverwrite != nil && !canOverwrite(dst, di) {
return 0, fmt.Errorf("cannot overwite: %s", dst)
}
}
s, err := os.Open(src)
if err != nil {
return 0, err
}
defer s.Close()
r := bufio.NewReader(s)
d, err := os.Create(dst)
defer func() {
if err := d.Close(); err != nil && rerr == nil {
rerr = err
return
}
if err := os.Chmod(dst, si.Mode()); err != nil && rerr == nil {
rerr = err
return
}
if err := os.Chtimes(dst, si.ModTime(), si.ModTime()); err != nil && rerr == nil {
rerr = err
return
}
}()
w := bufio.NewWriter(d)
defer func() {
if err := w.Flush(); err != nil && rerr == nil {
rerr = err
}
}()
return io.Copy(w, r)
}