1 // sysfile_posix.go -- POSIX File handling.
3 // Copyright 2010 The Go Authors. All rights reserved.
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file.
7 // Support for basic Unix file operations. This file simply
8 // translates from Go data types to Unix data types, and handles
9 // errno. FIXME: This could probably be done mechanically.
15 func libc_open(name
*byte, mode
int, perm Mode_t
) int __asm__ ("open");
16 func libc_close(fd
int) int __asm__ ("close");
17 func libc_read(fd
int, buf
*byte, count Size_t
) Ssize_t
__asm__ ("read");
18 func libc_write(fd
int, buf
*byte, count Size_t
) Ssize_t
__asm__ ("write");
19 func libc_fsync(fd
int) int __asm__ ("fsync")
20 func libc_pipe(filedes
*int) int __asm__("pipe");
21 func libc_unlink(name
*byte) int __asm__ ("unlink");
22 func libc_rmdir(name
*byte) int __asm__ ("rmdir");
23 func libc_fcntl(fd
int, cmd
int, arg
int) int __asm__ ("fcntl");
24 func libc_mkdir(name
*byte, perm Mode_t
) int __asm__ ("mkdir");
25 func libc_dup(int) int __asm__ ("dup")
26 func libc_gettimeofday(tv
*Timeval
, tz
*byte) int __asm__ ("gettimeofday");
27 func libc_select(int, *byte, *byte, *byte, *Timeval
) int __asm__ ("select");
28 func libc_chdir(name
*byte) int __asm__ ("chdir");
29 func libc_fchdir(int) int __asm__ ("fchdir");
30 func libc_getcwd(*byte, Size_t
) *byte __asm__ ("getcwd");
31 func libc_link(oldpath
*byte, newpath
*byte) int __asm__ ("link");
32 func libc_symlink(oldpath
*byte, newpath
*byte) int __asm__ ("symlink");
33 func libc_readlink(*byte, *byte, Size_t
) Ssize_t
__asm__ ("readlink");
34 func libc_rename(oldpath
*byte, newpath
*byte) int __asm__ ("rename");
35 func libc_chmod(path
*byte, mode Mode_t
) int __asm__ ("chmod");
36 func libc_fchmod(fd
int, mode Mode_t
) int __asm__ ("fchmod");
37 func libc_chown(path
*byte, owner Uid_t
, group Gid_t
) int __asm__ ("chown");
38 func libc_fchown(fd
int, owner Uid_t
, group Gid_t
) int __asm__ ("fchown");
39 func libc_lchown(path
*byte, owner Uid_t
, group Gid_t
) int __asm__ ("lchown");
40 func libc_utimes(filename
*byte, times
*[2]Timeval
) int __asm__ ("utimes");
41 func libc_getuid() Uid_t
__asm__ ("getuid");
42 func libc_geteuid() Uid_t
__asm__ ("geteuid");
43 func libc_getgid() Gid_t
__asm__ ("getgid");
44 func libc_getegid() Gid_t
__asm__ ("getegid");
45 func libc_getgroups(size
int, list
*Gid_t
) int __asm__ ("getgroups");
46 func libc_getpagesize() int __asm__ ("getpagesize");
47 func libc_exit(status
int) __asm__ ("exit")
48 func libc_getpid() Pid_t
__asm__ ("getpid")
49 func libc_getppid() Pid_t
__asm__ ("getppid")
50 func libc_kill(Pid_t
, int) int __asm__ ("kill")
52 func Open(name
string, mode
int, perm
uint32) (fd
int, errno
int) {
53 fd
= libc_open(StringBytePtr(name
), mode
, Mode_t(perm
));
54 if fd
< 0 { errno
= GetErrno() }
58 func Creat(name
string, perm
uint32) (fd
int, errno
int) {
59 fd
= libc_open(StringBytePtr(name
), O_CREAT | O_WRONLY | O_TRUNC
, Mode_t(perm
));
60 if fd
< 0 { errno
= GetErrno() }
64 func Close(fd
int) (errno
int) {
66 if r
< 0 { errno
= GetErrno() }
70 func Read(fd
int, p
[]byte) (n
int, errno
int) {
72 if len(p
) > 0 { _p0
= &p
[0]; }
73 r
:= libc_read(fd
, _p0
, Size_t(len(p
)));
74 if r
== -1 { errno
= GetErrno() }
79 func Write(fd
int, p
[]byte) (n
int, errno
int) {
81 if len(p
) > 0 { _p0
= &p
[0]; }
82 r
:= libc_write(fd
, _p0
, Size_t(len(p
)));
83 if r
== -1 { errno
= GetErrno() }
88 func Fsync(fd
int) (errno
int) {
89 if libc_fsync(fd
) < 0 {
95 func Pread(fd
int, p
[]byte, offset
int64) (n
int, errno
int) {
97 if len(p
) > 0 { _p0
= &p
[0]; }
98 r
:= libc_pread(fd
, _p0
, Size_t(len(p
)), Offset_t(offset
));
99 if r
== -1 { errno
= GetErrno() }
104 func Pwrite(fd
int, p
[]byte, offset
int64) (n
int, errno
int) {
106 if len(p
) > 0 { _p0
= &p
[0]; }
107 r
:= libc_pwrite(fd
, _p0
, Size_t(len(p
)), Offset_t(offset
));
108 if r
== -1 { errno
= GetErrno() }
113 func Seek(fd
int, offset
int64, whence
int) (off
int64, errno
int) {
114 r
:= libc_lseek(fd
, Offset_t(offset
), whence
);
115 if r
== -1 { errno
= GetErrno() }
120 func Pipe(p
[]int) (errno
int) {
125 r
:= libc_pipe(&pp
[0]);
134 func Stat(name
string, buf
*Stat_t
) (errno
int) {
135 r
:= libc_stat(StringBytePtr(name
), buf
);
136 if r
< 0 { errno
= GetErrno() }
140 func Lstat(name
string, buf
*Stat_t
) (errno
int) {
141 r
:= libc_lstat(StringBytePtr(name
), buf
);
142 if r
< 0 { errno
= GetErrno() }
146 func Fstat(fd
int, buf
*Stat_t
) (errno
int) {
147 r
:= libc_fstat(fd
, buf
);
148 if r
< 0 { errno
= GetErrno() }
152 func Unlink(name
string) (errno
int) {
153 r
:= libc_unlink(StringBytePtr(name
));
154 if r
< 0 { errno
= GetErrno() }
158 func Rmdir(name
string) (errno
int) {
159 r
:= libc_rmdir(StringBytePtr(name
));
160 if r
< 0 { errno
= GetErrno() }
164 func Mkdir(path
string, mode
uint32) (errno
int) {
165 r
:= libc_mkdir(StringBytePtr(path
), Mode_t(mode
));
166 if r
< 0 { errno
= GetErrno() }
170 func Dup(oldfd
int) (fd
int, errno
int) {
178 func Gettimeofday(tv
*Timeval
) (errno
int) {
179 r
:= libc_gettimeofday(tv
, nil);
180 if r
< 0 { errno
= GetErrno() }
184 const nfdbits
= unsafe
.Sizeof(fds_bits_type
) * 8
186 type FdSet_t
struct {
187 Fds_bits
[(FD_SETSIZE
+ nfdbits
- 1) / nfdbits
]fds_bits_type
190 func FDSet(fd
int, set
*FdSet_t
) {
191 set
.Fds_bits
[fd
/ nfdbits
] |
= (1 << (uint)(fd
% nfdbits
))
194 func FDClr(fd
int, set
*FdSet_t
) {
195 set
.Fds_bits
[fd
/ nfdbits
] &^= (1 << (uint)(fd
% nfdbits
))
198 func FDIsSet(fd
int, set
*FdSet_t
) bool {
199 if set
.Fds_bits
[fd
/ nfdbits
] & (1 << (uint)(fd
% nfdbits
)) != 0 {
206 func FDZero(set
*FdSet_t
) {
207 for i
:= range set
.Fds_bits
{
212 func Select(nfds
int, r
*FdSet_t
, w
*FdSet_t
, e
*FdSet_t
, timeout
*Timeval
) (n
int, errno
int) {
213 n
= libc_select(nfds
, (*byte)(unsafe
.Pointer(r
)),
214 (*byte)(unsafe
.Pointer(w
)),
215 (*byte)(unsafe
.Pointer(e
)), timeout
);
216 if n
< 0 { errno
= GetErrno() }
220 func Chdir(path
string) (errno
int) {
221 r
:= libc_chdir(StringBytePtr(path
));
222 if r
< 0 { errno
= GetErrno() }
226 func Fchdir(fd
int) (errno
int) {
227 r
:= libc_fchdir(int(fd
));
228 if r
< 0 { errno
= GetErrno() }
232 const ImplementsGetwd
= true
234 func Getwd() (ret
string, errno
int) {
235 for len := Size_t(4096); ; len *= 2 {
236 b
:= make([]byte, len);
237 p
:= libc_getcwd(&b
[0], len);
243 return string(b
[0:i
]), 0;
252 func Link(oldpath
, newpath
string) (errno
int) {
253 r
:= libc_link(StringBytePtr(oldpath
), StringBytePtr(newpath
));
254 if r
< 0 { errno
= GetErrno() }
258 func Symlink(oldpath
, newpath
string) (errno
int) {
259 r
:= libc_symlink(StringBytePtr(oldpath
), StringBytePtr(newpath
));
260 if r
< 0 { errno
= GetErrno() }
264 func Readlink(path
string, buf
[]byte) (n
int, errno
int) {
266 if len(buf
) > 0 { _p0
= &buf
[0]; }
267 r
:= libc_readlink(StringBytePtr(path
), _p0
, Size_t(len(buf
)));
268 if r
< 0 { errno
= GetErrno() }
273 func Rename(oldpath
, newpath
string) (errno
int) {
274 r
:= libc_rename(StringBytePtr(oldpath
), StringBytePtr(newpath
));
275 if r
< 0 { errno
= GetErrno() }
279 func Chmod(path
string, mode
uint32) (errno
int) {
280 r
:= libc_chmod(StringBytePtr(path
), Mode_t(mode
));
281 if r
< 0 { errno
= GetErrno() }
285 func Fchmod(fd
int, mode
uint32) (errno
int) {
286 r
:= libc_fchmod(fd
, Mode_t(mode
));
287 if r
< 0 { errno
= GetErrno() }
291 func Chown(path
string, uid
int, gid
int) (errno
int) {
292 r
:= libc_chown(StringBytePtr(path
), Uid_t(uid
), Gid_t(gid
));
293 if r
< 0 { errno
= GetErrno() }
297 func Lchown(path
string, uid
int, gid
int) (errno
int) {
298 r
:= libc_lchown(StringBytePtr(path
), Uid_t(uid
), Gid_t(gid
));
299 if r
< 0 { errno
= GetErrno() }
303 func Fchown(fd
int, uid
int, gid
int) (errno
int) {
304 r
:= libc_fchown(fd
, Uid_t(uid
), Gid_t(gid
));
305 if r
< 0 { errno
= GetErrno() }
309 func Truncate(path
string, length
int64) (errno
int) {
310 r
:= libc_truncate(StringBytePtr(path
), Offset_t(length
));
311 if r
< 0 { errno
= GetErrno() }
315 func Ftruncate(fd
int, length
int64) (errno
int) {
316 r
:= libc_ftruncate(fd
, Offset_t(length
));
317 if r
< 0 { errno
= GetErrno() }
321 func Utimes(path
string, tv
[]Timeval
) (errno
int) {
325 r
:= libc_utimes(StringBytePtr(path
),
326 (*[2]Timeval
)(unsafe
.Pointer(&tv
[0])));
333 // Getuid returns the numeric user id of the caller.
335 return int(libc_getuid());
338 // Geteuid returns the numeric effective user id of the caller.
340 return int(libc_geteuid());
343 // Getgid returns the numeric group id of the caller.
345 return int(libc_getgid());
348 // Getegid returns the numeric effective group id of the caller.
350 return int(libc_getegid());
353 // Getgroups returns a list of the numeric ids of groups that the caller belongs to.
354 func Getgroups() (gids
[]int, errno
int) {
355 n
:= libc_getgroups(0, nil);
357 return nil, GetErrno();
363 // Sanity check group count. Max is 1<<16 on Linux.
364 if n
< 0 || n
> 1<<20 {
368 a
:= make([]Gid_t
, n
);
369 n
= libc_getgroups(n
, &a
[0]);
371 return nil, GetErrno();
373 gids
= make([]int, n
);
374 for i
, v
:= range a
[0:n
] {
380 func Getpagesize() int {
381 return libc_getpagesize();
384 func TimespecToNsec(ts Timespec
) int64 {
385 return int64(ts
.Sec
)*1e9
+ int64(ts
.Nsec
);
388 func NsecToTimespec(nsec
int64) (ts Timespec
) {
389 ts
.Sec
= Timespec_sec_t(nsec
/ 1e9
);
390 ts
.Nsec
= Timespec_nsec_t(nsec
% 1e9
);
394 func TimevalToNsec(tv Timeval
) int64 {
395 return int64(tv
.Sec
)*1e9
+ int64(tv
.Usec
)*1e3
;
398 func NsecToTimeval(nsec
int64) (tv Timeval
) {
399 nsec
+= 999; // round up to microsecond
400 tv
.Sec
= Timeval_sec_t(nsec
/1e9
);
401 tv
.Usec
= Timeval_usec_t(nsec%1e9
/ 1e3
);
405 func Exit(code
int) {
409 func fcntl(fd
, cmd
, arg
int) (val
int, errno
int) {
410 val
= libc_fcntl(int(fd
), int(cmd
), int(arg
));
411 if val
== -1 { errno
= GetErrno() }
415 func Getpid() (pid
int) {
416 return int(libc_getpid());
419 func Getppid() (ppid
int) {
420 return int(libc_getppid());
423 func Kill(pid
int, sig
int) (errno
int) {
424 r
:= libc_kill(Pid_t(pid
), sig
)