diff --git a/pkg/bifs/system.go b/pkg/bifs/system.go index d56f0bb66..e2044b4b8 100644 --- a/pkg/bifs/system.go +++ b/pkg/bifs/system.go @@ -102,3 +102,25 @@ func BIF_exec(mlrvals []*mlrval.Mlrval) *mlrval.Mlrval { outputString := strings.TrimRight(string(outputBytes), "\n") return mlrval.FromString(outputString) } + +func BIF_stat(input1 *mlrval.Mlrval) *mlrval.Mlrval { + if !input1.IsStringOrVoid() { + return mlrval.FromNotStringError("system", input1) + } + path := input1.AcquireStringValue() + + fileInfo, err := os.Stat(path) + + if err != nil { + return mlrval.FromError(err) + } + + output := mlrval.NewMlrmap() + output.PutReference("name", mlrval.FromString(fileInfo.Name())) + output.PutReference("size", mlrval.FromInt(fileInfo.Size())) + output.PutReference("mode", mlrval.FromIntShowingOctal(int64(fileInfo.Mode()))) + output.PutReference("modtime", mlrval.FromInt(fileInfo.ModTime().UTC().Unix())) + output.PutReference("isdir", mlrval.FromBool(fileInfo.IsDir())) + + return mlrval.FromMap(output) +} diff --git a/pkg/dsl/cst/builtin_function_manager.go b/pkg/dsl/cst/builtin_function_manager.go index 90f854fe0..ec4bfa980 100644 --- a/pkg/dsl/cst/builtin_function_manager.go +++ b/pkg/dsl/cst/builtin_function_manager.go @@ -2487,6 +2487,23 @@ Run a command via executable, path, args and environment, yielding its stdout mi variadicFunc: bifs.BIF_exec, }, + { + name: "stat", + class: FUNC_CLASS_SYSTEM, + help: `Returns a map containing information about the provided path: "name" with string value, "size" as decimal int value, "mode" as octal int value, "modtime" as int-valued epoch seconds, and "isdir" as boolean value.`, + unaryFunc: bifs.BIF_stat, + examples: []string{ + `stat("./mlr") gives {`, + ` "name": "mlr",`, + ` "size": 38391584,`, + ` "mode": 0755,`, + ` "modtime": 1715207874,`, + ` "isdir": false`, + `}`, + `stat("./mlr")["size"] gives 38391584`, + }, + }, + { name: "version", class: FUNC_CLASS_SYSTEM, diff --git a/pkg/mlrval/mlrval_new.go b/pkg/mlrval/mlrval_new.go index cb548c3d0..c4109af26 100644 --- a/pkg/mlrval/mlrval_new.go +++ b/pkg/mlrval/mlrval_new.go @@ -197,6 +197,15 @@ func FromInt(input int64) *Mlrval { } } +func FromIntShowingOctal(input int64) *Mlrval { + return &Mlrval{ + mvtype: MT_INT, + printrepValid: true, + printrep: fmt.Sprintf("0%o", input), + intf: input, + } +} + // TryFromIntString is used by the mlrval Formatter (fmtnum DSL function, // format-values verb, etc). Each mlrval has printrep and a printrepValid for // its original string, then a type-code like MT_INT or MT_FLOAT, and