Rune Serialize - Stabilization, Generation, major overhaul
[rune.git] / classes / sys / fd.d
1 # SYS/FD.D - File descriptor / File System support
2 #
3
4 #%doc
5 #
6 # The Fs class handles most basic filesystem calls that manipulate
7 # file paths or descriptors.  A descriptor can be set in Fs.fd to enable
8 # descriptor-based system calls such as read().  Errors are typically
9 # returned (not always), and will always be recorded in the error field.
10 #
11 # The API explicitly allows the programmer to pull out descriptors and
12 # replicate Fs objects in order to e.g. separately track error conditions.
13 #
14 # All calls which create a new descriptor automatically set the descriptor
15 # O_CLOEXEC.  We do not expose OS-specific descriptor operations with flags
16 # for the same, on purpose.  e.g. open(), pipe(), socketpair(), dup(),
17 # dup2() all automatically set O_CLOEXEC.  The caller should use the
18 # setcloexec(TRUE/FALSE) call to change it.  All systems this language runs
19 # on are required to implement appropriate system calls to allow this.
20 #
21 # File descriptors can be passed around discretely without using the
22 # Fs class, as evidenced by some of the other structures in this module.
23 # Fs objects are needed as a container for method calls and error codes.
24 #
25 # Note that there is no auto-close destructor for this class.  Fs is
26 # meant to be used this way.  The programmer is responsible for
27 # closing file descriptors, or for embedding Fs into a larger class
28 # (such as our File or Stream class) which DOES close the underlying
29 # descriptors.
30 #
31 # read  - read the full request or until EOF.
32 # read1 - read at least 1 byte plus whatever else is available.
33 # readn - non-blocking read can return on EINTR or EAGAIN.
34 # write - write the full request or until an error.
35 # write1- write at least 1 byte plus whatever else it can.
36 # writen- non-blocking write can return on EINTR or EAGAIN.
37 # importdesc - adjust imported descriptor for rune operation
38 #
39 public class Fs {
40         public int fd = -1;     # field must match libruntime
41         public int error;       # field must match libruntime
42
43         # Run-time tie-ins.
44         #
45         # NOTE: These functions always set error, so if an operation has
46         #       no error, the error field will be set to 0.
47         #
48         public internal method size_t read(void *buf, size_t bytes,
49                                                 off_t off = -1);
50         public internal method size_t read1(void *buf, size_t bytes,
51                                                 off_t off = -1);
52         public internal method size_t readn(void *buf, size_t bytes,
53                                                 off_t off = -1);
54         public internal method size_t write(void *buf, size_t bytes,
55                                                 off_t off = -1);
56         public internal method size_t write1(void *buf, size_t bytes,
57                                                 off_t off = -1);
58         public internal method size_t writen(void *buf, size_t bytes,
59                                                 off_t off = -1);
60         public internal method int open(const char *path, int flags,
61                                                 int modes = 0666);
62         public internal method int close();
63
64         #% doc
65         #
66         # dup dups sfd and sets object->fd to the result.  Result is
67         # automatically O_CLOEXEC.
68         #
69         # dup2 dups sfd and sets object->fd to the result, using dfd.
70         # Result is automatically O_CLOEXEC.
71         #
72         public internal method int flock(int op);
73         public internal method int dup(int sfd);
74         public internal method int dup2(int sfd, int dfd);
75         public internal mode_t umask(mode_t mode);
76         public internal method off_t lseek(off_t off, int how);
77         public internal method int setcloexec(bool enable);
78         public internal method int setappend(bool enable);
79         public internal method int setnonblock(bool enable);
80         public internal method int setdirect(bool enable);
81         public internal method void importdesc();
82         public internal method void iowait_rd();
83         public internal method void iowait_wr();
84
85         #%doc
86         #
87         # These path based methods do not need an operational descriptor
88         # but are still method calls for error setting.
89         #
90         # (if I decide to add the 'at*' calls, those will).
91         #
92         public internal method int symlink(const char *buf, const char *nfile);
93         public internal method int link(const char *ofile, const char *nfile);
94         public internal method int readlink(const char *target, char *buf);
95         public internal method int unlink(const char *target);
96
97         #%doc
98         #
99         # pipe creates a one-way pipe with a read descriptor and a write
100         # descriptor.  The descriptors are O_CLOEXEC on return.
101         #
102         # socketpair creates a full-duplex socket (or pipe).  The descriptors
103         # are O_CLOEXEC on return.
104         #
105         public internal int pipe(lvalue Fs fdr, lvalue Fs fdw);
106         public internal int socketpair(int d, int type, int proto,
107                                         lvalue Fs fdr, lvalue Fs fdw);
108
109 }
110
111 public method
112 void
113 Fs.setfd(int fd)
114 {
115         this.fd = fd;
116 }
117
118 #%doc
119 #
120 # The FdLock class manages fcntl-based locking operations.  Fields
121 # basically work the same as you'd expect in C.  The structure is
122 # not field-for-field compatible (the rune pid_t might be a different size),
123 # but the system interface will translate.
124 #
125 # This class has an auto-unlock destructor.
126 #
127 public class FdLock {
128         off_t   start;                  # all fields must match libruntime
129         off_t   len;
130         pid_t   pid = -1;
131         int     type = F_UNLCK;
132         int     whence = SEEK_SET;
133         int     error;
134         int     fd;
135         int     active;
136         public internal method int fgetlk();
137         public internal method int fsetlk();
138         public internal method int fsetlkw();
139 }
140
141 public destructor method
142 void
143 FdLock.destruct()
144 {
145         if (this.active && this.type != F_UNLCK) {
146                 this.type = F_UNLCK;
147                 this.fsetlk();
148                 this.active = 0;
149         }
150 }
151
152 #%doc
153 #
154 # The FdMap class manages memory maps.  Note that this class has an
155 # auto-unmap destructor.
156 #
157 # NOTE: You may assign the base pointer to any structural pointer you
158 #       desire as long as the structure contains no lvalues, pointers, or
159 #       references, and the target structure is an integral multiple of
160 #       the number of bytes mapped.
161 #
162 public class FdMap {
163         public constant char *base;     # all fields must match libruntime
164         public constant size_t bytes;
165         public int error;
166         public int mapped;
167
168         public internal method int mmap(size_t bytes, int prot, int flags,
169                                                 int fd = -1, off_t offset = 0);
170         public internal method int munmap();
171         public internal method int mprotect(int prot, size_t off = 0,
172                                                 size_t bytes = this.bytes);
173         public internal method int madvise(int behav, size_t off = 0,
174                                                 size_t bytes = this.bytes);
175         public internal method int msync(size_t off = 0,
176                                                 size_t bytes = this.bytes,
177                                                 int flags = MS_ASYNC);
178 }
179
180 public destructor method
181 void
182 FdMap.destruct()
183 {
184         if (this.mapped)
185                 this.munmap();
186 }