mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-13 15:33:40 +00:00
feat: Implement Lchown function for changing file ownership (#5161)
* feat: Implement Lchown function for changing file ownership - Added Lchown function to change the numeric uid and gid of a file or symbolic link. - Included error handling to return *PathError for failed operations. - Added unit tests for Lchown to verify behavior on different error scenarios. * fix: fix chmod tests
This commit is contained in:
@@ -166,6 +166,19 @@ func Chown(name string, uid, gid int) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Lchown changes the numeric uid and gid of the named file.
|
||||||
|
// If the file is a symbolic link, it changes the uid and gid of the link itself.
|
||||||
|
// If there is an error, it will be of type [*PathError].
|
||||||
|
//
|
||||||
|
// If there is an error, it will be of type *PathError.
|
||||||
|
func Lchown(name string, uid, gid int) error {
|
||||||
|
e := ignoringEINTR(func() error { return syscall.Lchown(name, uid, gid) })
|
||||||
|
if e != nil {
|
||||||
|
return &PathError{Op: "lchown", Path: name, Err: e}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// ignoringEINTR makes a function call and repeats it if it returns an
|
// ignoringEINTR makes a function call and repeats it if it returns an
|
||||||
// EINTR error. This appears to be required even though we install all
|
// EINTR error. This appears to be required even though we install all
|
||||||
// signal handlers with SA_RESTART: see #22838, #38033, #38836, #40846.
|
// signal handlers with SA_RESTART: see #22838, #38033, #38836, #40846.
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
. "os"
|
. "os"
|
||||||
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
@@ -70,3 +71,38 @@ func TestChownErr(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLchownErr(t *testing.T) {
|
||||||
|
if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
|
||||||
|
t.Log("skipping on " + runtime.GOOS)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
TEST_UID_ROOT = 0
|
||||||
|
TEST_GID_ROOT = 0
|
||||||
|
)
|
||||||
|
|
||||||
|
f := newFile("TestLchown", t)
|
||||||
|
defer Remove(f.Name())
|
||||||
|
defer f.Close()
|
||||||
|
link := filepath.Join(TempDir(), "TestLchownLink")
|
||||||
|
_ = Symlink(f.Name(), link)
|
||||||
|
defer Remove(link)
|
||||||
|
|
||||||
|
// EACCES
|
||||||
|
if err := Lchown(link, TEST_UID_ROOT, TEST_GID_ROOT); err != nil {
|
||||||
|
errCmp := fs.PathError{Op: "lchown", Path: link, Err: errors.New("operation not permitted")}
|
||||||
|
if errors.Is(err, &errCmp) {
|
||||||
|
t.Fatalf("lchown(%s, uid=%v, gid=%v): got '%v', want 'operation not permitted'", link, TEST_UID_ROOT, TEST_GID_ROOT, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ENOENT
|
||||||
|
if err := Chown("invalid", Geteuid(), Getgid()); err != nil {
|
||||||
|
errCmp := fs.PathError{Op: "lchown", Path: "invalid", Err: errors.New("no such file or directory")}
|
||||||
|
if errors.Is(err, &errCmp) {
|
||||||
|
t.Fatalf("chown(%s, uid=%v, gid=%v): got '%v', want 'no such file or directory'", link, Geteuid(), Getegid(), err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -172,6 +172,15 @@ func Chown(path string, uid, gid int) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Lchown(path string, uid, gid int) (err error) {
|
||||||
|
data := cstring(path)
|
||||||
|
fail := int(libc_lchown(&data[0], uid, gid))
|
||||||
|
if fail < 0 {
|
||||||
|
err = getErrno()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func Fork() (err error) {
|
func Fork() (err error) {
|
||||||
fail := int(libc_fork())
|
fail := int(libc_fork())
|
||||||
if fail < 0 {
|
if fail < 0 {
|
||||||
@@ -368,6 +377,11 @@ func libc_chmod(pathname *byte, mode uint32) int32
|
|||||||
//export chown
|
//export chown
|
||||||
func libc_chown(pathname *byte, owner, group int) int32
|
func libc_chown(pathname *byte, owner, group int) int32
|
||||||
|
|
||||||
|
// int lchown(const char *pathname, uid_t owner, gid_t group);
|
||||||
|
//
|
||||||
|
//export lchown
|
||||||
|
func libc_lchown(pathname *byte, owner, group int) int32
|
||||||
|
|
||||||
// int mkdir(const char *pathname, mode_t mode);
|
// int mkdir(const char *pathname, mode_t mode);
|
||||||
//
|
//
|
||||||
//export mkdir
|
//export mkdir
|
||||||
|
|||||||
Reference in New Issue
Block a user