Skip to content

Commit

Permalink
interp: implement -O and -G tests
Browse files Browse the repository at this point in the history
Implement -O (syntax.TsUsrOwn, "file exists and is owned by the
effective user id") and -G (syntax.TsGrpOwn, "file exists and is owned
by the effective group id") tests, for non-Windows only.

Under Windows, still panics, as before.

-O and -G are hard/not applicable for Windows, since it doesn't really
have the concept of "file owners", only ACLs, and it's not clear how to
translate one to the other.
  • Loading branch information
theclapp authored Jul 13, 2024
1 parent 793d364 commit 3221159
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 0 deletions.
11 changes: 11 additions & 0 deletions interp/os_notunix.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
package interp

import (
"context"
"fmt"

"mvdan.cc/sh/v3/syntax"
)

func mkfifo(path string, mode uint32) error {
Expand All @@ -17,3 +20,11 @@ func mkfifo(path string, mode uint32) error {
func hasPermissionToDir(string) bool {
return true
}

// unTestOwnOrGrp panics. Under Unix, it implements the -O and -G unary tests,
// but under Windows, it's unclear how to implement those tests, since Windows
// doesn't have the concept of a file owner, just ACLs, and it's unclear how
// to map the one to the other.
func (r *Runner) unTestOwnOrGrp(ctx context.Context, op syntax.UnTestOperator, x string) bool {
panic(fmt.Sprintf("unhandled unary test op: %v", op))
}
25 changes: 25 additions & 0 deletions interp/os_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@
package interp

import (
"context"
"os/user"
"strconv"
"syscall"

"golang.org/x/sys/unix"
"mvdan.cc/sh/v3/syntax"
)

func mkfifo(path string, mode uint32) error {
Expand All @@ -18,3 +24,22 @@ func mkfifo(path string, mode uint32) error {
func hasPermissionToDir(path string) bool {
return unix.Access(path, unix.X_OK) == nil
}

// unTestOwnOrGrp implements the -O and -G unary tests. If the file does not
// exist, or the current user cannot be retrieved, returns false.
func (r *Runner) unTestOwnOrGrp(ctx context.Context, op syntax.UnTestOperator, x string) bool {
info, err := r.stat(ctx, x)
if err != nil {
return false
}
u, err := user.Current()
if err != nil {
return false
}
if op == syntax.TsUsrOwn {
uid, _ := strconv.Atoi(u.Uid)
return uint32(uid) == info.Sys().(*syscall.Stat_t).Uid
}
gid, _ := strconv.Atoi(u.Gid)
return uint32(gid) == info.Sys().(*syscall.Stat_t).Gid
}
2 changes: 2 additions & 0 deletions interp/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,8 @@ func (r *Runner) unTest(ctx context.Context, op syntax.UnTestOperator, x string)
return r.lookupVar(x).Kind == expand.NameRef
case syntax.TsNot:
return x == ""
case syntax.TsUsrOwn, syntax.TsGrpOwn:
return r.unTestOwnOrGrp(ctx, op, x)
default:
panic(fmt.Sprintf("unhandled unary test op: %v", op))
}
Expand Down

0 comments on commit 3221159

Please sign in to comment.