diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/os/Makefile | 5 | ||||
-rw-r--r-- | src/lib/os/file.go | 60 | ||||
-rw-r--r-- | src/lib/os/os_test.go | 123 | ||||
-rw-r--r-- | src/lib/os/path.go | 121 | ||||
-rw-r--r-- | src/lib/os/path_test.go | 152 | ||||
-rw-r--r-- | src/lib/os/user.go | 61 | ||||
-rw-r--r-- | src/lib/syscall/file_darwin.go | 91 | ||||
-rw-r--r-- | src/lib/syscall/file_linux.go | 40 |
8 files changed, 595 insertions, 58 deletions
diff --git a/src/lib/os/Makefile b/src/lib/os/Makefile index bfcb81dc2..02863cc97 100644 --- a/src/lib/os/Makefile +++ b/src/lib/os/Makefile @@ -3,7 +3,7 @@ # license that can be found in the LICENSE file. # DO NOT EDIT. Automatically generated by gobuild. -# gobuild -m dir_${GOARCH}_${GOOS}.go env.go error.go file.go proc_${GOOS}.go stat_${GOARCH}_${GOOS}.go time.go types.go exec.go user.go >Makefile +# gobuild -m dir_${GOARCH}_${GOOS}.go env.go error.go file.go path.go proc_${GOOS}.go stat_${GOARCH}_${GOOS}.go time.go types.go exec.go user.go >Makefile D= @@ -56,6 +56,7 @@ O3=\ O4=\ dir_$(GOARCH)_$(GOOS).$O\ exec.$O\ + path.$O\ phases: a1 a2 a3 a4 @@ -74,7 +75,7 @@ a3: $(O3) rm -f $(O3) a4: $(O4) - $(AR) grc _obj$D/os.a dir_$(GOARCH)_$(GOOS).$O exec.$O + $(AR) grc _obj$D/os.a dir_$(GOARCH)_$(GOOS).$O exec.$O path.$O rm -f $(O4) diff --git a/src/lib/os/file.go b/src/lib/os/file.go index 19706e3df..d65807326 100644 --- a/src/lib/os/file.go +++ b/src/lib/os/file.go @@ -315,23 +315,23 @@ func Remove(name string) Error { } // Link creates a hard link. -func Link(oldpath, newpath string) Error { - r, e := syscall.Link(oldpath, newpath); +func Link(oldname, newname string) Error { + r, e := syscall.Link(oldname, newname); return ErrnoToError(e); } // Symlink creates a symbolic link. -func Symlink(oldpath, newpath string) Error { - r, e := syscall.Symlink(oldpath, newpath); +func Symlink(oldname, newname string) Error { + r, e := syscall.Symlink(oldname, newname); return ErrnoToError(e); } // Readlink reads the contents of a symbolic link: the destination of // the link. It returns the contents and an Error, if any. -func Readlink(path string) (string, Error) { +func Readlink(name string) (string, Error) { for len := int64(128); ; len *= 2 { b := make([]byte, len); - r, e := syscall.Readlink(path, &b[0], len); + r, e := syscall.Readlink(name, &b[0], len); if r == -1 { return "", ErrnoToError(e); } else if r < len { @@ -341,3 +341,51 @@ func Readlink(path string) (string, Error) { // Silence 6g. return "", nil; } + +// Chmod changes the mode of the named file to mode. +// If the file is a symbolic link, it changes the uid and gid of the link's target. +func Chmod(name string, mode int) Error { + r, e := syscall.Chmod(name, int64(mode)); + return ErrnoToError(e); +} + +// Chmod changes the mode of the file to mode. +func (f *File) Chmod(mode int) Error { + r, e := syscall.Fchmod(f.fd, int64(mode)); + return ErrnoToError(e); +} + +// Chown 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's target. +func Chown(name string, uid, gid int) Error { + r, e := syscall.Chown(name, int64(uid), int64(gid)); + return ErrnoToError(e); +} + +// 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. +func Lchown(name string, uid, gid int) Error { + r, e := syscall.Lchown(name, int64(uid), int64(gid)); + return ErrnoToError(e); +} + +// Chown changes the numeric uid and gid of the named file. +func (f *File) Chown(uid, gid int) Error { + r, e := syscall.Fchown(f.fd, int64(uid), int64(gid)); + return ErrnoToError(e); +} + +// Truncate changes the size of the named file. +// If the file is a symbolic link, it changes the size of the link's target. +func Truncate(name string, size int64) Error { + r, e := syscall.Truncate(name, size); + return ErrnoToError(e); +} + +// Truncate changes the size of the file. +// It does not change the I/O offset. +func (f *File) Truncate(size int64) Error { + r, e := syscall.Ftruncate(f.fd, size); + return ErrnoToError(e); +} + diff --git a/src/lib/os/os_test.go b/src/lib/os/os_test.go index 5c2d68617..b291fd85a 100644 --- a/src/lib/os/os_test.go +++ b/src/lib/os/os_test.go @@ -331,3 +331,126 @@ func TestForkExec(t *testing.T) { } Wait(pid, 0); } + +func checkMode(t *testing.T, path string, mode uint32) { + dir, err := Stat(path); + if err != nil { + t.Fatalf("Stat %q (looking for mode %#o): %s", path, mode, err); + } + if dir.Mode & 0777 != mode { + t.Errorf("Stat %q: mode %#o want %#o", path, dir.Mode, 0777); + } +} + +func TestChmod(t *testing.T) { + MkdirAll("_obj", 0777); + const Path = "_obj/_TestChmod_"; + fd, err := os.Open(Path, os.O_WRONLY | os.O_CREAT, 0666); + if err != nil { + t.Fatalf("create %s: %s", Path, err); + } + + if err = os.Chmod(Path, 0456); err != nil { + t.Fatalf("chmod %s 0456: %s", Path, err); + } + checkMode(t, Path, 0456); + + if err = fd.Chmod(0123); err != nil { + t.Fatalf("fchmod %s 0123: %s", Path, err); + } + checkMode(t, Path, 0123); + + fd.Close(); + Remove(Path); +} + +func checkUidGid(t *testing.T, path string, uid, gid int) { + dir, err := Stat(path); + if err != nil { + t.Fatalf("Stat %q (looking for uid/gid %#o/%#o): %s", path, uid, gid, err); + } + if dir.Uid != uint32(uid) { + t.Errorf("Stat %q: uid %#o want %#o", path, dir.Uid, uid); + } + if dir.Gid != uint32(gid) { + t.Errorf("Stat %q: gid %#o want %#o", path, dir.Gid, uid); + } +} + +func TestChown(t *testing.T) { + // Use /tmp, not _obj, to make sure we're on a local file system, + // so that the group ids returned by Getgroups will be allowed + // on the file. If _obj is on NFS, the Getgroups groups are + // basically useless. + + const Path = "/tmp/_TestChown_"; + fd, err := os.Open(Path, os.O_WRONLY | os.O_CREAT, 0666); + if err != nil { + t.Fatalf("create %s: %s", Path, err); + } + dir, err := fd.Stat(); + if err != nil { + t.Fatalf("fstat %s: %s", Path, err); + } + defer fd.Close(); + defer Remove(Path); + + // Can't change uid unless root, but can try + // changing the group id. First try our current group. + gid := Getgid(); + if err = os.Chown(Path, -1, gid); err != nil { + t.Fatalf("chown %s -1 %d: %s", Path, gid, err); + } + checkUidGid(t, Path, int(dir.Uid), gid); + + // Then try all the auxiliary groups. + groups, err := Getgroups(); + if err != nil { + t.Fatalf("getgroups: %s", err); + } + for i, g := range groups { + if err = os.Chown(Path, -1, g); err != nil { + t.Fatalf("chown %s -1 %d: %s", Path, g, err); + } + checkUidGid(t, Path, int(dir.Uid), g); + + // change back to gid to test fd.Chown + if err = fd.Chown(-1, gid); err != nil { + t.Fatalf("fchown %s -1 %d: %s", Path, gid, err); + } + checkUidGid(t, Path, int(dir.Uid), gid); + } +} + +func checkSize(t *testing.T, path string, size uint64) { + dir, err := Stat(path); + if err != nil { + t.Fatalf("Stat %q (looking for size %d): %s", path, size, err); + } + if dir.Size != size { + t.Errorf("Stat %q: size %d want %d", path, dir.Size, size); + } +} + +func TestTruncate(t *testing.T) { + MkdirAll("_obj", 0777); + const Path = "_obj/_TestTruncate_"; + fd, err := os.Open(Path, os.O_WRONLY | os.O_CREAT, 0666); + if err != nil { + t.Fatalf("create %s: %s", Path, err); + } + + checkSize(t, Path, 0); + fd.Write(io.StringBytes("hello, world\n")); + checkSize(t, Path, 13); + fd.Truncate(10); + checkSize(t, Path, 10); + fd.Truncate(1024); + checkSize(t, Path, 1024); + fd.Truncate(0); + checkSize(t, Path, 0); + fd.Write(io.StringBytes("surprise!")); + checkSize(t, Path, 13 + 9); // wrote at offset past where hello, world was. + fd.Close(); + Remove(Path); +} diff --git a/src/lib/os/path.go b/src/lib/os/path.go new file mode 100644 index 000000000..0b86b8f8b --- /dev/null +++ b/src/lib/os/path.go @@ -0,0 +1,121 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package os + +import "os" + +// PathError reports an error and the file path where it occurred. +type PathError struct { + Path string; + Error Error; +} + +func (p *PathError) String() string { + return p.Path + ": " + p.Error.String(); +} + +// MkdirAll creates a directory named path, +// along with any necessary parents, and returns nil, +// or else returns an error. +// The permission bits perm are used for all +// directories that MkdirAll creates. +// If path is already a directory, MkdirAll does nothing +// and returns nil. +func MkdirAll(path string, perm int) Error { + // If path exists, stop with success or error. + dir, err := os.Lstat(path); + if err == nil { + if dir.IsDirectory() { + return nil; + } + return &PathError{path, ENOTDIR}; + } + + // Doesn't already exist; make sure parent does. + i := len(path); + for i > 0 && path[i-1] == '/' { // Skip trailing slashes. + i--; + } + + j := i; + for j > 0 && path[j-1] != '/' { // Scan backward over element. + j--; + } + + if j > 0 { + // Create parent + err = MkdirAll(path[0:j-1], perm); + if err != nil { + return err; + } + } + + // Now parent exists, try to create. + err = Mkdir(path, perm); + if err != nil { + // Handle arguments like "foo/." by + // double-checking that directory doesn't exist. + dir, err1 := os.Lstat(path); + if err1 == nil && dir.IsDirectory() { + return nil; + } + return &PathError{path, err}; + } + return nil; +} + +// RemoveAll removes path and any children it contains. +// It removes everything it can but returns the first error +// it encounters. +func RemoveAll(path string) Error { + // Simple case: if Remove works, we're done. + err := Remove(path); + if err == nil { + return nil; + } + + // Otherwise, is this a directory we need to recurse into? + dir, err1 := os.Lstat(path); + if err1 != nil { + return &PathError{path, err1}; + } + if !dir.IsDirectory() { + // Not a directory; return the error from Remove. + return &PathError{path, err}; + } + + // Directory. + fd, err := Open(path, os.O_RDONLY, 0); + if err != nil { + return &PathError{path, err}; + } + defer fd.Close(); + + // Remove contents & return first error. + err = nil; + for { + names, err1 := fd.Readdirnames(100); + for i, name := range names { + err1 := RemoveAll(path + "/" + name); + if err1 != nil && err == nil { + err = err1; + } + } + // If Readdirnames returned an error, use it. + if err1 != nil && err == nil { + err = &PathError{path, err1}; + } + if len(names) == 0 { + break; + } + } + + // Remove directory. + err1 = Remove(path); + if err1 != nil && err == nil { + err = &PathError{path, err1}; + } + return err; +} diff --git a/src/lib/os/path_test.go b/src/lib/os/path_test.go new file mode 100644 index 000000000..bb6148920 --- /dev/null +++ b/src/lib/os/path_test.go @@ -0,0 +1,152 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package os + +import ( + "os"; + "testing"; +) + +func TestMkdirAll(t *testing.T) { + // Create new dir, in _obj so it will get + // cleaned up by make if not by us. + path := "_obj/_TestMkdirAll_/dir/./dir2"; + err := MkdirAll(path, 0777); + if err != nil { + t.Fatalf("MkdirAll %q: %s", path, err); + } + + // Already exists, should succeed. + err = MkdirAll(path, 0777); + if err != nil { + t.Fatalf("MkdirAll %q (second time): %s", path, err); + } + + // Make file. + fpath := path + "/file"; + fd, err := os.Open(fpath, os.O_WRONLY | os.O_CREAT, 0666); + if err != nil { + t.Fatalf("create %q: %s", fpath, err); + } + + // Can't make directory named after file. + err = MkdirAll(fpath, 0777); + if err == nil { + t.Fatalf("MkdirAll %q: no error"); + } + perr, ok := err.(*PathError); + if !ok { + t.Fatalf("MkdirAll %q returned %T, not *PathError", fpath, err); + } + if perr.Path != fpath { + t.Fatalf("MkdirAll %q returned wrong error path: %q not %q", fpath, perr.Path, fpath); + } + + // Can't make subdirectory of file. + ffpath := fpath + "/subdir"; + err = MkdirAll(ffpath, 0777); + if err == nil { + t.Fatalf("MkdirAll %q: no error"); + } + perr, ok = err.(*PathError); + if !ok { + t.Fatalf("MkdirAll %q returned %T, not *PathError", ffpath, err); + } + if perr.Path != fpath { + t.Fatalf("MkdirAll %q returned wrong error path: %q not %q", ffpath, perr.Path, fpath); + } + + RemoveAll("_obj/_TestMkdirAll_"); +} + +func TestRemoveAll(t *testing.T) { + // Work directory. + path := "_obj/_TestRemoveAll_"; + fpath := path + "/file"; + dpath := path + "/dir"; + + // Make directory with 1 file and remove. + if err := MkdirAll(path, 0777); err != nil { + t.Fatalf("MkdirAll %q: %s", path, err); + } + fd, err := os.Open(fpath, os.O_WRONLY | os.O_CREAT, 0666); + if err != nil { + t.Fatalf("create %q: %s", fpath, err); + } + fd.Close(); + if err = RemoveAll(path); err != nil { + t.Fatalf("RemoveAll %q (first): %s", path, err); + } + if dir, err := os.Lstat(path); err == nil { + t.Fatalf("Lstat %q succeeded after RemoveAll (first)", path); + } + + // Make directory with file and subdirectory and remove. + if err = MkdirAll(dpath, 0777); err != nil { + t.Fatalf("MkdirAll %q: %s", dpath, err); + } + fd, err = os.Open(fpath, os.O_WRONLY | os.O_CREAT, 0666); + if err != nil { + t.Fatalf("create %q: %s", fpath, err); + } + fd.Close(); + fd, err = os.Open(dpath+"/file", os.O_WRONLY | os.O_CREAT, 0666); + if err != nil { + t.Fatalf("create %q: %s", fpath, err); + } + fd.Close(); + if err = RemoveAll(path); err != nil { + t.Fatalf("RemoveAll %q (second): %s", path, err); + } + if dir, err := os.Lstat(path); err == nil { + t.Fatalf("Lstat %q succeeded after RemoveAll (second)", path); + } + + // Make directory with file and subdirectory and trigger error. + if err = MkdirAll(dpath, 0777); err != nil { + t.Fatalf("MkdirAll %q: %s", dpath, err); + } + + // TODO(rsc): toss tmp once bug152 is fixed + tmp := []string{fpath, dpath+"/file1", path+"/zzz"}; + for i, s := range tmp { + fd, err = os.Open(s, os.O_WRONLY | os.O_CREAT, 0666); + if err != nil { + t.Fatalf("create %q: %s", s, err); + } + fd.Close(); + } + if err = os.Chmod(dpath, 0); err != nil { + t.Fatalf("Chmod %q 0: %s", dpath, err); + } + if err = RemoveAll(path); err == nil { + dir, err := Lstat(path); + if err == nil { + t.Errorf("Can lstat %q after supposed RemoveAll", path); + } + t.Fatalf("RemoveAll %q succeeded with chmod 0 subdirectory", path, err); + } + perr, ok := err.(*PathError); + if !ok { + t.Fatalf("RemoveAll %q returned %T not *PathError", path, err); + } + if perr.Path != dpath { + t.Fatalf("RemoveAll %q failed at %q not %q", path, perr.Path, dpath); + } + if err = os.Chmod(dpath, 0777); err != nil { + t.Fatalf("Chmod %q 0777: %s", dpath, err); + } + for i, s := range []string{fpath, path+"/zzz"} { + if dir, err := os.Lstat(s); err == nil { + t.Fatalf("Lstat %q succeeded after partial RemoveAll", s); + } + } + if err = RemoveAll(path); err != nil { + t.Fatalf("RemoveAll %q after partial RemoveAll: %s", path, err); + } + if dir, err := os.Lstat(path); err == nil { + t.Fatalf("Lstat %q succeeded after RemoveAll (final)", path); + } +} diff --git a/src/lib/os/user.go b/src/lib/os/user.go index abb665b30..1549abdcd 100644 --- a/src/lib/os/user.go +++ b/src/lib/os/user.go @@ -9,41 +9,54 @@ package os import ( "syscall"; "os"; + "unsafe"; ) // Getuid returns the numeric user id of the caller. -func Getuid() (uid int, err Error) { - u, _, e := syscall.Syscall(syscall.SYS_GETUID, 0, 0, 0); - if e != 0 { - return -1, ErrnoToError(e) - } - return int(u), nil +func Getuid() int { + u, r2, e := syscall.Syscall(syscall.SYS_GETUID, 0, 0, 0); + return int(u); } // Geteuid returns the numeric effective user id of the caller. -func Geteuid() (uid int, err Error) { - u, _, e := syscall.Syscall(syscall.SYS_GETEUID, 0, 0, 0); - if e != 0 { - return -1, ErrnoToError(e) - } - return int(u), nil +func Geteuid() int { + u, r2, e := syscall.Syscall(syscall.SYS_GETEUID, 0, 0, 0); + return int(u); } // Getgid returns the numeric group id of the caller. -func Getgid() (uid int, err Error) { - g, _, e := syscall.Syscall(syscall.SYS_GETGID, 0, 0, 0); - if e != 0 { - return -1, ErrnoToError(e) - } - return int(g), nil +func Getgid() int { + g, r2, e := syscall.Syscall(syscall.SYS_GETGID, 0, 0, 0); + return int(g); } // Getegid returns the numeric effective group id of the caller. -func Getegid() (uid int, err Error) { - g, _, e := syscall.Syscall(syscall.SYS_GETEGID, 0, 0, 0); - if e != 0 { - return -1, ErrnoToError(e) - } - return int(g), nil +func Getegid() int { + g, r2, e := syscall.Syscall(syscall.SYS_GETEGID, 0, 0, 0); + return int(g); } +// Getgroups returns a list of the numeric ids of groups that the caller belongs to. +func Getgroups() ([]int, os.Error) { + // first call asks how many there are. + r1, r2, err := syscall.Syscall(syscall.SYS_GETGROUPS, 0, 0, 0); + if err != 0 { + return nil, ErrnoToError(err); + } + + if r1 < 0 || r1 > 1024 { // the current max is 16; 1024 is a future-proof sanity check + return nil, EINVAL; + } + a := make([]int, r1); + if r1 > 0 { + tmp := make([]uint32, r1); + r1, r2, err = syscall.Syscall(syscall.SYS_GETGROUPS, r1, int64(uintptr(unsafe.Pointer(&tmp[0]))), 0); + if err != 0 { + return nil, ErrnoToError(err); + } + for i := 0; i < len(a); i++ { + a[i] = int(tmp[i]); + } + } + return a[0:r1], nil; +} diff --git a/src/lib/syscall/file_darwin.go b/src/lib/syscall/file_darwin.go index 558d66c91..e3c9567e3 100644 --- a/src/lib/syscall/file_darwin.go +++ b/src/lib/syscall/file_darwin.go @@ -13,39 +13,39 @@ import ( const nameBufsize = 512 -func Open(name string, mode int64, perm int64) (ret int64, errno int64) { +func Open(name string, mode int64, perm int64) (ret, errno int64) { namebuf := StringBytePtr(name); r1, r2, err := Syscall(SYS_OPEN, int64(uintptr(unsafe.Pointer(namebuf))), mode, perm); return r1, err; } -func Creat(name string, perm int64) (ret int64, errno int64) { +func Creat(name string, perm int64) (ret, errno int64) { namebuf := StringBytePtr(name); r1, r2, err := Syscall(SYS_OPEN, int64(uintptr(unsafe.Pointer(namebuf))), O_CREAT|O_WRONLY|O_TRUNC, perm); return r1, err; } -func Close(fd int64) (ret int64, errno int64) { +func Close(fd int64) (ret, errno int64) { r1, r2, err := Syscall(SYS_CLOSE, fd, 0, 0); return r1, err; } -func Read(fd int64, buf *byte, nbytes int64) (ret int64, errno int64) { +func Read(fd int64, buf *byte, nbytes int64) (ret, errno int64) { r1, r2, err := Syscall(SYS_READ, fd, int64(uintptr(unsafe.Pointer(buf))), nbytes); return r1, err; } -func Write(fd int64, buf *byte, nbytes int64) (ret int64, errno int64) { +func Write(fd int64, buf *byte, nbytes int64) (ret, errno int64) { r1, r2, err := Syscall(SYS_WRITE, fd, int64(uintptr(unsafe.Pointer(buf))), nbytes); return r1, err; } -func Seek(fd int64, offset int64, whence int64) (ret int64, errno int64) { +func Seek(fd int64, offset int64, whence int64) (ret, errno int64) { r1, r2, err := Syscall(SYS_LSEEK, fd, offset, whence); return r1, err; } -func Pipe(fds *[2]int64) (ret int64, errno int64) { +func Pipe(fds *[2]int64) (ret, errno int64) { r1, r2, err := Syscall(SYS_PIPE, 0, 0, 0); if r1 < 0 { return r1, err; @@ -55,78 +55,117 @@ func Pipe(fds *[2]int64) (ret int64, errno int64) { return 0, 0; } -func Stat(name string, buf *Stat_t) (ret int64, errno int64) { +func Stat(name string, buf *Stat_t) (ret, errno int64) { namebuf := StringBytePtr(name); r1, r2, err := Syscall(SYS_STAT64, int64(uintptr(unsafe.Pointer(namebuf))), int64(uintptr(unsafe.Pointer(buf))), 0); return r1, err; } -func Lstat(name string, buf *Stat_t) (ret int64, errno int64) { +func Lstat(name string, buf *Stat_t) (ret, errno int64) { namebuf := StringBytePtr(name); r1, r2, err := Syscall(SYS_LSTAT64, int64(uintptr(unsafe.Pointer(namebuf))), int64(uintptr(unsafe.Pointer(buf))), 0); return r1, err; } -func Fstat(fd int64, buf *Stat_t) (ret int64, errno int64) { +func Fstat(fd int64, buf *Stat_t) (ret, errno int64) { r1, r2, err := Syscall(SYS_FSTAT64, fd, int64(uintptr(unsafe.Pointer(buf))), 0); return r1, err; } -func Unlink(name string) (ret int64, errno int64) { +func Unlink(name string) (ret, errno int64) { namebuf := StringBytePtr(name); r1, r2, err := Syscall(SYS_UNLINK, int64(uintptr(unsafe.Pointer(namebuf))), 0, 0); return r1, err; } -func Rmdir(name string) (ret int64, errno int64) { +func Rmdir(name string) (ret, errno int64) { namebuf := StringBytePtr(name); r1, r2, err := Syscall(SYS_RMDIR, int64(uintptr(unsafe.Pointer(namebuf))), 0, 0); return r1, err; } -func Fcntl(fd, cmd, arg int64) (ret int64, errno int64) { +func Fcntl(fd, cmd, arg int64) (ret, errno int64) { r1, r2, err := Syscall(SYS_FCNTL, fd, cmd, arg); return r1, err } -func Mkdir(name string, perm int64) (ret int64, errno int64) { +func Mkdir(name string, perm int64) (ret, errno int64) { namebuf := StringBytePtr(name); r1, r2, err := Syscall(SYS_MKDIR, int64(uintptr(unsafe.Pointer(namebuf))), perm, 0); return r1, err; } -func Dup2(fd1, fd2 int64) (ret int64, errno int64) { +func Dup2(fd1, fd2 int64) (ret, errno int64) { r1, r2, err := Syscall(SYS_DUP2, fd1, fd2, 0); return r1, err; } -func Getdirentries(fd int64, buf *byte, nbytes int64, basep *int64) (ret int64, errno int64) { +func Getdirentries(fd int64, buf *byte, nbytes int64, basep *int64) (ret, errno int64) { r1, r2, err := Syscall6(SYS_GETDIRENTRIES64, fd, int64(uintptr(unsafe.Pointer(buf))), nbytes, int64(uintptr(unsafe.Pointer(basep))), 0, 0); return r1, err; } -func Chdir(dir string) (ret int64, errno int64) { +func Chdir(dir string) (ret, errno int64) { namebuf := StringBytePtr(dir); r1, r2, err := Syscall(SYS_CHDIR, int64(uintptr(unsafe.Pointer(namebuf))), 0, 0); return r1, err; } -func Link(oldpath, newpath string) (ret int64, errno int64) { - oldbuf := StringBytePtr(oldpath); - newbuf := StringBytePtr(newpath); +func Link(oldname, newname string) (ret, errno int64) { + oldbuf := StringBytePtr(oldname); + newbuf := StringBytePtr(newname); r1, r2, err := Syscall(SYS_LINK, int64(uintptr(unsafe.Pointer(oldbuf))), int64(uintptr(unsafe.Pointer(newbuf))), 0); return r1, err; } -func Symlink(oldpath, newpath string) (ret int64, errno int64) { - oldbuf := StringBytePtr(oldpath); - newbuf := StringBytePtr(newpath); +func Symlink(oldname, newname string) (ret, errno int64) { + oldbuf := StringBytePtr(oldname); + newbuf := StringBytePtr(newname); r1, r2, err := Syscall(SYS_SYMLINK, int64(uintptr(unsafe.Pointer(oldbuf))), int64(uintptr(unsafe.Pointer(newbuf))), 0); return r1, err; } -func Readlink(path string, buf *byte, nbytes int64) (ret int64, errno int64) { - pathbuf := StringBytePtr(path); - r1, r2, err := Syscall(SYS_READLINK, int64(uintptr(unsafe.Pointer(pathbuf))), int64(uintptr(unsafe.Pointer(buf))), nbytes); +func Readlink(name string, buf *byte, nbytes int64) (ret, errno int64) { + namebuf := StringBytePtr(name); + r1, r2, err := Syscall(SYS_READLINK, int64(uintptr(unsafe.Pointer(namebuf))), int64(uintptr(unsafe.Pointer(buf))), nbytes); + return r1, err; +} + +func Chmod(name string, mode int64) (ret, errno int64) { + namebuf := StringBytePtr(name); + r1, r2, err := Syscall(SYS_CHMOD, int64(uintptr(unsafe.Pointer(namebuf))), mode, 0); + return r1, err; +} + +func Fchmod(fd, mode int64) (ret, errno int64) { + r1, r2, err := Syscall(SYS_FCHMOD, fd, mode, 0); + return r1, err; +} + +func Chown(name string, uid, gid int64) (ret, errno int64) { + namebuf := StringBytePtr(name); + r1, r2, err := Syscall(SYS_CHOWN, int64(uintptr(unsafe.Pointer(namebuf))), uid, gid); + return r1, err; +} + +func Lchown(name string, uid, gid int64) (ret, errno int64) { + namebuf := StringBytePtr(name); + r1, r2, err := Syscall(SYS_LCHOWN, int64(uintptr(unsafe.Pointer(namebuf))), uid, gid); + return r1, err; +} + +func Fchown(fd, uid, gid int64) (ret, errno int64) { + r1, r2, err := Syscall(SYS_FCHOWN, fd, uid, gid); + return r1, err; +} + +func Truncate(name string, length int64) (ret, errno int64) { + namebuf := StringBytePtr(name); + r1, r2, err := Syscall(SYS_TRUNCATE, int64(uintptr(unsafe.Pointer(namebuf))), length, 0); + return r1, err; +} + +func Ftruncate(fd, length int64) (ret, errno int64) { + r1, r2, err := Syscall(SYS_FTRUNCATE, fd, length, 0); return r1, err; } diff --git a/src/lib/syscall/file_linux.go b/src/lib/syscall/file_linux.go index c7299f839..f6b6ea7e6 100644 --- a/src/lib/syscall/file_linux.go +++ b/src/lib/syscall/file_linux.go @@ -131,3 +131,43 @@ func Readlink(path string, buf *byte, nbytes int64) (ret int64, errno int64) { r1, r2, err := Syscall(SYS_READLINK, int64(uintptr(unsafe.Pointer(pathbuf))), int64(uintptr(unsafe.Pointer(buf))), nbytes); return r1, err; } + +func Chmod(name string, mode int64) (ret, errno int64) { + namebuf := StringBytePtr(name); + r1, r2, err := Syscall(SYS_CHMOD, int64(uintptr(unsafe.Pointer(namebuf))), mode, 0); + return r1, err; +} + +func Fchmod(fd, mode int64) (ret, errno int64) { + r1, r2, err := Syscall(SYS_FCHMOD, fd, mode, 0); + return r1, err; +} + +func Chown(name string, uid, gid int64) (ret, errno int64) { + namebuf := StringBytePtr(name); + r1, r2, err := Syscall(SYS_CHOWN, int64(uintptr(unsafe.Pointer(namebuf))), uid, gid); + return r1, err; +} + +func Lchown(name string, uid, gid int64) (ret, errno int64) { + namebuf := StringBytePtr(name); + r1, r2, err := Syscall(SYS_LCHOWN, int64(uintptr(unsafe.Pointer(namebuf))), uid, gid); + return r1, err; +} + +func Fchown(fd, uid, gid int64) (ret, errno int64) { + r1, r2, err := Syscall(SYS_FCHOWN, fd, uid, gid); + return r1, err; +} + +func Truncate(name string, length int64) (ret, errno int64) { + namebuf := StringBytePtr(name); + r1, r2, err := Syscall(SYS_TRUNCATE, int64(uintptr(unsafe.Pointer(namebuf))), length, 0); + return r1, err; +} + +func Ftruncate(fd, length int64) (ret, errno int64) { + r1, r2, err := Syscall(SYS_FTRUNCATE, fd, length, 0); + return r1, err; +} + |