1 module runtime.system.posix.posix_;
2 
3 ushort octal(int octal) nothrow @nogc
4 {
5     ushort result;
6 
7     result += octal % 10;
8     octal /= 10;
9     result += 8 * (octal % 10);
10     octal /= 10;
11     result += (8 * 8) * (octal % 10);
12     octal /= 10;
13     result += (8 * 8 * 8) * (octal % 10);
14     octal /= 10;
15     result += (8 * 8 * 8 * 8) * (octal % 10);
16     octal /= 10;
17     result += (8 * 8 * 8 * 8 * 8) * (octal % 10);
18     octal /= 10;
19     result += (8 * 8 * 8 * 8 * 8 * 8) * (octal % 10);
20     octal /= 10;
21     result += (8 * 8 * 8 *8 * 8 * 8 * 8) * (octal % 10);
22     octal /= 10;
23 
24     assert(octal == 0);
25 
26     return result;
27 }
28 @("octal")
29 unittest
30 {
31     assert(octal(666) == 0x1B6);
32 }
33 
34 version(Posix) extern(C) nothrow @nogc:
35 
36 enum 
37 {
38     PROT_NONE = 0,
39     PROT_READ = 1,
40     PROT_WRITE = 2,
41     PROT_EXEC = 4,
42 }
43 
44 enum 
45 {
46     MAP_FILE = 0,
47     MAP_SHARED = 1,
48     MAP_PRIVATE = 2,
49     MAP_TYPE = 0xF,
50     MAP_FIXED = 0x10,
51     MAP_ANONYMOUS = 0x20,
52     MAP_32BIT = 0x40,
53     MAP_GROWSDOWN = 0x00100,
54     MAP_DENYWRITE = 0x00800,
55     MAP_EXECUTABLE = 0x01000,
56     MAP_LOCKED = 0x02000,
57     MAP_NORESERVE = 0x04000,
58     MAP_POPULATE = 0x08000,
59     MAP_NONBLOCK = 0x10000,
60     MAP_STACK = 0x20000,
61 }
62 enum MAP_FAILED = cast(void*)-1;
63 
64 enum
65 {
66     O_RDONLY    =   0,
67     O_WRONLY    =   1,
68     O_RDWR      =   2,
69     O_CREAT     =   100.octal,
70     O_EXCL      =   200.octal,
71     O_NOCTTY    =   400.octal,
72     O_TRUNC     =   1000.octal,
73     O_APPEND    =   2000.octal,
74     O_NONBLOCK  =   4000.octal,
75     O_NDELAY    =   O_NONBLOCK,
76     O_SYNC      =   4010000.octal,
77     O_FSYNC     =   O_SYNC,
78     O_ASYNC     =   20000.octal,
79     O_LARGEFILE =   100000.octal,
80     O_DIRECTORY =   200000.octal,
81     O_NOFOLLOW  =   400000.octal,
82     O_CLOEXEC   =   2000000.octal,
83     O_DIRECT    =   40000.octal,
84     O_NOATIME   =   1000000.octal,
85     O_PATH      =   10000000.octal,
86     O_DSYNC     =   10000.octal,
87     O_TMPFILE   =   (20000000.octal | O_DIRECTORY),
88 }
89 
90 enum
91 {
92     
93 EPERM =		1,		/* Operation not permitted */
94 ENOENT =		2,		/* No such file or directory */
95 ESRCH =		3,		/* No such process */
96 EINTR =		4,		/* Interrupted system call */
97 EIO =		5,		/* Input/output error */
98 ENXIO =		6,		/* Device not configured */
99 E2BIG =		7,		/* Argument list too long */
100 ENOEXEC =		8,		/* Exec format error */
101 EBADF =		9,		/* Bad file descriptor */
102 ECHILD =		10,		/* No child processes */
103 EDEADLK =		11,		/* Resource deadlock avoided */
104 ENOMEM =		12,		/* Cannot allocate memory */
105 EACCES =		13,		/* Permission denied */
106 EFAULT =		14,		/* Bad address */
107 ENOTBLK =		15,		/* Block device required */
108 EBUSY =		16,		/* Device busy */
109 EEXIST =		17,		/* File exists */
110 EXDEV =		18,		/* Cross-device link */
111 ENODEV =		19,		/* Operation not supported by device */
112 ENOTDIR =		20,		/* Not a directory */
113 EISDIR =		21,		/* Is a directory */
114 EINVAL =		22,		/* Invalid argument */
115 ENFILE =		23,		/* Too many open files in system */
116 EMFILE =		24,		/* Too many open files */
117 ENOTTY =		25,		/* Inappropriate ioctl for device */
118 ETXTBSY =		26,		/* Text file busy */
119 EFBIG =		27,		/* File too large */
120 ENOSPC =		28,		/* No space left on device */
121 ESPIPE =		29,		/* Illegal seek */
122 EROFS =		30,		/* Read-only file system */
123 EMLINK =		31,		/* Too many links */
124 EPIPE =		32,		/* Broken pipe */
125 EDOM =		33,		/* Numerical argument out of domain */
126 ERANGE =		34,		/* Result too large */
127 EAGAIN =		35,		/* Resource temporarily unavailable */
128 EWOULDBLOCK =	EAGAIN,		/* Operation would block */
129 EINPROGRESS =	36,		/* Operation now in progress */
130 EALREADY =	37,		/* Operation already in progress */
131 ENOTSOCK =	38,		/* Socket operation on non-socket */
132 EDESTADDRREQ =	39,		/* Destination address required */
133 EMSGSIZE =	40,		/* Message too long */
134 EPROTOTYPE =	41,		/* Protocol wrong type for socket */
135 ENOPROTOOPT =	42,		/* Protocol not available */
136 EPROTONOSUPPORT =	43,		/* Protocol not supported */
137 ESOCKTNOSUPPORT =	44,		/* Socket type not supported */
138 EOPNOTSUPP =	45,		/* Operation not supported on socket */
139 EPFNOSUPPORT =	46,		/* Protocol family not supported */
140 EAFNOSUPPORT =	47,		/* Address family not supported by protocol family */
141 EADDRINUSE =	48,		/* Address already in use */
142 EADDRNOTAVAIL =	49,		/* Can't assign requested address */
143 ENETDOWN =	50,		/* Network is down */
144 ENETUNREACH =	51,		/* Network is unreachable */
145 ENETRESET =	52,		/* Network dropped connection on reset */
146 ECONNABORTED =	53,		/* Software caused connection abort */
147 ECONNRESET =	54,		/* Connection reset by peer */
148 ENOBUFS =		55,		/* No buffer space available */
149 EISCONN =		56,		/* Socket is already connected */
150 ENOTCONN =	57,		/* Socket is not connected */
151 ESHUTDOWN =	58,		/* Can't send after socket shutdown */
152 ETOOMANYREFS =	59,		/* Too many references: can't splice */
153 ETIMEDOUT =	60,		/* Connection timed out */
154 ECONNREFUSED =	61,		/* Connection refused */
155 ELOOP =		62,		/* Too many levels of symbolic links */
156 ENAMETOOLONG =	63,		/* File name too long */
157 EHOSTDOWN =	64,		/* Host is down */
158 EHOSTUNREACH =	65,		/* No route to host */
159 ENOTEMPTY =	66,		/* Directory not empty */
160 EPROCLIM =	67,		/* Too many processes */
161 EUSERS =		68,		/* Too many users */
162 EDQUOT =		69,		/* Disc quota exceeded */
163 ESTALE =		70,		/* Stale NFS file handle */
164 EREMOTE =		71,		/* Too many levels of remote in path */
165 EBADRPC =		72,		/* RPC struct is bad */
166 ERPCMISMATCH =	73,		/* RPC version wrong */
167 EPROGUNAVAIL =	74,		/* RPC prog. not avail */
168 EPROGMISMATCH =	75,		/* Program version wrong */
169 EPROCUNAVAIL =	76,		/* Bad procedure for program */
170 ENOLCK =		77,		/* No locks available */
171 ENOSYS =		78,		/* Function not implemented */
172 EFTYPE =		79,		/* Inappropriate file type or format */
173 }
174 
175 enum
176 {
177     SEEK_SET = 0,
178     SEEK_CUR = 1,
179     SEEK_END = 2,
180 }
181 
182 enum
183 {
184     F_OK = 0
185 }
186 
187 alias umode_t = ushort;
188 alias ssize_t = long;
189 alias uint          dev_t;
190 alias ulong         ino_t;
191 alias uint         mode_t;
192 alias int          pid_t;
193 alias uint          uid_t;
194 alias uint          gid_t;
195 alias ulong       nlink_t;
196 alias long         off_t;
197 alias long     blksize_t;
198 alias long      blkcnt_t;
199 alias long        time_t;
200 
201 __gshared int g_errno;
202 
203 struct timespec {
204 	time_t	tv_sec;		/* seconds */
205 	long			tv_nsec;	/* nanoseconds */
206 };
207 
208 struct stat {
209     dev_t     st_dev;         /* ID of device containing file */
210     ino_t     st_ino;         /* Inode number */
211     mode_t    st_mode;        /* File type and mode */
212     nlink_t   st_nlink;       /* Number of hard links */
213     uid_t     st_uid;         /* User ID of owner */
214     gid_t     st_gid;         /* Group ID of owner */
215     dev_t     st_rdev;        /* Device ID (if special file) */
216     off_t     st_size;        /* Total size, in bytes */
217     blksize_t st_blksize;     /* Block size for filesystem I/O */
218     blkcnt_t  st_blocks;      /* Number of 512B blocks allocated */
219 
220     /* Since Linux 2.6, the kernel supports nanosecond
221         precision for the following timestamp fields.
222         For the details before Linux 2.6, see NOTES. */
223 
224     timespec st_atim;  /* Time of last access */
225     timespec st_mtim;  /* Time of last modification */
226     timespec st_ctim;  /* Time of last status change */
227 };
228 
229 private immutable setErrnoReturn = q{
230     asm @nogc nothrow {
231         jnc RETURN;
232         neg RAX;
233         lea RCX, g_errno;
234         mov [RCX], RAX;
235         neg RAX;
236         RETURN: ret;
237     }
238 };
239 
240 void* mmap(
241     void* addr, 
242     ulong len, 
243     int prot = PROT_READ | PROT_WRITE, 
244     int flags = MAP_PRIVATE | MAP_ANONYMOUS, 
245     int fd = -1, 
246     int off = 0
247 )
248 {
249     asm @nogc nothrow 
250     {
251         naked;
252         mov R10, RCX;
253         mov RAX, 9;
254         syscall;
255     }
256     mixin(setErrnoReturn);
257 }
258 
259 int munmap(void* addr, ulong len)
260 {
261     asm @nogc nothrow
262     {
263         naked;
264         mov RAX, 11;
265         syscall;
266     }
267     mixin(setErrnoReturn);
268 }
269 
270 int open(const char* filename, int flags, umode_t mode)
271 {
272     asm @nogc nothrow
273     {
274         naked;
275         mov RAX, 2;
276         syscall;
277     }
278     mixin(setErrnoReturn);
279 }
280 
281 int close(uint fd)
282 {
283     asm @nogc nothrow
284     {
285         naked;
286         mov RAX, 3;
287         syscall;
288     }
289     mixin(setErrnoReturn);
290 }
291 
292 ssize_t read(int fd, void* buf, size_t count)
293 {
294     asm @nogc nothrow
295     {
296         naked;
297         mov RAX, 0;
298         syscall;
299     }
300     mixin(setErrnoReturn);
301 }
302 
303 ssize_t write(int fd, const void* buf, size_t count)
304 {
305     asm @nogc nothrow
306     {
307         naked;
308         mov RAX, 1;
309         syscall;
310     }
311     mixin(setErrnoReturn);
312 }
313 
314 int fstat(int fd, stat* statbuf)
315 {
316     asm @nogc nothrow
317     {
318         naked;
319         mov RAX, 5;
320         syscall;
321     }
322     mixin(setErrnoReturn);
323 }
324 
325 off_t lseek(int fd, off_t offset, int whence)
326 {
327     asm @nogc nothrow
328     {
329         naked;
330         mov RAX, 8;
331         syscall;
332     }
333     mixin(setErrnoReturn);
334 }
335 
336 int access(const char* filename, int mode)
337 {
338     asm @nogc nothrow
339     {
340         naked;
341         mov RAX, 21;
342         syscall;
343     }
344     mixin(setErrnoReturn);
345 }
346 
347 int unlink(const char* filename)
348 {
349     asm @nogc nothrow
350     {
351         naked;
352         mov RAX, 87;
353         syscall;
354     }
355     mixin(setErrnoReturn);
356 }
357 
358 int rmdir(const char* filename)
359 {
360     asm @nogc nothrow
361     {
362         naked;
363         mov RAX, 84;
364         syscall;
365     }
366     mixin(setErrnoReturn);
367 }