Commit 7aabf2d9 authored by Ian Lance Taylor's avatar Ian Lance Taylor

Add os.Link, os.Symlink, os.Readlink.

R=r,rsc
DELTA=161  (161 added, 0 deleted, 0 changed)
OCL=28745
CL=28747
parent 52f071ed
......@@ -306,3 +306,30 @@ func Remove(name string) Error {
return ErrnoToError(e);
}
// Link creates a hard link.
func Link(oldpath, newpath string) Error {
r, e := syscall.Link(oldpath, newpath);
return ErrnoToError(e);
}
// Symlink creates a symbolic link.
func Symlink(oldpath, newpath string) Error {
r, e := syscall.Symlink(oldpath, newpath);
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) {
for len := int64(128); ; len *= 2 {
b := make([]byte, len);
r, e := syscall.Readlink(path, &b[0], len);
if r == -1 {
return "", ErrnoToError(e);
} else if r < len {
return string(b[0:r]), nil;
}
}
// Silence 6g.
return "", nil;
}
......@@ -205,3 +205,97 @@ func TestReaddirnamesOneAtATime(t *testing.T) {
}
}
func TestHardLink(t *testing.T) {
from, to := "hardlinktestfrom", "hardlinktestto";
Remove(from); // Just in case.
file, err := Open(to, O_CREAT | O_WRONLY, 0666);
if err != nil {
t.Fatalf("open %q failed: %v", to, err);
}
defer Remove(to);
if err = file.Close(); err != nil {
t.Errorf("close %q failed: %v", to, err);
}
err = Link(to, from);
if err != nil {
t.Fatalf("link %q, %q failed: %v", to, from, err);
}
defer Remove(from);
tostat, err := Stat(to);
if err != nil {
t.Fatalf("stat %q failed: %v", to, err);
}
fromstat, err := Stat(from);
if err != nil {
t.Fatalf("stat %q failed: %v", from, err);
}
if tostat.Dev != fromstat.Dev || tostat.Ino != fromstat.Ino {
t.Errorf("link %q, %q did not create hard link", to, from);
}
}
func TestSymLink(t *testing.T) {
from, to := "symlinktestfrom", "symlinktestto";
Remove(from); // Just in case.
file, err := Open(to, O_CREAT | O_WRONLY, 0666);
if err != nil {
t.Fatalf("open %q failed: %v", to, err);
}
defer Remove(to);
if err = file.Close(); err != nil {
t.Errorf("close %q failed: %v", to, err);
}
err = Symlink(to, from);
if err != nil {
t.Fatalf("symlink %q, %q failed: %v", to, from, err);
}
defer Remove(from);
tostat, err := Stat(to);
if err != nil {
t.Fatalf("stat %q failed: %v", to, err);
}
fromstat, err := Stat(from);
if err != nil {
t.Fatalf("stat %q failed: %v", from, err);
}
if tostat.Dev != fromstat.Dev || tostat.Ino != fromstat.Ino {
t.Errorf("symlink %q, %q did not create symlink", to, from);
}
fromstat, err = Lstat(from);
if err != nil {
t.Fatalf("lstat %q failed: %v", from, err);
}
if !fromstat.IsSymlink() {
t.Fatalf("symlink %q, %q did not create symlink", to, from);
}
s, err := Readlink(from);
if err != nil {
t.Fatalf("readlink %q failed: %v", from, err);
}
if s != to {
t.Fatalf("after symlink %q != %q", s, to);
}
file, err = Open(from, O_RDONLY, 0);
if err != nil {
t.Fatalf("open %q failed: %v", from, err);
}
file.Close();
}
func TestLongSymlink(t *testing.T) {
s := "0123456789abcdef";
s = s + s + s + s + s + s + s + s + s + s + s + s + s + s + s + s + s;
from := "longsymlinktestfrom";
err := Symlink(s, from);
if err != nil {
t.Fatalf("symlink %q, %q failed: %v", s, from, err);
}
defer Remove(from);
r, err := Readlink(from);
if err != nil {
t.Fatalf("readlink %q failed: %v", from, err);
}
if r != s {
t.Fatalf("after symlink %q != %q", r, s);
}
}
......@@ -110,3 +110,23 @@ func Chdir(dir string) (ret int64, errno int64) {
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);
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);
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);
return r1, err;
}
......@@ -111,3 +111,23 @@ func Chdir(dir string) (ret int64, errno int64) {
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);
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);
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);
return r1, err;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment