This commit is contained in:
Yuvia 2025-08-12 20:45:14 +00:00
commit a2ed5b669d
2 changed files with 381 additions and 0 deletions

3
go.mod Normal file
View file

@ -0,0 +1,3 @@
module yuvia/gols
go 1.23.9

378
gols.go Normal file
View file

@ -0,0 +1,378 @@
package main
import (
"fmt"
"io/fs"
"log"
"os"
"slices"
"strings"
"syscall"
"time"
)
/*
gols
Throughout the program, the simple approach (the braindead one), was the most taken one.
*/
var modes = map[uint32]string{
0: "---",
1: "--x",
2: "-w-",
3: "-wx",
4: "r--",
5: "r-x",
6: "rw-",
7: "rwx",
}
var vwidth int = 1
var uwidth int = 1
var gwidth int = 1
var lwidth int = 1
var swidth int = 1
var mwidth int = 1
var qwidth int = 1
var now int64
var dflag bool = false
var lflag bool = false
var mflag bool = false
var nflag bool = false
var pflag bool = false
var qflag bool = false
var Qflag bool = false
var rflag bool = false
var sflag bool = false
var tflag bool = false
var Tflag bool = false
var uflag bool = false
var Fflag bool = false
// there is an objectively better way to do this.
// i wont do it though, not feeling like it XXX
func parseargs(args []string) int {
var i int
var j int
if len(args) == 0 {
return 0
} else if args[0][0] != '-' {
return 0
}
for i = 0; i < len(args); i++ {
if args[i][0] != '-' {
break
}
if args[i] == "-" || args[i] == "--" { // the people are dumb
break
}
for j = 1; j < len(args[i]); j++ {
switch args[i][j] {
case 'F':
Fflag = true
case 'd':
dflag = true
case 'l':
lflag = true
case 'm':
mflag = true
case 'n':
nflag = true
case 'p':
pflag = true
case 'q':
qflag = true
case 'Q':
Qflag = true
case 'r':
rflag = true
case 's':
sflag = true
case 't':
tflag = true
case 'T':
Tflag = true
case 'u':
uflag = true
default:
fmt.Println(args[i], args[i][j])
fmt.Fprintln(os.Stderr, "usage: gls [-dlmnpqrstuFQT] [file ...]")
os.Exit(1)
}
}
}
return i
}
func main() {
args := os.Args[1:]
flag := false
optind := parseargs(args)
if pflag {
flag = true
}
if lflag {
now = time.Now().Unix()
}
if len(args[optind:]) == 0 {
widths([]string{"."})
err := ls(".", true)
if err != nil {
log.Fatal(err)
}
}
widths(args[optind:])
for _, arg := range args[optind:] {
err := ls(arg, flag)
if err != nil {
log.Fatal(err)
}
}
}
func widths(args []string) {
for _, a := range args {
st, err := os.Lstat(a)
if err != nil {
log.Fatal(err)
}
if st.IsDir() && !dflag {
d, err := os.ReadDir(a)
if err != nil {
log.Fatal(err)
}
for _, ent := range d {
dowidths(ent)
}
} else {
dowidths(fs.FileInfoToDirEntry(st))
}
}
}
func compar(a os.DirEntry, b os.DirEntry) int {
if tflag {
if uflag {
ai, _ := a.Info()
as := ai.Sys().(*syscall.Dir)
bi, _ := b.Info()
bs := bi.Sys().(*syscall.Dir)
if as.Atime-bs.Atime > 0 {
return -1
} else {
return 1
}
} else {
ai, _ := a.Info()
bi, _ := b.Info()
if ai.ModTime().Unix()-bi.ModTime().Unix() > 0 {
return -1
} else {
return 1
}
}
} else {
return strings.Compare(a.Name(), b.Name())
}
}
func ls(p string, flag bool) error {
st, err := os.Lstat(p)
if err != nil {
return err
}
if st.IsDir() && !dflag {
d, err := os.ReadDir(p)
if err != nil {
return err
}
if !nflag {
slices.SortFunc(d, compar)
if rflag {
slices.Reverse(d)
}
}
for _, ent := range d {
i, err := ent.Info()
if err != nil {
log.Fatalf("the fuck?: %s\n", err)
}
output(i, p, flag)
}
} else {
output(st, p, flag)
}
return nil
}
/*
as seen from /sys/src/cmd/ls.c, in xcleanname:
Compress slashes, remove trailing slash. Don't worry about . and ..
*/
func cleanname(s string) string {
if len(s) == 1 {
return s
}
b := new(strings.Builder)
prev := ' ' // ;)
for _, c := range s {
if c == '/' && prev == '/' {
prev = c
continue
}
prev = c
b.WriteRune(c)
}
ret := b.String()
if ret[len(ret)-1] == '/' {
return ret[:len(ret)-2]
} else {
return ret
}
}
func getpropername(p, f string, flag bool) string {
var c string
quot := false
quoters := "# '"
if !flag {
if p == "/" {
p = ""
}
c = p + "/" + f
} else {
c = f
}
quot = strings.ContainsAny(c, quoters)
if quot {
b := new(strings.Builder)
b.WriteByte('\'')
for _, e := range c {
b.WriteRune(e)
if e == '\'' {
b.WriteRune(e)
}
}
b.WriteByte('\'')
return b.String()
} else {
return c
}
}
func fileflag(s *syscall.Dir) string {
if !Fflag {
return ""
}
if s.Qid.Type&syscall.QTDIR == syscall.QTDIR {
return "/"
}
if s.Mode&0111 > 0 {
return "*"
}
return ""
}
func output(i os.FileInfo, p string, flag bool) {
p = cleanname(p)
s := (i.Sys().(*syscall.Dir))
if sflag {
fmt.Printf("%*d ", swidth, (i.Size()+1023)/1024)
}
if mflag {
m := getpropername("", s.Muid, true)
fmt.Printf("[%*s] ", mwidth, m)
}
if qflag {
fmt.Printf("(%.16x %*d %.2x) ", s.Qid.Path, qwidth, s.Qid.Vers, s.Qid.Type)
}
if Tflag {
if s.Mode&syscall.DMTMP == syscall.DMTMP {
fmt.Print("t ")
} else {
fmt.Print("- ")
}
}
if lflag {
t := time.Unix(int64(s.Mtime), 0)
fmt.Printf("%s %c %*d %-*s %-*s %*d ", modestr(s.Mode), s.Type, vwidth, s.Dev, uwidth, s.Uid, gwidth, s.Gid, lwidth, i.Size())
if uflag {
t = time.Unix(int64(s.Atime), 0)
}
if t.Unix() < now-180*24*60*60 || t.Unix() > now+24*60*60 {
fmt.Printf("%s %5s ", t.Format("Jan _2"), t.Format("2006"))
} else {
fmt.Printf("%s ", t.Format("Jan _2 15:04"))
}
}
name := getpropername(p, i.Name(), flag)
fmt.Printf("%s%s\n", name, fileflag(s))
}
func modestr(m uint32) string {
b := new(strings.Builder)
if m&syscall.DMDIR == syscall.DMDIR {
b.WriteByte('d')
} else if m&syscall.DMAPPEND == syscall.DMAPPEND {
b.WriteByte('a')
} else if m&syscall.DMAUTH == syscall.DMAUTH {
b.WriteByte('A')
} else {
b.WriteByte('-')
}
if m&syscall.DMEXCL == syscall.DMEXCL {
b.WriteByte('l')
} else {
b.WriteByte('-')
}
b.WriteString(modes[m>>6&7])
b.WriteString(modes[m>>3&7])
b.WriteString(modes[m&7])
return b.String()
}
func dowidths(d os.DirEntry) {
i, _ := d.Info()
y := (i.Sys().(*syscall.Dir))
if sflag {
s := fmt.Sprint((i.Size() + 1023) / 1024)
if len(s) > swidth {
swidth = len(s)
}
}
if qflag {
s := fmt.Sprint(y.Qid.Vers)
if len(s) > qwidth {
qwidth = len(s)
}
}
if mflag {
s := fmt.Sprint(y.Muid)
if len(s) > mwidth {
mwidth = len(s)
}
}
if lflag {
s := fmt.Sprint(y.Dev)
if len(s) > vwidth {
vwidth = len(s)
}
s = fmt.Sprint(y.Uid)
if len(s) > uwidth {
uwidth = len(s)
}
s = fmt.Sprint(y.Gid)
if len(s) > gwidth {
gwidth = len(s)
}
s = fmt.Sprint(i.Size())
if len(s) > lwidth {
lwidth = len(s)
}
}
}