2
* POSIX-compatible libc layer
4
* Samuel Thibault <Samuel.Thibault@eu.citrix.net>, October 2007
6
* Provides the UNIXish part of the standard libc function.
8
* Relatively straight-forward: just multiplex the file descriptor operations
9
* among the various file types (console, FS, network, ...)
12
//#define LIBC_VERBOSE
16
#define DEBUG(fmt,...) printk(fmt, ##__VA_ARGS__)
18
#define DEBUG(fmt,...)
33
#include <sys/types.h>
34
#include <sys/unistd.h>
48
#include <lwip/sockets.h>
52
#define debug(fmt, ...) \
54
#define print_unsupported(fmt, ...) \
55
printk("Unsupported function "fmt" called in Mini-OS kernel\n", ## __VA_ARGS__);
57
/* Crash on function call */
58
#define unsupported_function_crash(function) \
59
int __unsup_##function(void) asm(#function); \
60
int __unsup_##function(void) \
62
print_unsupported(#function); \
66
/* Log and err out on function call */
67
#define unsupported_function_log(type, function, ret) \
68
type __unsup_##function(void) asm(#function); \
69
type __unsup_##function(void) \
71
print_unsupported(#function); \
76
/* Err out on function call */
77
#define unsupported_function(type, function, ret) \
78
type __unsup_##function(void) asm(#function); \
79
type __unsup_##function(void) \
86
extern int xc_evtchn_close(int fd);
87
extern int xc_interface_close(int fd);
88
extern int xc_gnttab_close(int fd);
90
pthread_mutex_t fd_lock = PTHREAD_MUTEX_INITIALIZER;
91
struct file files[NOFILE] = {
92
{ .type = FTYPE_CONSOLE }, /* stdin */
93
{ .type = FTYPE_CONSOLE }, /* stdout */
94
{ .type = FTYPE_CONSOLE }, /* stderr */
97
DECLARE_WAIT_QUEUE_HEAD(event_queue);
99
int alloc_fd(enum fd_type type)
102
pthread_mutex_lock(&fd_lock);
103
for (i=0; i<NOFILE; i++) {
104
if (files[i].type == FTYPE_NONE) {
105
files[i].type = type;
106
pthread_mutex_unlock(&fd_lock);
110
pthread_mutex_unlock(&fd_lock);
111
printk("Too many opened files\n");
115
void close_all_files(void)
118
pthread_mutex_lock(&fd_lock);
119
for (i=NOFILE - 1; i > 0; i--)
120
if (files[i].type != FTYPE_NONE)
122
pthread_mutex_unlock(&fd_lock);
125
int dup2(int oldfd, int newfd)
127
pthread_mutex_lock(&fd_lock);
128
if (files[newfd].type != FTYPE_NONE)
130
// XXX: this is a bit bogus, as we are supposed to share the offset etc
131
files[newfd] = files[oldfd];
132
pthread_mutex_unlock(&fd_lock);
151
char *getcwd(char *buf, size_t size)
153
snprintf(buf, size, "/");
157
#define LOG_PATH "/var/log/"
159
int mkdir(const char *pathname, mode_t mode)
162
ret = fs_create(fs_import, (char *) pathname, 1, mode);
170
int posix_openpt(int flags)
172
struct consfront_dev *dev;
176
dev = init_consfront(NULL);
177
dev->fd = alloc_fd(FTYPE_CONSOLE);
178
files[dev->fd].cons.dev = dev;
180
printk("fd(%d) = posix_openpt\n", dev->fd);
184
int open(const char *pathname, int flags, ...)
187
/* Ugly, but fine. */
188
if (!strncmp(pathname,LOG_PATH,strlen(LOG_PATH))) {
189
fd = alloc_fd(FTYPE_CONSOLE);
190
printk("open(%s) -> %d\n", pathname, fd);
193
if (!strncmp(pathname, "/dev/mem", strlen("/dev/mem"))) {
194
fd = alloc_fd(FTYPE_MEM);
195
printk("open(/dev/mem) -> %d\n", fd);
198
if (!strncmp(pathname, "/dev/ptmx", strlen("/dev/ptmx")))
199
return posix_openpt(flags);
200
printk("open(%s, %x)", pathname, flags);
201
switch (flags & ~O_ACCMODE) {
203
fs_fd = fs_open(fs_import, (void *) pathname);
205
case O_CREAT|O_TRUNC:
210
mode = va_arg(ap, mode_t);
212
fs_fd = fs_create(fs_import, (void *) pathname, 0, mode);
216
printk(" unsupported flags\n");
223
fd = alloc_fd(FTYPE_FILE);
224
printk("-> %d\n", fd);
225
files[fd].file.fd = fs_fd;
226
files[fd].file.offset = 0;
232
return files[fd].type == FTYPE_CONSOLE;
235
int read(int fd, void *buf, size_t nbytes)
237
switch (files[fd].type) {
238
case FTYPE_CONSOLE: {
242
add_waiter(w, console_queue);
243
ret = xencons_ring_recv(files[fd].cons.dev, buf, nbytes);
253
if (nbytes > PAGE_SIZE * FSIF_NR_READ_GNTS)
254
nbytes = PAGE_SIZE * FSIF_NR_READ_GNTS;
255
ret = fs_read(fs_import, files[fd].file.fd, buf, nbytes, files[fd].file.offset);
257
files[fd].file.offset += ret;
259
} else if (ret < 0) {
267
return lwip_read(files[fd].socket.fd, buf, nbytes);
271
ret = netfront_receive(files[fd].tap.dev, buf, nbytes);
280
n = nbytes / sizeof(union xenkbd_in_event);
281
ret = kbdfront_receive(files[fd].kbd.dev, buf, n);
286
return ret * sizeof(union xenkbd_in_event);
290
n = nbytes / sizeof(union xenfb_in_event);
291
ret = fbfront_receive(files[fd].fb.dev, buf, n);
296
return ret * sizeof(union xenfb_in_event);
301
printk("read(%d): Bad descriptor\n", fd);
306
int write(int fd, const void *buf, size_t nbytes)
308
switch (files[fd].type) {
310
console_print(files[fd].cons.dev, (char *)buf, nbytes);
314
if (nbytes > PAGE_SIZE * FSIF_NR_WRITE_GNTS)
315
nbytes = PAGE_SIZE * FSIF_NR_WRITE_GNTS;
316
ret = fs_write(fs_import, files[fd].file.fd, (void *) buf, nbytes, files[fd].file.offset);
318
files[fd].file.offset += ret;
320
} else if (ret < 0) {
328
return lwip_write(files[fd].socket.fd, (void*) buf, nbytes);
331
netfront_xmit(files[fd].tap.dev, (void*) buf, nbytes);
336
printk("write(%d): Bad descriptor\n", fd);
341
off_t lseek(int fd, off_t offset, int whence)
343
if (files[fd].type != FTYPE_FILE) {
349
files[fd].file.offset = offset;
352
files[fd].file.offset += offset;
357
ret = fstat(fd, &st);
360
files[fd].file.offset = st.st_size + offset;
367
return files[fd].file.offset;
371
switch (files[fd].type) {
374
ret = fs_sync(fs_import, files[fd].file.fd);
384
printk("fsync(%d): Bad descriptor\n", fd);
391
printk("close(%d)\n", fd);
392
switch (files[fd].type) {
394
files[fd].type = FTYPE_NONE;
397
int ret = fs_close(fs_import, files[fd].file.fd);
398
files[fd].type = FTYPE_NONE;
406
xs_daemon_close((void*)(intptr_t) fd);
410
int res = lwip_close(files[fd].socket.fd);
411
files[fd].type = FTYPE_NONE;
416
xc_interface_close(fd);
425
shutdown_netfront(files[fd].tap.dev);
426
files[fd].type = FTYPE_NONE;
429
shutdown_blkfront(files[fd].blk.dev);
430
files[fd].type = FTYPE_NONE;
433
shutdown_kbdfront(files[fd].kbd.dev);
434
files[fd].type = FTYPE_NONE;
437
shutdown_fbfront(files[fd].fb.dev);
438
files[fd].type = FTYPE_NONE;
441
fini_console(files[fd].cons.dev);
442
files[fd].type = FTYPE_NONE;
447
printk("close(%d): Bad descriptor\n", fd);
452
static void init_stat(struct stat *buf)
454
memset(buf, 0, sizeof(*buf));
459
buf->st_blksize = 4096;
463
static void stat_from_fs(struct stat *buf, struct fsif_stat_response *stat)
465
buf->st_mode = stat->stat_mode;
466
buf->st_uid = stat->stat_uid;
467
buf->st_gid = stat->stat_gid;
468
buf->st_size = stat->stat_size;
469
buf->st_atime = stat->stat_atime;
470
buf->st_mtime = stat->stat_mtime;
471
buf->st_ctime = stat->stat_ctime;
474
int stat(const char *path, struct stat *buf)
476
struct fsif_stat_response stat;
479
printk("stat(%s)\n", path);
480
fs_fd = fs_open(fs_import, (char*) path);
486
ret = fs_stat(fs_import, fs_fd, &stat);
493
stat_from_fs(buf, &stat);
497
fs_close(fs_import, fs_fd);
502
int fstat(int fd, struct stat *buf)
505
switch (files[fd].type) {
508
buf->st_mode = (files[fd].type == FTYPE_CONSOLE?S_IFCHR:S_IFSOCK) | S_IRUSR|S_IWUSR;
514
buf->st_ctime = time(NULL);
518
struct fsif_stat_response stat;
520
ret = fs_stat(fs_import, files[fd].file.fd, &stat);
525
/* The protocol is a bit evasive about this value */
526
stat_from_fs(buf, &stat);
533
printk("statf(%d): Bad descriptor\n", fd);
538
int ftruncate(int fd, off_t length)
540
switch (files[fd].type) {
543
ret = fs_truncate(fs_import, files[fd].file.fd, length);
554
printk("ftruncate(%d): Bad descriptor\n", fd);
559
int remove(const char *pathname)
562
printk("remove(%s)", pathname);
563
ret = fs_remove(fs_import, (char*) pathname);
571
int unlink(const char *pathname)
573
return remove(pathname);
576
int rmdir(const char *pathname)
578
return remove(pathname);
581
int fcntl(int fd, int cmd, ...)
586
arg = va_arg(ap, long);
592
if (files[fd].type == FTYPE_SOCKET && !(arg & ~O_NONBLOCK)) {
593
/* Only flag supported: non-blocking mode */
594
uint32_t nblock = !!(arg & O_NONBLOCK);
595
return lwip_ioctl(files[fd].socket.fd, FIONBIO, &nblock);
600
printk("fcntl(%d, %d, %lx/%lo)\n", fd, cmd, arg, arg);
606
DIR *opendir(const char *name)
609
ret = malloc(sizeof(*ret));
610
ret->name = strdup(name);
619
struct dirent *readdir(DIR *dir)
621
if (dir->curentry >= 0) {
622
free(dir->entries[dir->curentry]);
623
dir->entries[dir->curentry] = NULL;
626
if (dir->curentry >= dir->nbentries) {
627
dir->offset += dir->nbentries;
633
dir->entries = fs_list(fs_import, dir->name, dir->offset, &dir->nbentries, &dir->has_more);
634
if (!dir->entries || !dir->nbentries)
638
dir->dirent.d_name = dir->entries[dir->curentry];
641
int closedir(DIR *dir)
644
for (i=0; i<dir->nbentries; i++)
645
free(dir->entries[i]);
652
/* We assume that only the main thread calls select(). */
654
static const char file_types[] = {
656
[FTYPE_CONSOLE] = 'C',
658
[FTYPE_XENBUS] = 'S',
660
[FTYPE_EVTCHN] = 'E',
661
[FTYPE_SOCKET] = 's',
668
static void dump_set(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
671
#define printfds(set) do {\
673
for (i = 0; i < nfds; i++) { \
674
if (FD_ISSET(i, set)) { \
677
printk("%d(%c)", i, file_types[files[i].type]); \
694
printk("{ %ld, %ld }", timeout->tv_sec, timeout->tv_usec);
697
#define dump_set(nfds, readfds, writefds, exceptfds, timeout)
700
/* Just poll without blocking */
701
static int select_poll(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds)
705
int sock_n = 0, sock_nfds = 0;
706
fd_set sock_readfds, sock_writefds, sock_exceptfds;
707
struct timeval timeout = { .tv_sec = 0, .tv_usec = 0};
712
static int nbread[NOFILE], nbwrite[NOFILE], nbexcept[NOFILE];
713
static s_time_t lastshown;
719
/* first poll network */
720
FD_ZERO(&sock_readfds);
721
FD_ZERO(&sock_writefds);
722
FD_ZERO(&sock_exceptfds);
723
for (i = 0; i < nfds; i++) {
724
if (files[i].type == FTYPE_SOCKET) {
725
if (FD_ISSET(i, readfds)) {
726
FD_SET(files[i].socket.fd, &sock_readfds);
729
if (FD_ISSET(i, writefds)) {
730
FD_SET(files[i].socket.fd, &sock_writefds);
733
if (FD_ISSET(i, exceptfds)) {
734
FD_SET(files[i].socket.fd, &sock_exceptfds);
740
DEBUG("lwip_select(");
741
dump_set(nfds, &sock_readfds, &sock_writefds, &sock_exceptfds, &timeout);
743
sock_n = lwip_select(sock_nfds, &sock_readfds, &sock_writefds, &sock_exceptfds, &timeout);
744
dump_set(nfds, &sock_readfds, &sock_writefds, &sock_exceptfds, &timeout);
749
/* Then see others as well. */
750
for (i = 0; i < nfds; i++) {
751
switch(files[i].type) {
753
if (FD_ISSET(i, readfds) || FD_ISSET(i, writefds) || FD_ISSET(i, exceptfds))
754
printk("bogus fd %d in select\n", i);
759
FD_CLR(i, exceptfds);
762
if (FD_ISSET(i, readfds)) {
763
if (xencons_ring_avail(files[i].cons.dev))
768
if (FD_ISSET(i, writefds))
770
FD_CLR(i, exceptfds);
773
if (FD_ISSET(i, readfds)) {
774
if (files[i].xenbus.events)
780
FD_CLR(i, exceptfds);
787
if (FD_ISSET(i, readfds)) {
794
FD_CLR(i, exceptfds);
798
if (FD_ISSET(i, readfds)) {
799
/* Optimize no-network-packet case. */
800
if (sock_n && FD_ISSET(files[i].socket.fd, &sock_readfds))
805
if (FD_ISSET(i, writefds)) {
806
if (sock_n && FD_ISSET(files[i].socket.fd, &sock_writefds))
811
if (FD_ISSET(i, exceptfds)) {
812
if (sock_n && FD_ISSET(files[i].socket.fd, &sock_exceptfds))
815
FD_CLR(i, exceptfds);
821
if (FD_ISSET(i, readfds))
823
if (FD_ISSET(i, writefds))
825
if (FD_ISSET(i, exceptfds))
830
if (NOW() > lastshown + 1000000000ull) {
832
printk("%lu MB free, ", num_free_pages() / ((1 << 20) / PAGE_SIZE));
833
printk("%d(%d): ", nb, sock_n);
834
for (i = 0; i < nfds; i++) {
835
if (nbread[i] || nbwrite[i] || nbexcept[i])
836
printk(" %d(%c):", i, file_types[files[i].type]);
838
printk(" %dR", nbread[i]);
840
printk(" %dW", nbwrite[i]);
842
printk(" %dE", nbexcept[i]);
845
memset(nbread, 0, sizeof(nbread));
846
memset(nbwrite, 0, sizeof(nbwrite));
847
memset(nbexcept, 0, sizeof(nbexcept));
854
/* The strategy is to
855
* - announce that we will maybe sleep
856
* - poll a bit ; if successful, return
857
* - if timeout, return
858
* - really sleep (except if somebody woke us in the meanwhile) */
859
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
860
struct timeval *timeout)
863
fd_set myread, mywrite, myexcept;
864
struct thread *thread = get_current();
865
s_time_t start = NOW(), stop;
873
assert(thread == main_thread);
875
DEBUG("select(%d, ", nfds);
876
dump_set(nfds, readfds, writefds, exceptfds, timeout);
880
stop = start + SECONDS(timeout->tv_sec) + timeout->tv_usec * 1000;
882
/* just make gcc happy */
885
/* Tell people we're going to sleep before looking at what they are
886
* saying, hence letting them wake us if events happen between here and
888
add_waiter(w1, netfront_queue);
889
add_waiter(w2, event_queue);
890
add_waiter(w3, blkfront_queue);
891
add_waiter(w4, xenbus_watch_queue);
892
add_waiter(w5, kbdfront_queue);
893
add_waiter(w6, console_queue);
904
myexcept = *exceptfds;
909
dump_set(nfds, &myread, &mywrite, &myexcept, timeout);
911
n = select_poll(nfds, &myread, &mywrite, &myexcept);
914
dump_set(nfds, readfds, writefds, exceptfds, timeout);
920
*exceptfds = myexcept;
922
dump_set(nfds, readfds, writefds, exceptfds, timeout);
928
if (timeout && NOW() >= stop) {
936
timeout->tv_usec = 0;
943
thread->wakeup_time = stop;
955
myexcept = *exceptfds;
959
n = select_poll(nfds, &myread, &mywrite, &myexcept);
967
*exceptfds = myexcept;
985
int socket(int domain, int type, int protocol)
988
fd = lwip_socket(domain, type, protocol);
991
res = alloc_fd(FTYPE_SOCKET);
992
printk("socket -> %d\n", res);
993
files[res].socket.fd = fd;
997
int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
1000
if (files[s].type != FTYPE_SOCKET) {
1001
printk("accept(%d): Bad descriptor\n", s);
1005
fd = lwip_accept(files[s].socket.fd, addr, addrlen);
1008
res = alloc_fd(FTYPE_SOCKET);
1009
files[res].socket.fd = fd;
1010
printk("accepted on %d -> %d\n", s, res);
1014
#define LWIP_STUB(ret, name, proto, args) \
1017
if (files[s].type != FTYPE_SOCKET) { \
1018
printk(#name "(%d): Bad descriptor\n", s); \
1022
s = files[s].socket.fd; \
1023
return lwip_##name args; \
1026
LWIP_STUB(int, bind, (int s, struct sockaddr *my_addr, socklen_t addrlen), (s, my_addr, addrlen))
1027
LWIP_STUB(int, getsockopt, (int s, int level, int optname, void *optval, socklen_t *optlen), (s, level, optname, optval, optlen))
1028
LWIP_STUB(int, setsockopt, (int s, int level, int optname, void *optval, socklen_t optlen), (s, level, optname, optval, optlen))
1029
LWIP_STUB(int, connect, (int s, struct sockaddr *serv_addr, socklen_t addrlen), (s, serv_addr, addrlen))
1030
LWIP_STUB(int, listen, (int s, int backlog), (s, backlog));
1031
LWIP_STUB(ssize_t, recv, (int s, void *buf, size_t len, int flags), (s, buf, len, flags))
1032
LWIP_STUB(ssize_t, recvfrom, (int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen), (s, buf, len, flags, from, fromlen))
1033
LWIP_STUB(ssize_t, send, (int s, void *buf, size_t len, int flags), (s, buf, len, flags))
1034
LWIP_STUB(ssize_t, sendto, (int s, void *buf, size_t len, int flags, struct sockaddr *to, socklen_t tolen), (s, buf, len, flags, to, tolen))
1035
LWIP_STUB(int, getsockname, (int s, struct sockaddr *name, socklen_t *namelen), (s, name, namelen))
1038
static char *syslog_ident;
1039
void openlog(const char *ident, int option, int facility)
1043
syslog_ident = strdup(ident);
1046
void vsyslog(int priority, const char *format, va_list ap)
1048
printk("%s: ", syslog_ident);
1049
print(0, format, ap);
1052
void syslog(int priority, const char *format, ...)
1055
va_start(ap, format);
1056
vsyslog(priority, format, ap);
1063
syslog_ident = NULL;
1066
void vwarn(const char *format, va_list ap)
1068
int the_errno = errno;
1069
printk("stubdom: ");
1071
print(0, format, ap);
1074
printk("%s", strerror(the_errno));
1077
void warn(const char *format, ...)
1080
va_start(ap, format);
1085
void verr(int eval, const char *format, va_list ap)
1091
void err(int eval, const char *format, ...)
1094
va_start(ap, format);
1095
verr(eval, format, ap);
1099
void vwarnx(const char *format, va_list ap)
1101
printk("stubdom: ");
1103
print(0, format, ap);
1106
void warnx(const char *format, ...)
1109
va_start(ap, format);
1114
void verrx(int eval, const char *format, va_list ap)
1120
void errx(int eval, const char *format, ...)
1123
va_start(ap, format);
1124
verrx(eval, format, ap);
1128
int nanosleep(const struct timespec *req, struct timespec *rem)
1130
s_time_t start = NOW();
1131
s_time_t stop = start + SECONDS(req->tv_sec) + req->tv_nsec;
1133
struct thread *thread = get_current();
1135
thread->wakeup_time = stop;
1136
clear_runnable(thread);
1142
s_time_t remaining = stop - stopped;
1145
rem->tv_nsec = remaining % 1000000000ULL;
1146
rem->tv_sec = remaining / 1000000000ULL;
1147
} else memset(rem, 0, sizeof(*rem));
1153
int usleep(useconds_t usec)
1155
/* "usec shall be less than one million." */
1156
struct timespec req;
1157
req.tv_nsec = usec * 1000;
1160
if (nanosleep(&req, NULL))
1166
unsigned int sleep(unsigned int seconds)
1168
struct timespec req, rem;
1169
req.tv_sec = seconds;
1172
if (nanosleep(&req, &rem))
1175
if (rem.tv_nsec > 0)
1181
int clock_gettime(clockid_t clk_id, struct timespec *tp)
1184
case CLOCK_MONOTONIC:
1188
gettimeofday(&tv, NULL);
1190
tp->tv_sec = tv.tv_sec;
1191
tp->tv_nsec = tv.tv_usec * 1000;
1195
case CLOCK_REALTIME:
1197
uint64_t nsec = monotonic_clock();
1199
tp->tv_sec = nsec / 1000000000ULL;
1200
tp->tv_nsec = nsec % 1000000000ULL;
1205
print_unsupported("clock_gettime(%d)", clk_id);
1233
int gethostname(char *name, size_t namelen)
1235
strncpy(name, "mini-os", namelen);
1239
size_t getpagesize(void)
1244
void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset)
1246
unsigned long n = (length + PAGE_SIZE - 1) / PAGE_SIZE;
1249
ASSERT(prot == (PROT_READ|PROT_WRITE));
1250
ASSERT((fd == -1 && (flags == (MAP_SHARED|MAP_ANON) || flags == (MAP_PRIVATE|MAP_ANON)))
1251
|| (fd != -1 && flags == MAP_SHARED));
1254
return map_zero(n, 1);
1255
else if (files[fd].type == FTYPE_XC) {
1256
unsigned long zero = 0;
1257
return map_frames_ex(&zero, n, 0, 0, 1, DOMID_SELF, NULL, 0);
1258
} else if (files[fd].type == FTYPE_MEM) {
1259
unsigned long first_mfn = offset >> PAGE_SHIFT;
1260
return map_frames_ex(&first_mfn, n, 0, 1, 1, DOMID_IO, NULL, _PAGE_PRESENT|_PAGE_RW);
1264
int munmap(void *start, size_t length)
1266
int total = length / PAGE_SIZE;
1269
ret = unmap_frames((unsigned long)start, (unsigned long)total);
1277
void sparse(unsigned long data, size_t size)
1279
unsigned long newdata;
1283
newdata = (data + PAGE_SIZE - 1) & PAGE_MASK;
1284
if (newdata - data > size)
1286
size -= newdata - data;
1288
n = size / PAGE_SIZE;
1289
size = n * PAGE_SIZE;
1291
mfns = malloc(n * sizeof(*mfns));
1292
for (i = 0; i < n; i++) {
1295
for (j=0; j<PAGE_SIZE; j++)
1296
if (((char*)data + i * PAGE_SIZE)[j]) {
1297
printk("%lx is not zero!\n", data + i * PAGE_SIZE + j);
1301
mfns[i] = virtual_to_mfn(data + i * PAGE_SIZE);
1304
printk("sparsing %ldMB at %lx\n", size >> 20, data);
1306
munmap((void *) data, size);
1307
free_physical_pages(mfns, n);
1308
do_map_zero(data, n);
1313
printk("nice() stub called with inc=%d\n", inc);
1318
/* Not supported by FS yet. */
1319
unsupported_function_crash(link);
1320
unsupported_function(int, readlink, -1);
1321
unsupported_function_crash(umask);
1323
/* We could support that. */
1324
unsupported_function_log(int, chdir, -1);
1326
/* No dynamic library support. */
1327
unsupported_function_log(void *, dlopen, NULL);
1328
unsupported_function_log(void *, dlsym, NULL);
1329
unsupported_function_log(char *, dlerror, NULL);
1330
unsupported_function_log(int, dlclose, -1);
1332
/* We don't raise signals anyway. */
1333
unsupported_function(int, sigemptyset, -1);
1334
unsupported_function(int, sigfillset, -1);
1335
unsupported_function(int, sigaddset, -1);
1336
unsupported_function(int, sigdelset, -1);
1337
unsupported_function(int, sigismember, -1);
1338
unsupported_function(int, sigprocmask, -1);
1339
unsupported_function(int, sigaction, -1);
1340
unsupported_function(int, __sigsetjmp, 0);
1341
unsupported_function(int, sigaltstack, -1);
1342
unsupported_function_crash(kill);
1345
unsupported_function_crash(pipe);
1346
unsupported_function_crash(fork);
1347
unsupported_function_crash(execv);
1348
unsupported_function_crash(execve);
1349
unsupported_function_crash(waitpid);
1350
unsupported_function_crash(wait);
1351
unsupported_function_crash(lockf);
1352
unsupported_function_crash(sysconf);
1353
unsupported_function(int, tcsetattr, -1);
1354
unsupported_function(int, tcgetattr, 0);
1355
unsupported_function(int, grantpt, -1);
1356
unsupported_function(int, unlockpt, -1);
1357
unsupported_function(char *, ptsname, NULL);
1358
unsupported_function(int, poll, -1);
1361
unsupported_function_log(unsigned int, if_nametoindex, -1);
1362
unsupported_function_log(char *, if_indextoname, (char *) NULL);
1363
unsupported_function_log(struct if_nameindex *, if_nameindex, (struct if_nameindex *) NULL);
1364
unsupported_function_crash(if_freenameindex);
1366
/* Linuxish abi for the Caml runtime, don't support
1367
Log, and return an error code if possible. If it is not possible
1368
to inform the application of an error, then crash instead!
1370
unsupported_function_log(struct dirent *, readdir64, NULL);
1371
unsupported_function_log(int, getrusage, -1);
1372
unsupported_function_log(int, getrlimit, -1);
1373
unsupported_function_log(int, getrlimit64, -1);
1374
unsupported_function_log(int, __xstat64, -1);
1375
unsupported_function_log(long, __strtol_internal, LONG_MIN);
1376
unsupported_function_log(double, __strtod_internal, HUGE_VAL);
1377
unsupported_function_log(int, utime, -1);
1378
unsupported_function_log(int, truncate64, -1);
1379
unsupported_function_log(int, tcflow, -1);
1380
unsupported_function_log(int, tcflush, -1);
1381
unsupported_function_log(int, tcdrain, -1);
1382
unsupported_function_log(int, tcsendbreak, -1);
1383
unsupported_function_log(int, cfsetospeed, -1);
1384
unsupported_function_log(int, cfsetispeed, -1);
1385
unsupported_function_crash(cfgetospeed);
1386
unsupported_function_crash(cfgetispeed);
1387
unsupported_function_log(int, symlink, -1);
1388
unsupported_function_log(const char*, inet_ntop, NULL);
1389
unsupported_function_crash(__fxstat64);
1390
unsupported_function_crash(__lxstat64);
1391
unsupported_function_log(int, socketpair, -1);
1392
unsupported_function_crash(sigsuspend);
1393
unsupported_function_log(int, sigpending, -1);
1394
unsupported_function_log(int, shutdown, -1);
1395
unsupported_function_log(int, setuid, -1);
1396
unsupported_function_log(int, setgid, -1);
1397
unsupported_function_crash(rewinddir);
1398
unsupported_function_log(int, getpriority, -1);
1399
unsupported_function_log(int, setpriority, -1);
1400
unsupported_function_log(int, mkfifo, -1);
1401
unsupported_function_log(int, getitimer, -1);
1402
unsupported_function_log(int, setitimer, -1);
1403
unsupported_function_log(void *, getservbyport, NULL);
1404
unsupported_function_log(void *, getservbyname, NULL);
1405
unsupported_function_log(void *, getpwuid, NULL);
1406
unsupported_function_log(void *, getpwnam, NULL);
1407
unsupported_function_log(void *, getprotobynumber, NULL);
1408
unsupported_function_log(void *, getprotobyname, NULL);
1409
unsupported_function_log(int, getpeername, -1);
1410
unsupported_function_log(int, getnameinfo, -1);
1411
unsupported_function_log(char *, getlogin, NULL);
1412
unsupported_function_crash(__h_errno_location);
1413
unsupported_function_log(int, gethostbyname_r, -1);
1414
unsupported_function_log(int, gethostbyaddr_r, -1);
1415
unsupported_function_log(int, getgroups, -1);
1416
unsupported_function_log(void *, getgrgid, NULL);
1417
unsupported_function_log(void *, getgrnam, NULL);
1418
unsupported_function_log(int, getaddrinfo, -1);
1419
unsupported_function_log(int, freeaddrinfo, -1);
1420
unsupported_function_log(int, ftruncate64, -1);
1421
unsupported_function_log(int, fchown, -1);
1422
unsupported_function_log(int, fchmod, -1);
1423
unsupported_function_crash(execvp);
1424
unsupported_function_log(int, dup, -1)
1425
unsupported_function_log(int, chroot, -1)
1426
unsupported_function_log(int, chown, -1);
1427
unsupported_function_log(int, chmod, -1);
1428
unsupported_function_crash(alarm);
1429
unsupported_function_log(int, inet_pton, -1);
1430
unsupported_function_log(int, access, -1);