This commit was manufactured by cvs2svn to create branch 'mono-1-0'.
[mono.git] / mcs / class / Mono.Posix / Mono.Posix / Syscall.cs
1 //
2 // Mono.Posix.Syscall.cs: System calls to Posix subsystem features
3 //
4 // Author:
5 //   Miguel de Icaza (miguel@novell.com)
6 //
7 // (C) 2003 Novell, Inc.
8 //
9 // This file implements the low-level syscall interface to the POSIX
10 // subsystem.
11 //
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
14 // data types.
15 //
16 // Implementation notes:
17 //
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.
23 //
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
27 //    OS.
28 //
29 //    Methods that require tuning are bound as `internal syscal_NAME' methods
30 //    and then a `NAME' method is exposed.
31 //
32
33 //
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:
41 // 
42 // The above copyright notice and this permission notice shall be
43 // included in all copies or substantial portions of the Software.
44 // 
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.
52 //
53
54 using System;
55 using System.Text;
56 using System.Runtime.InteropServices;
57
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 {
61
62         [Map][Flags]
63         public enum OpenFlags {
64                 //
65                 // One of these
66                 //
67                 O_RDONLY    = 0,
68                 O_WRONLY    = 1,
69                 O_RDWR      = 2,
70
71                 //
72                 // Or-ed with zero or more of these
73                 //
74                 O_CREAT     = 4,
75                 O_EXCL      = 8,
76                 O_NOCTTY    = 16,
77                 O_TRUNC     = 32,
78                 O_APPEND    = 64,
79                 O_NONBLOCK  = 128,
80                 O_SYNC      = 256,
81
82                 //
83                 // These are non-Posix, think of a way of exposing
84                 // this for Linux users.
85                 //
86                 
87                 // O_NOFOLLOW  = 512,
88                 // O_DIRECTORY = 1024,
89                 // O_DIRECT    = 2048,
90                 // O_ASYNC     = 4096,
91                 // O_LARGEFILE = 8192
92         }
93         
94         [Flags][Map]
95         public enum FileMode {
96                 S_ISUID   = 2048,
97                 S_ISGID   = 1024,
98                 S_ISVTX   = 512,
99                 S_IRUSR   = 256,
100                 S_IWUSR   = 128,
101                 S_IXUSR   = 64,
102                 S_IRGRP   = 32,
103                 S_IWGRP   = 16,
104                 S_IXGRP   = 8,
105                 S_IROTH   = 4,
106                 S_IWOTH   = 2,
107                 S_IXOTH   = 1
108         }
109
110         [Flags][Map]
111         public enum WaitOptions {
112                 WNOHANG,
113                 WUNTRACED
114         }
115
116         [Flags][Map]
117         public enum AccessMode {
118                 R_OK = 1,
119                 W_OK = 2,
120                 X_OK = 4,
121                 F_OK = 8
122         }
123
124         [Map]
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,
131                 
132                 // SIGPWR,
133                 SIGSYS,
134                 // SIGRTMIN
135         }
136         
137         public class Syscall {
138                 [DllImport ("libc", SetLastError=true)]
139                 public static extern int exit (int status);
140
141                 [DllImport ("libc", SetLastError=true)]
142                 public static extern int fork ();
143
144                 [DllImport ("libc", SetLastError=true)]
145                 public unsafe static extern IntPtr read (int fileDescriptor, void *buf, IntPtr count);
146
147                 [DllImport ("libc", SetLastError=true)]
148                 public unsafe static extern IntPtr write (int fileDescriptor, void *buf, IntPtr count);
149
150                 [DllImport ("libc", EntryPoint="open", SetLastError=true)]
151                 internal static extern int syscall_open (string pathname, int flags, int mode);
152
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);
157                 
158                 public static int open (string pathname, OpenFlags flags)
159                 {
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");
162                         
163                         int posix_flags = map_Mono_Posix_OpenFlags (flags);
164                         return syscall_open (pathname, posix_flags, 0);
165                 }
166
167                 public static int open (string pathname, OpenFlags flags, FileMode mode)
168                 {
169                         int posix_flags = map_Mono_Posix_OpenFlags (flags);
170                         int posix_mode = map_Mono_Posix_FileMode (mode);
171
172                         return syscall_open (pathname, posix_flags, posix_mode);
173                 }
174                 
175
176                 [DllImport ("libc", SetLastError=true)]
177                 public static extern int close (int fileDescriptor);
178
179                 [DllImport ("libc", EntryPoint="waitpid", SetLastError=true)]
180                 unsafe internal static extern int syscall_waitpid (int pid, int * status, int options);
181
182                 [DllImport ("MonoPosixHelper")]
183                 internal extern static int map_Mono_Posix_WaitOptions (WaitOptions wait_options);
184                 
185                 public static int waitpid (int pid, out int status, WaitOptions options)
186                 {
187                         unsafe {
188                                 int s = 0;
189                                 int r = syscall_waitpid (pid, &s, map_Mono_Posix_WaitOptions (options));
190                                 status = s;
191                                 return r;
192                         }
193                 }
194                 
195                 public static int waitpid (int pid, WaitOptions options)
196                 {
197                         unsafe {
198                                 return syscall_waitpid (pid, null, map_Mono_Posix_WaitOptions (options));
199                         }
200                 }
201
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);
214
215                 [DllImport ("libc", SetLastError=true)]
216                 internal static extern int syscall_creat (string pathname, int flags);
217
218                 public static int creat (string pathname, FileMode flags)
219                 {
220                         return syscall_creat (pathname, map_Mono_Posix_FileMode (flags));
221                 }
222
223                 [DllImport ("libc", SetLastError=true)]
224                 public static extern int link (string oldPath, string newPath);
225
226                 [DllImport ("libc", SetLastError=true)]
227                 public static extern int unlink (string path);
228
229                 [DllImport ("libc", SetLastError=true)]
230                 public static extern int symlink (string oldpath, string newpath);
231                 
232                 // TODO: execve
233
234                 [DllImport ("libc", SetLastError=true)]
235                 public static extern int chdir (string path);
236
237                 // TODO: time
238                 // TODO: mknod
239
240                 
241                 [DllImport ("libc", EntryPoint="chmod", SetLastError=true)]
242                 internal static extern int syscall_chmod (string path, int mode);
243
244                 public static int chmod (string path, FileMode mode)
245                 {
246                         return syscall_chmod (path, map_Mono_Posix_FileMode (mode));
247                 }
248
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);
253                 
254                 [DllImport ("libc", SetLastError=true)]
255                 public static extern int lseek (int fileDescriptor, int offset, int whence);
256
257                 [DllImport ("libc", SetLastError=true)]
258                 public static extern int getpid ();
259                 
260                 // TODO: mount
261                 // TODO: umount
262
263                 [DllImport ("libc", SetLastError=true)]
264                 public static extern int setuid (int uid);
265                 
266                 [DllImport ("libc", SetLastError=true)]
267                 public static extern int getuid ();
268
269                 // TODO: stime
270                 // TODO: ptrace
271                 
272                 [DllImport ("libc")]
273                 public static extern uint alarm (uint seconds);
274
275                 [DllImport ("libc", SetLastError=true)]
276                 public static extern int pause ();
277
278                 // TODO: utime
279
280                 [DllImport ("libc")]
281                 internal extern static int syscall_access (string pathname, int mode);
282
283                 [DllImport ("MonoPosixHelper")]
284                 internal extern static int map_Mono_Posix_AccessMode (AccessMode mode);
285
286                 public static int access (string pathname, AccessMode mode)
287                 {
288                         return syscall_access (pathname, map_Mono_Posix_AccessMode (mode));
289                 }
290
291                 [DllImport ("libc", SetLastError=true)]
292                 public static extern int nice (int increment);
293
294                 // TODO: ftime
295
296                 [DllImport ("libc")]
297                 public static extern void sync ();
298
299                 [DllImport ("libc", SetLastError=true)]
300                 public static extern void kill (int pid, int sig);
301
302                 [DllImport ("libc", SetLastError=true)]
303                 public static extern int rename (string oldPath, string newPath);
304                 
305                 [DllImport ("libc", SetLastError=true)]
306                 internal extern static int syscall_mkdir (string pathname, int mode);
307
308                 public static int mkdir (string pathname, FileMode mode)
309                 {
310                         return syscall_mkdir (pathname, map_Mono_Posix_FileMode (mode));
311                 }
312
313                 [DllImport ("libc", SetLastError=true)]
314                 public static extern int rmdir (string path);
315
316                 [DllImport ("libc", SetLastError=true)]
317                 public static extern int dup (int fileDescriptor);
318
319                 // TODO: pipe
320                 // TODO: times
321
322                 [DllImport ("libc", SetLastError=true)]
323                 public static extern int setgid (int gid);
324                 [DllImport ("libc", SetLastError=true)]
325                 public static extern int getgid ();
326
327                 
328                 public delegate void sighandler_t (int v);
329                 
330                 [DllImport ("libc", SetLastError=true)]
331                 public static extern int signal (int signum, sighandler_t handler);
332                 
333                 [DllImport ("libc", SetLastError=true)]
334                 public static extern int geteuid ();
335                 
336                 [DllImport ("libc", SetLastError=true)]
337                 public static extern int getegid ();
338
339                 // TODO: fcntl
340                 
341                 [DllImport ("libc", SetLastError=true)]
342                 public static extern int setpgid (int pid, int pgid);
343
344                 // TODO: ulimit
345
346                 [DllImport ("libc")]
347                 public static extern int umask (int umask);
348
349                 [DllImport ("libc", SetLastError=true)]
350                 public static extern int chroot (string path);
351
352                 [DllImport ("libc", SetLastError=true)]
353                 public static extern int dup2 (int oldFileDescriptor, int newFileDescriptor);
354
355                 [DllImport ("libc", SetLastError=true)]
356                 public static extern int getppid ();
357
358                 [DllImport ("libc", SetLastError=true)]
359                 public static extern int getpgrp ();
360
361                 [DllImport ("libc", SetLastError=true)]
362                 public static extern int setsid ();
363                 
364                 // TODO: sigaction
365                 
366                 [DllImport ("libc", SetLastError=true)]
367                 public static extern int setreuid (int ruid, int euid);
368
369                 [DllImport ("libc", SetLastError=true)]
370                 public static extern int setregid (int rgid, int egid);
371
372                 // these don't exactly match POSIX, but it's a nice way to get user/group names
373                 
374                 [DllImport ("MonoPosixHelper", SetLastError=true)]
375                 private static extern string helper_Mono_Posix_GetUserName (int uid);
376
377                 [DllImport ("MonoPosixHelper", SetLastError=true)]
378                 private static extern string helper_Mono_Posix_GetGroupName (int gid);
379                 
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); }
382                 
383                 // TODO: sigsuspend
384                 // TODO: sigpending
385                 // TODO: setrlimit
386                 // TODO: getrlimit
387                 // TODO: getrusage
388                 // TODO: gettimeofday
389                 // TODO: settimeofday
390                 
391                 [DllImport ("libc", EntryPoint="gethostname", SetLastError=true)]
392                 static extern int syscall_gethostname (byte[] p, int len);
393
394                 public static string GetHostName ()
395                 {
396                         byte [] buf = new byte [256];
397                         int res = syscall_gethostname (buf, buf.Length);
398                         if (res == -1)
399                                 return "localhost";
400                         for (res = 0; res < buf.Length; ++res) {
401                                 if (buf [res] == 0)
402                                         break;
403                         }
404                                 
405                         return Encoding.UTF8.GetString (buf, 0, res);
406                 }
407
408                 public static string gethostname ()
409                 {
410                         return GetHostName ();
411                 }
412                 
413
414                 [DllImport ("libc", EntryPoint="isatty")]
415                 static extern int syscall_isatty (int desc);
416                 
417                 public static bool isatty (int desc)
418                 {
419                         int res = syscall_isatty (desc);
420                         if (res == 1)
421                                 return true;
422                         else
423                                 return false;
424                 }
425                 
426
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);
433                 
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;
439
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);
445                                 
446                         stat = new Stat(
447                                 device, inode, mode,
448                                 nlinks, uid, gid,
449                                 rdev, size, blksize, blocks,
450                                 atime, mtime, ctime);
451
452                         if (ret != 0) return ret;
453
454                         return 0;
455                 }
456
457                 public static int stat(string filename, out Stat stat) {
458                         return stat2(filename, false, out stat);
459                 }
460
461                 public static int lstat(string filename, out Stat stat) {
462                         return stat2(filename, true, out stat);
463                 }
464                 
465                 [DllImport ("libc")]
466                 private static extern int readlink(string path, byte[] buffer, int buflen);
467
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);
475                 }
476
477                 [DllImport ("libc", EntryPoint="strerror")]
478                 static extern IntPtr _strerror(int errnum);
479
480                 public static string strerror (int errnum)
481                 {
482                         return Marshal.PtrToStringAnsi (_strerror (errnum));
483                 }
484
485                 [DllImport ("libc")]
486                 public static extern IntPtr opendir(string path);
487
488                 [DllImport ("libc")]
489                 public static extern int closedir(IntPtr dir);
490                 
491                 [DllImport ("MonoPosixHelper", EntryPoint="helper_Mono_Posix_readdir")]
492                 public static extern string readdir(IntPtr dir);
493                 
494         }
495         
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)
501         }
502         
503         [Flags]
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  
524         }
525         
526         public struct Stat {
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;
540                 
541                 public static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1).ToLocalTime();
542                 
543                 public static DateTime UnixToDateTime(long unix) {
544                         return UnixEpoch.Add(TimeSpan.FromSeconds(unix));
545                 }
546
547                 internal Stat(
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) {
552                         Device = device;
553                         INode = inode;
554                         Mode = (StatMode)mode;
555                         NLinks = nlinks;
556                         Uid = uid;
557                         Gid = gid;
558                         DeviceType = rdev;
559                         Size = size;
560                         BlockSize = blksize;
561                         Blocks = blocks;
562                         if (atime != 0)
563                                 ATime = UnixToDateTime(atime);
564                         else
565                                 ATime = new DateTime();
566                         if (mtime != 0)
567                                 MTime = UnixToDateTime(mtime);
568                         else
569                                 MTime = new DateTime();
570                         if (ctime != 0)
571                                 CTime = UnixToDateTime(ctime);
572                         else
573                                 CTime = new DateTime();
574                 }
575         }
576         
577
578 }