updating to the latest module.
[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 were 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 // Deprecated Warning:
33 //
34 //    This class is deprecated, and exists only for backward compatibility.
35 //    Please use and maintain Mono.Unix.Syscall.
36 //
37 //    The [Map] attributes have been removed.  The naming and methodology of
38 //    the mapping routines has changed.  The old map functions still exist in
39 //    MonoPosixHelper, but they will not be updated any further.
40 //    Consequently, there is little point in maintaining the [Map] attributes
41 //    in this file, as they would only bloat MonoPosixHelper.
42 //
43
44 //
45 // Permission is hereby granted, free of charge, to any person obtaining
46 // a copy of this software and associated documentation files (the
47 // "Software"), to deal in the Software without restriction, including
48 // without limitation the rights to use, copy, modify, merge, publish,
49 // distribute, sublicense, and/or sell copies of the Software, and to
50 // permit persons to whom the Software is furnished to do so, subject to
51 // the following conditions:
52 // 
53 // The above copyright notice and this permission notice shall be
54 // included in all copies or substantial portions of the Software.
55 // 
56 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
57 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
58 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
59 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
60 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
61 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
62 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
63 //
64
65 using System;
66 using System.Text;
67 using System.Runtime.InteropServices;
68
69 namespace Mono.Posix {
70
71         [Flags]
72         public enum OpenFlags {
73                 //
74                 // One of these
75                 //
76                 O_RDONLY    = 0,
77                 O_WRONLY    = 1,
78                 O_RDWR      = 2,
79
80                 //
81                 // Or-ed with zero or more of these
82                 //
83                 O_CREAT     = 4,
84                 O_EXCL      = 8,
85                 O_NOCTTY    = 16,
86                 O_TRUNC     = 32,
87                 O_APPEND    = 64,
88                 O_NONBLOCK  = 128,
89                 O_SYNC      = 256,
90
91                 //
92                 // These are non-Posix, think of a way of exposing
93                 // this for Linux users.
94                 //
95                 
96                 // O_NOFOLLOW  = 512,
97                 // O_DIRECTORY = 1024,
98                 // O_DIRECT    = 2048,
99                 // O_ASYNC     = 4096,
100                 // O_LARGEFILE = 8192
101         }
102         
103         [Flags]
104         public enum FileMode {
105                 S_ISUID   = 2048,
106                 S_ISGID   = 1024,
107                 S_ISVTX   = 512,
108                 S_IRUSR   = 256,
109                 S_IWUSR   = 128,
110                 S_IXUSR   = 64,
111                 S_IRGRP   = 32,
112                 S_IWGRP   = 16,
113                 S_IXGRP   = 8,
114                 S_IROTH   = 4,
115                 S_IWOTH   = 2,
116                 S_IXOTH   = 1
117         }
118
119         [Flags]
120         public enum WaitOptions {
121                 WNOHANG,
122                 WUNTRACED
123         }
124
125         [Flags]
126         public enum AccessMode {
127                 R_OK = 1,
128                 W_OK = 2,
129                 X_OK = 4,
130                 F_OK = 8
131         }
132
133         
134         public enum Signals {
135                 SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGBUS,
136                 SIGFPE, SIGKILL, SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE,
137                 SIGALRM, SIGTERM, SIGCHLD, SIGCONT, SIGSTOP, SIGTSTP,
138                 SIGTTIN, SIGTTOU, SIGURG, SIGXCPU, SIGXFSZ, SIGVTALRM,
139                 SIGPROF, SIGWINCH, SIGIO,
140                 
141                 // SIGPWR,
142                 SIGSYS,
143                 // SIGRTMIN
144         }
145         
146         [Obsolete ("Syscall is unmaintained.  Please use Mono.Unix.Syscall.")]
147         public class Syscall {
148                 [DllImport ("libc", SetLastError=true)]
149                 public static extern int exit (int status);
150
151                 [DllImport ("libc", SetLastError=true)]
152                 public static extern int fork ();
153
154                 [DllImport ("libc", SetLastError=true)]
155                 public unsafe static extern IntPtr read (int fileDescriptor, void *buf, IntPtr count);
156
157                 [DllImport ("libc", SetLastError=true)]
158                 public unsafe static extern IntPtr write (int fileDescriptor, void *buf, IntPtr count);
159
160                 [DllImport ("libc", EntryPoint="open", SetLastError=true)]
161                 internal static extern int syscall_open (string pathname, int flags, int mode);
162
163                 [DllImport ("MonoPosixHelper")]
164                 internal extern static int map_Mono_Posix_OpenFlags (OpenFlags flags);
165                 [DllImport ("MonoPosixHelper")]
166                 internal extern static int map_Mono_Posix_FileMode (FileMode mode);
167                 
168                 public static int open (string pathname, OpenFlags flags)
169                 {
170                         if ((flags & OpenFlags.O_CREAT) != 0)
171                                 throw new ArgumentException ("If you pass O_CREAT, you must call the method with the mode flag");
172                         
173                         int posix_flags = map_Mono_Posix_OpenFlags (flags);
174                         return syscall_open (pathname, posix_flags, 0);
175                 }
176
177                 public static int open (string pathname, OpenFlags flags, FileMode mode)
178                 {
179                         int posix_flags = map_Mono_Posix_OpenFlags (flags);
180                         int posix_mode = map_Mono_Posix_FileMode (mode);
181
182                         return syscall_open (pathname, posix_flags, posix_mode);
183                 }
184                 
185
186                 [DllImport ("libc", SetLastError=true)]
187                 public static extern int close (int fileDescriptor);
188
189                 [DllImport ("libc", EntryPoint="waitpid", SetLastError=true)]
190                 unsafe internal static extern int syscall_waitpid (int pid, int * status, int options);
191
192                 [DllImport ("MonoPosixHelper")]
193                 internal extern static int map_Mono_Posix_WaitOptions (WaitOptions wait_options);
194                 
195                 public static int waitpid (int pid, out int status, WaitOptions options)
196                 {
197                         unsafe {
198                                 int s = 0;
199                                 int r = syscall_waitpid (pid, &s, map_Mono_Posix_WaitOptions (options));
200                                 status = s;
201                                 return r;
202                         }
203                 }
204                 
205                 public static int waitpid (int pid, WaitOptions options)
206                 {
207                         unsafe {
208                                 return syscall_waitpid (pid, null, map_Mono_Posix_WaitOptions (options));
209                         }
210                 }
211
212                 [DllImport ("MonoPosixHelper", EntryPoint="wifexited")]
213                 public static extern int WIFEXITED (int status);
214                 [DllImport ("MonoPosixHelper", EntryPoint="wexitstatus")]
215                 public static extern int WEXITSTATUS (int status);
216                 [DllImport ("MonoPosixHelper", EntryPoint="wifsignaled")]
217                 public static extern int WIFSIGNALED (int status);
218                 [DllImport ("MonoPosixHelper", EntryPoint="wtermsig")]
219                 public static extern int WTERMSIG (int status);
220                 [DllImport ("MonoPosixHelper", EntryPoint="wifstopped")]
221                 public static extern int WIFSTOPPED (int status);
222                 [DllImport ("MonoPosixHelper", EntryPoint="wstopsig")]
223                 public static extern int WSTOPSIG (int status);
224
225                 [DllImport ("libc", EntryPoint="creat", SetLastError=true)]
226                 internal static extern int syscall_creat (string pathname, int flags);
227
228                 public static int creat (string pathname, FileMode flags)
229                 {
230                         return syscall_creat (pathname, map_Mono_Posix_FileMode (flags));
231                 }
232
233                 [DllImport ("libc", SetLastError=true)]
234                 public static extern int link (string oldPath, string newPath);
235
236                 [DllImport ("libc", SetLastError=true)]
237                 public static extern int unlink (string path);
238
239                 [DllImport ("libc", SetLastError=true)]
240                 public static extern int symlink (string oldpath, string newpath);
241                 
242                 // TODO: execve
243
244                 [DllImport ("libc", SetLastError=true)]
245                 public static extern int chdir (string path);
246
247                 // TODO: time
248                 // TODO: mknod
249
250                 
251                 [DllImport ("libc", EntryPoint="chmod", SetLastError=true)]
252                 internal static extern int syscall_chmod (string path, int mode);
253
254                 public static int chmod (string path, FileMode mode)
255                 {
256                         return syscall_chmod (path, map_Mono_Posix_FileMode (mode));
257                 }
258
259                 [DllImport ("libc", SetLastError=true)]
260                 public static extern int chown (string path, int owner, int group);
261                 [DllImport ("libc", SetLastError=true)]
262                 public static extern int lchown (string path, int owner, int group);
263                 
264                 [DllImport ("libc", SetLastError=true)]
265                 public static extern int lseek (int fileDescriptor, int offset, int whence);
266
267                 [DllImport ("libc", SetLastError=true)]
268                 public static extern int getpid ();
269                 
270                 // TODO: mount
271                 // TODO: umount
272
273                 [DllImport ("libc", SetLastError=true)]
274                 public static extern int setuid (int uid);
275                 
276                 [DllImport ("libc", SetLastError=true)]
277                 public static extern int getuid ();
278
279                 // TODO: stime
280                 // TODO: ptrace
281                 
282                 [DllImport ("libc")]
283                 public static extern uint alarm (uint seconds);
284
285                 [DllImport ("libc", SetLastError=true)]
286                 public static extern int pause ();
287
288                 // TODO: utime
289
290                 [DllImport ("libc", EntryPoint="access", SetLastError=true)]
291                 internal extern static int syscall_access (string pathname, int mode);
292
293                 [DllImport ("MonoPosixHelper")]
294                 internal extern static int map_Mono_Posix_AccessMode (AccessMode mode);
295
296                 public static int access (string pathname, AccessMode mode)
297                 {
298                         return syscall_access (pathname, map_Mono_Posix_AccessMode (mode));
299                 }
300
301                 [DllImport ("libc", SetLastError=true)]
302                 public static extern int nice (int increment);
303
304                 // TODO: ftime
305
306                 [DllImport ("libc")]
307                 public static extern void sync ();
308
309                 [DllImport ("libc", SetLastError=true)]
310                 public static extern void kill (int pid, int sig);
311
312                 [DllImport ("libc", SetLastError=true)]
313                 public static extern int rename (string oldPath, string newPath);
314                 
315                 [DllImport ("libc", EntryPoint="mkdir", SetLastError=true)]
316                 internal extern static int syscall_mkdir (string pathname, int mode);
317
318                 public static int mkdir (string pathname, FileMode mode)
319                 {
320                         return syscall_mkdir (pathname, map_Mono_Posix_FileMode (mode));
321                 }
322
323                 [DllImport ("libc", SetLastError=true)]
324                 public static extern int rmdir (string path);
325
326                 [DllImport ("libc", SetLastError=true)]
327                 public static extern int dup (int fileDescriptor);
328
329                 // TODO: pipe
330                 // TODO: times
331
332                 [DllImport ("libc", SetLastError=true)]
333                 public static extern int setgid (int gid);
334                 [DllImport ("libc", SetLastError=true)]
335                 public static extern int getgid ();
336
337                 
338                 public delegate void sighandler_t (int v);
339                 
340                 [DllImport ("libc", SetLastError=true)]
341                 public static extern int signal (int signum, sighandler_t handler);
342                 
343                 [DllImport ("libc", SetLastError=true)]
344                 public static extern int geteuid ();
345                 
346                 [DllImport ("libc", SetLastError=true)]
347                 public static extern int getegid ();
348
349                 // TODO: fcntl
350                 
351                 [DllImport ("libc", SetLastError=true)]
352                 public static extern int setpgid (int pid, int pgid);
353
354                 // TODO: ulimit
355
356                 [DllImport ("libc")]
357                 public static extern int umask (int umask);
358
359                 [DllImport ("libc", SetLastError=true)]
360                 public static extern int chroot (string path);
361
362                 [DllImport ("libc", SetLastError=true)]
363                 public static extern int dup2 (int oldFileDescriptor, int newFileDescriptor);
364
365                 [DllImport ("libc", SetLastError=true)]
366                 public static extern int getppid ();
367
368                 [DllImport ("libc", SetLastError=true)]
369                 public static extern int getpgrp ();
370
371                 [DllImport ("libc", SetLastError=true)]
372                 public static extern int setsid ();
373                 
374                 // TODO: sigaction
375                 
376                 [DllImport ("libc", SetLastError=true)]
377                 public static extern int setreuid (int ruid, int euid);
378
379                 [DllImport ("libc", SetLastError=true)]
380                 public static extern int setregid (int rgid, int egid);
381
382                 // these don't exactly match POSIX, but it's a nice way to get user/group names
383                 
384                 [DllImport ("MonoPosixHelper", SetLastError=true)]
385                 private static extern string helper_Mono_Posix_GetUserName (int uid);
386
387                 [DllImport ("MonoPosixHelper", SetLastError=true)]
388                 private static extern string helper_Mono_Posix_GetGroupName (int gid);
389                 
390                 public static string getusername(int uid) { return helper_Mono_Posix_GetUserName(uid); }
391                 public static string getgroupname(int gid) { return helper_Mono_Posix_GetGroupName(gid); }
392                 
393                 // TODO: sigsuspend
394                 // TODO: sigpending
395                 // TODO: setrlimit
396                 // TODO: getrlimit
397                 // TODO: getrusage
398                 // TODO: gettimeofday
399                 // TODO: settimeofday
400                 
401                 [DllImport ("libc", EntryPoint="gethostname", SetLastError=true)]
402                 static extern int syscall_gethostname (byte[] p, int len);
403
404                 public static string GetHostName ()
405                 {
406                         byte [] buf = new byte [256];
407                         int res = syscall_gethostname (buf, buf.Length);
408                         if (res == -1)
409                                 return "localhost";
410                         for (res = 0; res < buf.Length; ++res) {
411                                 if (buf [res] == 0)
412                                         break;
413                         }
414                                 
415                         return Encoding.UTF8.GetString (buf, 0, res);
416                 }
417
418                 public static string gethostname ()
419                 {
420                         return GetHostName ();
421                 }
422                 
423
424                 [DllImport ("libc", EntryPoint="isatty")]
425                 static extern int syscall_isatty (int desc);
426                 
427                 public static bool isatty (int desc)
428                 {
429                         int res = syscall_isatty (desc);
430                         if (res == 1)
431                                 return true;
432                         else
433                                 return false;
434                 }
435                 
436
437                 [DllImport ("MonoPosixHelper")]
438                 internal extern static int helper_Mono_Posix_Stat (string filename, bool dereference,
439                         out int device, out int inode, out int mode,
440                         out int nlinks, out int uid, out int gid,
441                         out int rdev, out long size, out long blksize, out long blocks,
442                         out long atime, out long mtime, out long ctime);
443                 
444                 private static int stat2(string filename, bool dereference, out Stat stat) {
445                         int device, inode, mode;
446                         int nlinks, uid, gid, rdev;
447                         long size, blksize, blocks;
448                         long atime, mtime, ctime;
449
450                         int ret = helper_Mono_Posix_Stat(filename, dereference,
451                                 out device, out inode, out mode,
452                                 out nlinks, out uid, out gid,
453                                 out rdev, out size, out blksize, out blocks,
454                                 out atime, out mtime, out ctime);
455                                 
456                         stat = new Stat(
457                                 device, inode, mode,
458                                 nlinks, uid, gid,
459                                 rdev, size, blksize, blocks,
460                                 atime, mtime, ctime);
461
462                         if (ret != 0) return ret;
463
464                         return 0;
465                 }
466
467                 public static int stat(string filename, out Stat stat) {
468                         return stat2(filename, false, out stat);
469                 }
470
471                 public static int lstat(string filename, out Stat stat) {
472                         return stat2(filename, true, out stat);
473                 }
474                 
475                 [DllImport ("libc")]
476                 private static extern int readlink(string path, byte[] buffer, int buflen);
477
478                 public static string readlink(string path) {
479                         byte[] buf = new byte[512];
480                         int ret = readlink(path, buf, buf.Length);
481                         if (ret == -1) return null;
482                         char[] cbuf = new char[512];
483                         int chars = System.Text.Encoding.Default.GetChars(buf, 0, ret, cbuf, 0);
484                         return new String(cbuf, 0, chars);
485                 }
486
487                 [DllImport ("libc", EntryPoint="strerror")]
488                 static extern IntPtr _strerror(int errnum);
489
490                 public static string strerror (int errnum)
491                 {
492                         return Marshal.PtrToStringAnsi (_strerror (errnum));
493                 }
494
495                 [DllImport ("libc")]
496                 public static extern IntPtr opendir(string path);
497
498                 [DllImport ("libc")]
499                 public static extern int closedir(IntPtr dir);
500                 
501                 [DllImport ("MonoPosixHelper", EntryPoint="helper_Mono_Posix_readdir")]
502                 public static extern string readdir(IntPtr dir);
503                 
504         }
505         
506         public enum StatModeMasks {
507                 TypeMask = 0xF000, // bitmask for the file type bitfields
508                 OwnerMask = 0x1C0, // mask for file owner permissions
509                 GroupMask = 0x38, // mask for group permissions
510                 OthersMask = 0x7, // mask for permissions for others (not in group)
511         }
512         
513         [Flags]
514         public enum StatMode {
515                 Socket = 0xC000, // socket
516                 SymLink = 0xA000, // symbolic link
517                 Regular = 0x8000, // regular file
518                 BlockDevice = 0x6000, // block device
519                 Directory = 0x4000, // directory
520                 CharDevice = 0x2000, // character device
521                 FIFO = 0x1000, // fifo
522                 SUid = 0x800, // set UID bit
523                 SGid = 0x400, // set GID bit
524                 Sticky = 0x200, // sticky bit
525                 OwnerRead = 0x100, // owner has read permission
526                 OwnerWrite = 0x80, // owner has write permission
527                 OwnerExecute = 0x40, // owner has execute permission
528                 GroupRead = 0x20, // group has read permission
529                 GroupWrite = 0x10, // group has write permission
530                 GroupExecute = 0x8, // group has execute permission
531                 OthersRead = 0x4, // others have read permission
532                 OthersWrite = 0x2, // others have write permisson
533                 OthersExecute = 0x1, // others have execute permission  
534         }
535         
536         public struct Stat {
537                 public readonly int Device;
538                 public readonly int INode;
539                 public readonly StatMode Mode;
540                 public readonly int NLinks;
541                 public readonly int Uid;
542                 public readonly int Gid;
543                 public readonly long DeviceType;
544                 public readonly long Size;
545                 public readonly long BlockSize;
546                 public readonly long Blocks;
547                 public readonly DateTime ATime;
548                 public readonly DateTime MTime;
549                 public readonly DateTime CTime;
550                 
551                 public static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1).ToLocalTime();
552                 
553                 public static DateTime UnixToDateTime(long unix) {
554                         return UnixEpoch.Add(TimeSpan.FromSeconds(unix));
555                 }
556
557                 internal Stat(
558                         int device, int inode, int mode,
559                         int nlinks, int uid, int gid,
560                         int rdev, long size, long blksize, long blocks,
561                         long atime, long mtime, long ctime) {
562                         Device = device;
563                         INode = inode;
564                         Mode = (StatMode)mode;
565                         NLinks = nlinks;
566                         Uid = uid;
567                         Gid = gid;
568                         DeviceType = rdev;
569                         Size = size;
570                         BlockSize = blksize;
571                         Blocks = blocks;
572                         if (atime != 0)
573                                 ATime = UnixToDateTime(atime);
574                         else
575                                 ATime = new DateTime();
576                         if (mtime != 0)
577                                 MTime = UnixToDateTime(mtime);
578                         else
579                                 MTime = new DateTime();
580                         if (ctime != 0)
581                                 CTime = UnixToDateTime(ctime);
582                         else
583                                 CTime = new DateTime();
584                 }
585         }
586         
587
588 }