2 // Mono.Posix.Syscall.cs: System calls to Posix subsystem features
5 // Miguel de Icaza (miguel@novell.com)
7 // (C) 2003 Novell, Inc.
9 // This file implements the low-level syscall interface to the POSIX
12 // This file tries to stay close to the low-level API as much as possible
13 // using enumerations, structures and in a few cases, using existing .NET
16 // Implementation notes:
18 // Since the values for the various constants on the API changes
19 // from system to system (even Linux on different architectures will
20 // have different values), we define our own set of values, and we
21 // use a set of C helper routines to map from the constants we define
22 // to the values of the native OS.
24 // Bitfields are flagged with the [Map] attribute, and a helper program
25 // generates a set of map_XXXX routines that we can call to convert
26 // from our value definitions to the value definitions expected by the
29 // Methods that require tuning are bound as `internal syscal_NAME' methods
30 // and then a `NAME' method is exposed.
34 // Permission is hereby granted, free of charge, to any person obtaining
35 // a copy of this software and associated documentation files (the
36 // "Software"), to deal in the Software without restriction, including
37 // without limitation the rights to use, copy, modify, merge, publish,
38 // distribute, sublicense, and/or sell copies of the Software, and to
39 // permit persons to whom the Software is furnished to do so, subject to
40 // the following conditions:
42 // The above copyright notice and this permission notice shall be
43 // included in all copies or substantial portions of the Software.
45 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
46 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
47 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
48 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
49 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
50 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
51 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
56 using System.Runtime.InteropServices;
58 [assembly:Mono.Posix.IncludeAttribute (new string [] {"sys/types.h", "sys/stat.h", "sys/wait.h", "unistd.h", "fcntl.h", "signal.h"},
59 new string [] {"_GNU_SOURCE"})]
60 namespace Mono.Posix {
63 public enum OpenFlags {
72 // Or-ed with zero or more of these
83 // These are non-Posix, think of a way of exposing
84 // this for Linux users.
88 // O_DIRECTORY = 1024,
95 public enum FileMode {
111 public enum WaitOptions {
117 public enum AccessMode {
125 public enum Signals {
126 SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGBUS,
127 SIGFPE, SIGKILL, SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE,
128 SIGALRM, SIGTERM, SIGCHLD, SIGCONT, SIGSTOP, SIGTSTP,
129 SIGTTIN, SIGTTOU, SIGURG, SIGXCPU, SIGXFSZ, SIGVTALRM,
130 SIGPROF, SIGWINCH, SIGIO,
137 public class Syscall {
138 [DllImport ("libc", SetLastError=true)]
139 public static extern int exit (int status);
141 [DllImport ("libc", SetLastError=true)]
142 public static extern int fork ();
144 [DllImport ("libc", SetLastError=true)]
145 public unsafe static extern IntPtr read (int fileDescriptor, void *buf, IntPtr count);
147 [DllImport ("libc", SetLastError=true)]
148 public unsafe static extern IntPtr write (int fileDescriptor, void *buf, IntPtr count);
150 [DllImport ("libc", EntryPoint="open", SetLastError=true)]
151 internal static extern int syscall_open (string pathname, int flags, int mode);
153 [DllImport ("MonoPosixHelper")]
154 internal extern static int map_Mono_Posix_OpenFlags (OpenFlags flags);
155 [DllImport ("MonoPosixHelper")]
156 internal extern static int map_Mono_Posix_FileMode (FileMode mode);
158 public static int open (string pathname, OpenFlags flags)
160 if ((flags & OpenFlags.O_CREAT) != 0)
161 throw new ArgumentException ("If you pass O_CREAT, you must call the method with the mode flag");
163 int posix_flags = map_Mono_Posix_OpenFlags (flags);
164 return syscall_open (pathname, posix_flags, 0);
167 public static int open (string pathname, OpenFlags flags, FileMode mode)
169 int posix_flags = map_Mono_Posix_OpenFlags (flags);
170 int posix_mode = map_Mono_Posix_FileMode (mode);
172 return syscall_open (pathname, posix_flags, posix_mode);
176 [DllImport ("libc", SetLastError=true)]
177 public static extern int close (int fileDescriptor);
179 [DllImport ("libc", EntryPoint="waitpid", SetLastError=true)]
180 unsafe internal static extern int syscall_waitpid (int pid, int * status, int options);
182 [DllImport ("MonoPosixHelper")]
183 internal extern static int map_Mono_Posix_WaitOptions (WaitOptions wait_options);
185 public static int waitpid (int pid, out int status, WaitOptions options)
189 int r = syscall_waitpid (pid, &s, map_Mono_Posix_WaitOptions (options));
195 public static int waitpid (int pid, WaitOptions options)
198 return syscall_waitpid (pid, null, map_Mono_Posix_WaitOptions (options));
202 [DllImport ("MonoPosixHelper", EntryPoint="wifexited")]
203 public static extern int WIFEXITED (int status);
204 [DllImport ("MonoPosixHelper", EntryPoint="wexitstatus")]
205 public static extern int WEXITSTATUS (int status);
206 [DllImport ("MonoPosixHelper", EntryPoint="wifsignaled")]
207 public static extern int WIFSIGNALED (int status);
208 [DllImport ("MonoPosixHelper", EntryPoint="wtermsig")]
209 public static extern int WTERMSIG (int status);
210 [DllImport ("MonoPosixHelper", EntryPoint="wifstopped")]
211 public static extern int WIFSTOPPED (int status);
212 [DllImport ("MonoPosixHelper", EntryPoint="wstopsig")]
213 public static extern int WSTOPSIG (int status);
215 [DllImport ("libc", SetLastError=true)]
216 internal static extern int syscall_creat (string pathname, int flags);
218 public static int creat (string pathname, FileMode flags)
220 return syscall_creat (pathname, map_Mono_Posix_FileMode (flags));
223 [DllImport ("libc", SetLastError=true)]
224 public static extern int link (string oldPath, string newPath);
226 [DllImport ("libc", SetLastError=true)]
227 public static extern int unlink (string path);
229 [DllImport ("libc", SetLastError=true)]
230 public static extern int symlink (string oldpath, string newpath);
234 [DllImport ("libc", SetLastError=true)]
235 public static extern int chdir (string path);
241 [DllImport ("libc", EntryPoint="chmod", SetLastError=true)]
242 internal static extern int syscall_chmod (string path, int mode);
244 public static int chmod (string path, FileMode mode)
246 return syscall_chmod (path, map_Mono_Posix_FileMode (mode));
249 [DllImport ("libc", SetLastError=true)]
250 public static extern int chown (string path, int owner, int group);
251 [DllImport ("libc", SetLastError=true)]
252 public static extern int lchown (string path, int owner, int group);
254 [DllImport ("libc", SetLastError=true)]
255 public static extern int lseek (int fileDescriptor, int offset, int whence);
257 [DllImport ("libc", SetLastError=true)]
258 public static extern int getpid ();
263 [DllImport ("libc", SetLastError=true)]
264 public static extern int setuid (int uid);
266 [DllImport ("libc", SetLastError=true)]
267 public static extern int getuid ();
273 public static extern uint alarm (uint seconds);
275 [DllImport ("libc", SetLastError=true)]
276 public static extern int pause ();
281 internal extern static int syscall_access (string pathname, int mode);
283 [DllImport ("MonoPosixHelper")]
284 internal extern static int map_Mono_Posix_AccessMode (AccessMode mode);
286 public static int access (string pathname, AccessMode mode)
288 return syscall_access (pathname, map_Mono_Posix_AccessMode (mode));
291 [DllImport ("libc", SetLastError=true)]
292 public static extern int nice (int increment);
297 public static extern void sync ();
299 [DllImport ("libc", SetLastError=true)]
300 public static extern void kill (int pid, int sig);
302 [DllImport ("libc", SetLastError=true)]
303 public static extern int rename (string oldPath, string newPath);
305 [DllImport ("libc", SetLastError=true)]
306 internal extern static int syscall_mkdir (string pathname, int mode);
308 public static int mkdir (string pathname, FileMode mode)
310 return syscall_mkdir (pathname, map_Mono_Posix_FileMode (mode));
313 [DllImport ("libc", SetLastError=true)]
314 public static extern int rmdir (string path);
316 [DllImport ("libc", SetLastError=true)]
317 public static extern int dup (int fileDescriptor);
322 [DllImport ("libc", SetLastError=true)]
323 public static extern int setgid (int gid);
324 [DllImport ("libc", SetLastError=true)]
325 public static extern int getgid ();
328 public delegate void sighandler_t (int v);
330 [DllImport ("libc", SetLastError=true)]
331 public static extern int signal (int signum, sighandler_t handler);
333 [DllImport ("libc", SetLastError=true)]
334 public static extern int geteuid ();
336 [DllImport ("libc", SetLastError=true)]
337 public static extern int getegid ();
341 [DllImport ("libc", SetLastError=true)]
342 public static extern int setpgid (int pid, int pgid);
347 public static extern int umask (int umask);
349 [DllImport ("libc", SetLastError=true)]
350 public static extern int chroot (string path);
352 [DllImport ("libc", SetLastError=true)]
353 public static extern int dup2 (int oldFileDescriptor, int newFileDescriptor);
355 [DllImport ("libc", SetLastError=true)]
356 public static extern int getppid ();
358 [DllImport ("libc", SetLastError=true)]
359 public static extern int getpgrp ();
361 [DllImport ("libc", SetLastError=true)]
362 public static extern int setsid ();
366 [DllImport ("libc", SetLastError=true)]
367 public static extern int setreuid (int ruid, int euid);
369 [DllImport ("libc", SetLastError=true)]
370 public static extern int setregid (int rgid, int egid);
372 // these don't exactly match POSIX, but it's a nice way to get user/group names
374 [DllImport ("MonoPosixHelper", SetLastError=true)]
375 private static extern string helper_Mono_Posix_GetUserName (int uid);
377 [DllImport ("MonoPosixHelper", SetLastError=true)]
378 private static extern string helper_Mono_Posix_GetGroupName (int gid);
380 public static string getusername(int uid) { return helper_Mono_Posix_GetUserName(uid); }
381 public static string getgroupname(int gid) { return helper_Mono_Posix_GetGroupName(gid); }
388 // TODO: gettimeofday
389 // TODO: settimeofday
391 [DllImport ("libc", EntryPoint="gethostname", SetLastError=true)]
392 static extern int syscall_gethostname (byte[] p, int len);
394 public static string GetHostName ()
396 byte [] buf = new byte [256];
397 int res = syscall_gethostname (buf, buf.Length);
400 for (res = 0; res < buf.Length; ++res) {
405 return Encoding.UTF8.GetString (buf, 0, res);
408 public static string gethostname ()
410 return GetHostName ();
414 [DllImport ("libc", EntryPoint="isatty")]
415 static extern int syscall_isatty (int desc);
417 public static bool isatty (int desc)
419 int res = syscall_isatty (desc);
427 [DllImport ("MonoPosixHelper")]
428 internal extern static int helper_Mono_Posix_Stat (string filename, bool dereference,
429 out int device, out int inode, out int mode,
430 out int nlinks, out int uid, out int gid,
431 out int rdev, out long size, out long blksize, out long blocks,
432 out long atime, out long mtime, out long ctime);
434 private static int stat2(string filename, bool dereference, out Stat stat) {
435 int device, inode, mode;
436 int nlinks, uid, gid, rdev;
437 long size, blksize, blocks;
438 long atime, mtime, ctime;
440 int ret = helper_Mono_Posix_Stat(filename, dereference,
441 out device, out inode, out mode,
442 out nlinks, out uid, out gid,
443 out rdev, out size, out blksize, out blocks,
444 out atime, out mtime, out ctime);
449 rdev, size, blksize, blocks,
450 atime, mtime, ctime);
452 if (ret != 0) return ret;
457 public static int stat(string filename, out Stat stat) {
458 return stat2(filename, false, out stat);
461 public static int lstat(string filename, out Stat stat) {
462 return stat2(filename, true, out stat);
466 private static extern int readlink(string path, byte[] buffer, int buflen);
468 public static string readlink(string path) {
469 byte[] buf = new byte[512];
470 int ret = readlink(path, buf, buf.Length);
471 if (ret == -1) return null;
472 char[] cbuf = new char[512];
473 int chars = System.Text.Encoding.Default.GetChars(buf, 0, ret, cbuf, 0);
474 return new String(cbuf, 0, chars);
477 [DllImport ("libc", EntryPoint="strerror")]
478 static extern IntPtr _strerror(int errnum);
480 public static string strerror (int errnum)
482 return Marshal.PtrToStringAnsi (_strerror (errnum));
486 public static extern IntPtr opendir(string path);
489 public static extern int closedir(IntPtr dir);
491 [DllImport ("MonoPosixHelper", EntryPoint="helper_Mono_Posix_readdir")]
492 public static extern string readdir(IntPtr dir);
496 public enum StatModeMasks {
497 TypeMask = 0xF000, // bitmask for the file type bitfields
498 OwnerMask = 0x1C0, // mask for file owner permissions
499 GroupMask = 0x38, // mask for group permissions
500 OthersMask = 0x7, // mask for permissions for others (not in group)
504 public enum StatMode {
505 Socket = 0xC000, // socket
506 SymLink = 0xA000, // symbolic link
507 Regular = 0x8000, // regular file
508 BlockDevice = 0x6000, // block device
509 Directory = 0x4000, // directory
510 CharDevice = 0x2000, // character device
511 FIFO = 0x1000, // fifo
512 SUid = 0x800, // set UID bit
513 SGid = 0x400, // set GID bit
514 Sticky = 0x200, // sticky bit
515 OwnerRead = 0x100, // owner has read permission
516 OwnerWrite = 0x80, // owner has write permission
517 OwnerExecute = 0x40, // owner has execute permission
518 GroupRead = 0x20, // group has read permission
519 GroupWrite = 0x10, // group has write permission
520 GroupExecute = 0x8, // group has execute permission
521 OthersRead = 0x4, // others have read permission
522 OthersWrite = 0x2, // others have write permisson
523 OthersExecute = 0x1, // others have execute permission
527 public readonly int Device;
528 public readonly int INode;
529 public readonly StatMode Mode;
530 public readonly int NLinks;
531 public readonly int Uid;
532 public readonly int Gid;
533 public readonly long DeviceType;
534 public readonly long Size;
535 public readonly long BlockSize;
536 public readonly long Blocks;
537 public readonly DateTime ATime;
538 public readonly DateTime MTime;
539 public readonly DateTime CTime;
541 public static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1).ToLocalTime();
543 public static DateTime UnixToDateTime(long unix) {
544 return UnixEpoch.Add(TimeSpan.FromSeconds(unix));
548 int device, int inode, int mode,
549 int nlinks, int uid, int gid,
550 int rdev, long size, long blksize, long blocks,
551 long atime, long mtime, long ctime) {
554 Mode = (StatMode)mode;
563 ATime = UnixToDateTime(atime);
565 ATime = new DateTime();
567 MTime = UnixToDateTime(mtime);
569 MTime = new DateTime();
571 CTime = UnixToDateTime(ctime);
573 CTime = new DateTime();