~ubuntu-branches/ubuntu/utopic/xen/utopic

« back to all changes in this revision

Viewing changes to extras/mini-os/lib/sys.c

  • Committer: Bazaar Package Importer
  • Author(s): Bastian Blank
  • Date: 2010-05-06 15:47:38 UTC
  • mto: (1.3.1) (15.1.1 sid) (4.1.1 experimental)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20100506154738-agoz0rlafrh1fnq7
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * POSIX-compatible libc layer
 
3
 *
 
4
 * Samuel Thibault <Samuel.Thibault@eu.citrix.net>, October 2007
 
5
 *
 
6
 * Provides the UNIXish part of the standard libc function.
 
7
 *
 
8
 * Relatively straight-forward: just multiplex the file descriptor operations
 
9
 * among the various file types (console, FS, network, ...)
 
10
 */
 
11
 
 
12
//#define LIBC_VERBOSE
 
13
//#define LIBC_DEBUG
 
14
 
 
15
#ifdef LIBC_DEBUG
 
16
#define DEBUG(fmt,...) printk(fmt, ##__VA_ARGS__)
 
17
#else
 
18
#define DEBUG(fmt,...)
 
19
#endif
 
20
 
 
21
#ifdef HAVE_LIBC
 
22
#include <os.h>
 
23
#include <console.h>
 
24
#include <sched.h>
 
25
#include <events.h>
 
26
#include <wait.h>
 
27
#include <netfront.h>
 
28
#include <blkfront.h>
 
29
#include <fbfront.h>
 
30
#include <xenbus.h>
 
31
#include <xs.h>
 
32
 
 
33
#include <sys/types.h>
 
34
#include <sys/unistd.h>
 
35
#include <sys/stat.h>
 
36
#include <sys/mman.h>
 
37
#include <net/if.h>
 
38
#include <time.h>
 
39
#include <errno.h>
 
40
#include <fcntl.h>
 
41
#include <pthread.h>
 
42
#include <assert.h>
 
43
#include <dirent.h>
 
44
#include <stdlib.h>
 
45
#include <math.h>
 
46
 
 
47
#ifdef HAVE_LWIP
 
48
#include <lwip/sockets.h>
 
49
#endif
 
50
#include <fs.h>
 
51
 
 
52
#define debug(fmt, ...) \
 
53
 
 
54
#define print_unsupported(fmt, ...) \
 
55
    printk("Unsupported function "fmt" called in Mini-OS kernel\n", ## __VA_ARGS__);
 
56
 
 
57
/* Crash on function call */
 
58
#define unsupported_function_crash(function) \
 
59
    int __unsup_##function(void) asm(#function); \
 
60
    int __unsup_##function(void) \
 
61
    { \
 
62
        print_unsupported(#function); \
 
63
        do_exit(); \
 
64
    }
 
65
 
 
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) \
 
70
    { \
 
71
        print_unsupported(#function); \
 
72
        errno = ENOSYS; \
 
73
        return ret; \
 
74
    }
 
75
 
 
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) \
 
80
    { \
 
81
        errno = ENOSYS; \
 
82
        return ret; \
 
83
    }
 
84
 
 
85
#define NOFILE 32
 
86
extern int xc_evtchn_close(int fd);
 
87
extern int xc_interface_close(int fd);
 
88
extern int xc_gnttab_close(int fd);
 
89
 
 
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 */
 
95
};
 
96
 
 
97
DECLARE_WAIT_QUEUE_HEAD(event_queue);
 
98
 
 
99
int alloc_fd(enum fd_type type)
 
100
{
 
101
    int i;
 
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);
 
107
            return i;
 
108
        }
 
109
    }
 
110
    pthread_mutex_unlock(&fd_lock);
 
111
    printk("Too many opened files\n");
 
112
    do_exit();
 
113
}
 
114
 
 
115
void close_all_files(void)
 
116
{
 
117
    int i;
 
118
    pthread_mutex_lock(&fd_lock);
 
119
    for (i=NOFILE - 1; i > 0; i--)
 
120
        if (files[i].type != FTYPE_NONE)
 
121
            close(i);
 
122
    pthread_mutex_unlock(&fd_lock);
 
123
}
 
124
 
 
125
int dup2(int oldfd, int newfd)
 
126
{
 
127
    pthread_mutex_lock(&fd_lock);
 
128
    if (files[newfd].type != FTYPE_NONE)
 
129
        close(newfd);
 
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);
 
133
    return 0;
 
134
}
 
135
 
 
136
pid_t getpid(void)
 
137
{
 
138
    return 1;
 
139
}
 
140
 
 
141
pid_t getppid(void)
 
142
{
 
143
    return 1;
 
144
}
 
145
 
 
146
pid_t setsid(void)
 
147
{
 
148
    return 1;
 
149
}
 
150
 
 
151
char *getcwd(char *buf, size_t size)
 
152
{
 
153
    snprintf(buf, size, "/");
 
154
    return buf;
 
155
}
 
156
 
 
157
#define LOG_PATH "/var/log/"
 
158
 
 
159
int mkdir(const char *pathname, mode_t mode)
 
160
{
 
161
    int ret;
 
162
    ret = fs_create(fs_import, (char *) pathname, 1, mode);
 
163
    if (ret < 0) {
 
164
        errno = EIO;
 
165
        return -1;
 
166
    }
 
167
    return 0;
 
168
}
 
169
 
 
170
int posix_openpt(int flags)
 
171
{
 
172
    struct consfront_dev *dev;
 
173
 
 
174
    /* Ignore flags */
 
175
 
 
176
    dev = init_consfront(NULL);
 
177
    dev->fd = alloc_fd(FTYPE_CONSOLE);
 
178
    files[dev->fd].cons.dev = dev;
 
179
 
 
180
    printk("fd(%d) = posix_openpt\n", dev->fd);
 
181
    return(dev->fd);
 
182
}
 
183
 
 
184
int open(const char *pathname, int flags, ...)
 
185
{
 
186
    int fs_fd, fd;
 
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);
 
191
        return fd;
 
192
    }
 
193
    if (!strncmp(pathname, "/dev/mem", strlen("/dev/mem"))) {
 
194
        fd = alloc_fd(FTYPE_MEM);
 
195
        printk("open(/dev/mem) -> %d\n", fd);
 
196
        return fd;
 
197
    }
 
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) {
 
202
        case 0:
 
203
            fs_fd = fs_open(fs_import, (void *) pathname);
 
204
            break;
 
205
        case O_CREAT|O_TRUNC:
 
206
        {
 
207
            va_list ap;
 
208
            mode_t mode;
 
209
            va_start(ap, flags);
 
210
            mode = va_arg(ap, mode_t);
 
211
            va_end(ap);
 
212
            fs_fd = fs_create(fs_import, (void *) pathname, 0, mode);
 
213
            break;
 
214
        }
 
215
        default:
 
216
            printk(" unsupported flags\n");
 
217
            do_exit();
 
218
    }
 
219
    if (fs_fd < 0) {
 
220
        errno = EIO;
 
221
        return -1;
 
222
    }
 
223
    fd = alloc_fd(FTYPE_FILE);
 
224
    printk("-> %d\n", fd);
 
225
    files[fd].file.fd = fs_fd;
 
226
    files[fd].file.offset = 0;
 
227
    return fd;
 
228
}
 
229
 
 
230
int isatty(int fd)
 
231
{
 
232
    return files[fd].type == FTYPE_CONSOLE;
 
233
}
 
234
 
 
235
int read(int fd, void *buf, size_t nbytes)
 
236
{
 
237
    switch (files[fd].type) {
 
238
        case FTYPE_CONSOLE: {
 
239
            int ret;
 
240
            DEFINE_WAIT(w);
 
241
            while(1) {
 
242
                add_waiter(w, console_queue);
 
243
                ret = xencons_ring_recv(files[fd].cons.dev, buf, nbytes);
 
244
                if (ret)
 
245
                    break;
 
246
                schedule();
 
247
            }
 
248
            remove_waiter(w);
 
249
            return ret;
 
250
        }
 
251
        case FTYPE_FILE: {
 
252
            ssize_t ret;
 
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);
 
256
            if (ret > 0) {
 
257
                files[fd].file.offset += ret;
 
258
                return ret;
 
259
            } else if (ret < 0) {
 
260
                errno = EIO;
 
261
                return -1;
 
262
            }
 
263
            return 0;
 
264
        }
 
265
#ifdef HAVE_LWIP
 
266
        case FTYPE_SOCKET:
 
267
            return lwip_read(files[fd].socket.fd, buf, nbytes);
 
268
#endif
 
269
        case FTYPE_TAP: {
 
270
            ssize_t ret;
 
271
            ret = netfront_receive(files[fd].tap.dev, buf, nbytes);
 
272
            if (ret <= 0) {
 
273
                errno = EAGAIN;
 
274
                return -1;
 
275
            }
 
276
            return ret;
 
277
        }
 
278
        case FTYPE_KBD: {
 
279
            int ret, n;
 
280
            n = nbytes / sizeof(union xenkbd_in_event);
 
281
            ret = kbdfront_receive(files[fd].kbd.dev, buf, n);
 
282
            if (ret <= 0) {
 
283
                errno = EAGAIN;
 
284
                return -1;
 
285
            }
 
286
            return ret * sizeof(union xenkbd_in_event);
 
287
        }
 
288
        case FTYPE_FB: {
 
289
            int ret, n;
 
290
            n = nbytes / sizeof(union xenfb_in_event);
 
291
            ret = fbfront_receive(files[fd].fb.dev, buf, n);
 
292
            if (ret <= 0) {
 
293
                errno = EAGAIN;
 
294
                return -1;
 
295
            }
 
296
            return ret * sizeof(union xenfb_in_event);
 
297
        }
 
298
        default:
 
299
            break;
 
300
    }
 
301
    printk("read(%d): Bad descriptor\n", fd);
 
302
    errno = EBADF;
 
303
    return -1;
 
304
}
 
305
 
 
306
int write(int fd, const void *buf, size_t nbytes)
 
307
{
 
308
    switch (files[fd].type) {
 
309
        case FTYPE_CONSOLE:
 
310
            console_print(files[fd].cons.dev, (char *)buf, nbytes);
 
311
            return nbytes;
 
312
        case FTYPE_FILE: {
 
313
            ssize_t ret;
 
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);
 
317
            if (ret > 0) {
 
318
                files[fd].file.offset += ret;
 
319
                return ret;
 
320
            } else if (ret < 0) {
 
321
                errno = EIO;
 
322
                return -1;
 
323
            }
 
324
            return 0;
 
325
        }
 
326
#ifdef HAVE_LWIP
 
327
        case FTYPE_SOCKET:
 
328
            return lwip_write(files[fd].socket.fd, (void*) buf, nbytes);
 
329
#endif
 
330
        case FTYPE_TAP:
 
331
            netfront_xmit(files[fd].tap.dev, (void*) buf, nbytes);
 
332
            return nbytes;
 
333
        default:
 
334
            break;
 
335
    }
 
336
    printk("write(%d): Bad descriptor\n", fd);
 
337
    errno = EBADF;
 
338
    return -1;
 
339
}
 
340
 
 
341
off_t lseek(int fd, off_t offset, int whence)
 
342
{
 
343
    if (files[fd].type != FTYPE_FILE) {
 
344
        errno = ESPIPE;
 
345
        return (off_t) -1;
 
346
    }
 
347
    switch (whence) {
 
348
        case SEEK_SET:
 
349
            files[fd].file.offset = offset;
 
350
            break;
 
351
        case SEEK_CUR:
 
352
            files[fd].file.offset += offset;
 
353
            break;
 
354
        case SEEK_END: {
 
355
            struct stat st;
 
356
            int ret;
 
357
            ret = fstat(fd, &st);
 
358
            if (ret)
 
359
                return -1;
 
360
            files[fd].file.offset = st.st_size + offset;
 
361
            break;
 
362
        }
 
363
        default:
 
364
            errno = EINVAL;
 
365
            return -1;
 
366
    }
 
367
    return files[fd].file.offset;
 
368
}
 
369
 
 
370
int fsync(int fd) {
 
371
    switch (files[fd].type) {
 
372
        case FTYPE_FILE: {
 
373
            int ret;
 
374
            ret = fs_sync(fs_import, files[fd].file.fd);
 
375
            if (ret < 0) {
 
376
                errno = EIO;
 
377
                return -1;
 
378
            }
 
379
            return 0;
 
380
        }
 
381
        default:
 
382
            break;
 
383
    }
 
384
    printk("fsync(%d): Bad descriptor\n", fd);
 
385
    errno = EBADF;
 
386
    return -1;
 
387
}
 
388
 
 
389
int close(int fd)
 
390
{
 
391
    printk("close(%d)\n", fd);
 
392
    switch (files[fd].type) {
 
393
        default:
 
394
            files[fd].type = FTYPE_NONE;
 
395
            return 0;
 
396
        case FTYPE_FILE: {
 
397
            int ret = fs_close(fs_import, files[fd].file.fd);
 
398
            files[fd].type = FTYPE_NONE;
 
399
            if (ret < 0) {
 
400
                errno = EIO;
 
401
                return -1;
 
402
            }
 
403
            return 0;
 
404
        }
 
405
        case FTYPE_XENBUS:
 
406
            xs_daemon_close((void*)(intptr_t) fd);
 
407
            return 0;
 
408
#ifdef HAVE_LWIP
 
409
        case FTYPE_SOCKET: {
 
410
            int res = lwip_close(files[fd].socket.fd);
 
411
            files[fd].type = FTYPE_NONE;
 
412
            return res;
 
413
        }
 
414
#endif
 
415
        case FTYPE_XC:
 
416
            xc_interface_close(fd);
 
417
            return 0;
 
418
        case FTYPE_EVTCHN:
 
419
            xc_evtchn_close(fd);
 
420
            return 0;
 
421
        case FTYPE_GNTMAP:
 
422
            xc_gnttab_close(fd);
 
423
            return 0;
 
424
        case FTYPE_TAP:
 
425
            shutdown_netfront(files[fd].tap.dev);
 
426
            files[fd].type = FTYPE_NONE;
 
427
            return 0;
 
428
        case FTYPE_BLK:
 
429
            shutdown_blkfront(files[fd].blk.dev);
 
430
            files[fd].type = FTYPE_NONE;
 
431
            return 0;
 
432
        case FTYPE_KBD:
 
433
            shutdown_kbdfront(files[fd].kbd.dev);
 
434
            files[fd].type = FTYPE_NONE;
 
435
            return 0;
 
436
        case FTYPE_FB:
 
437
            shutdown_fbfront(files[fd].fb.dev);
 
438
            files[fd].type = FTYPE_NONE;
 
439
            return 0;
 
440
        case FTYPE_CONSOLE:
 
441
            fini_console(files[fd].cons.dev);
 
442
            files[fd].type = FTYPE_NONE;
 
443
            return 0;
 
444
        case FTYPE_NONE:
 
445
            break;
 
446
    }
 
447
    printk("close(%d): Bad descriptor\n", fd);
 
448
    errno = EBADF;
 
449
    return -1;
 
450
}
 
451
 
 
452
static void init_stat(struct stat *buf)
 
453
{
 
454
    memset(buf, 0, sizeof(*buf));
 
455
    buf->st_dev = 0;
 
456
    buf->st_ino = 0;
 
457
    buf->st_nlink = 1;
 
458
    buf->st_rdev = 0;
 
459
    buf->st_blksize = 4096;
 
460
    buf->st_blocks = 0;
 
461
}
 
462
 
 
463
static void stat_from_fs(struct stat *buf, struct fsif_stat_response *stat)
 
464
{
 
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;
 
472
}
 
473
 
 
474
int stat(const char *path, struct stat *buf)
 
475
{
 
476
    struct fsif_stat_response stat;
 
477
    int ret;
 
478
    int fs_fd;
 
479
    printk("stat(%s)\n", path);
 
480
    fs_fd = fs_open(fs_import, (char*) path);
 
481
    if (fs_fd < 0) {
 
482
        errno = EIO;
 
483
        ret = -1;
 
484
        goto out;
 
485
    }
 
486
    ret = fs_stat(fs_import, fs_fd, &stat);
 
487
    if (ret < 0) {
 
488
        errno = EIO;
 
489
        ret = -1;
 
490
        goto outfd;
 
491
    }
 
492
    init_stat(buf);
 
493
    stat_from_fs(buf, &stat);
 
494
    ret = 0;
 
495
 
 
496
outfd:
 
497
    fs_close(fs_import, fs_fd);
 
498
out:
 
499
    return ret;
 
500
}
 
501
 
 
502
int fstat(int fd, struct stat *buf)
 
503
{
 
504
    init_stat(buf);
 
505
    switch (files[fd].type) {
 
506
        case FTYPE_CONSOLE:
 
507
        case FTYPE_SOCKET: {
 
508
            buf->st_mode = (files[fd].type == FTYPE_CONSOLE?S_IFCHR:S_IFSOCK) | S_IRUSR|S_IWUSR;
 
509
            buf->st_uid = 0;
 
510
            buf->st_gid = 0;
 
511
            buf->st_size = 0;
 
512
            buf->st_atime = 
 
513
            buf->st_mtime = 
 
514
            buf->st_ctime = time(NULL);
 
515
            return 0;
 
516
        }
 
517
        case FTYPE_FILE: {
 
518
            struct fsif_stat_response stat;
 
519
            int ret;
 
520
            ret = fs_stat(fs_import, files[fd].file.fd, &stat);
 
521
            if (ret < 0) {
 
522
                errno = EIO;
 
523
                return -1;
 
524
            }
 
525
            /* The protocol is a bit evasive about this value */
 
526
            stat_from_fs(buf, &stat);
 
527
            return 0;
 
528
        }
 
529
        default:
 
530
            break;
 
531
    }
 
532
 
 
533
    printk("statf(%d): Bad descriptor\n", fd);
 
534
    errno = EBADF;
 
535
    return -1;
 
536
}
 
537
 
 
538
int ftruncate(int fd, off_t length)
 
539
{
 
540
    switch (files[fd].type) {
 
541
        case FTYPE_FILE: {
 
542
            int ret;
 
543
            ret = fs_truncate(fs_import, files[fd].file.fd, length);
 
544
            if (ret < 0) {
 
545
                errno = EIO;
 
546
                return -1;
 
547
            }
 
548
            return 0;
 
549
        }
 
550
        default:
 
551
            break;
 
552
    }
 
553
 
 
554
    printk("ftruncate(%d): Bad descriptor\n", fd);
 
555
    errno = EBADF;
 
556
    return -1;
 
557
}
 
558
 
 
559
int remove(const char *pathname)
 
560
{
 
561
    int ret;
 
562
    printk("remove(%s)", pathname);
 
563
    ret = fs_remove(fs_import, (char*) pathname);
 
564
    if (ret < 0) {
 
565
        errno = EIO;
 
566
        return -1;
 
567
    }
 
568
    return 0;
 
569
}
 
570
 
 
571
int unlink(const char *pathname)
 
572
{
 
573
    return remove(pathname);
 
574
}
 
575
 
 
576
int rmdir(const char *pathname)
 
577
{
 
578
    return remove(pathname);
 
579
}
 
580
 
 
581
int fcntl(int fd, int cmd, ...)
 
582
{
 
583
    long arg;
 
584
    va_list ap;
 
585
    va_start(ap, cmd);
 
586
    arg = va_arg(ap, long);
 
587
    va_end(ap);
 
588
 
 
589
    switch (cmd) {
 
590
#ifdef HAVE_LWIP
 
591
        case F_SETFL:
 
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);
 
596
            }
 
597
            /* Fallthrough */
 
598
#endif
 
599
        default:
 
600
            printk("fcntl(%d, %d, %lx/%lo)\n", fd, cmd, arg, arg);
 
601
            errno = ENOSYS;
 
602
            return -1;
 
603
    }
 
604
}
 
605
 
 
606
DIR *opendir(const char *name)
 
607
{
 
608
    DIR *ret;
 
609
    ret = malloc(sizeof(*ret));
 
610
    ret->name = strdup(name);
 
611
    ret->offset = 0;
 
612
    ret->entries = NULL;
 
613
    ret->curentry = -1;
 
614
    ret->nbentries = 0;
 
615
    ret->has_more = 1;
 
616
    return ret;
 
617
}
 
618
 
 
619
struct dirent *readdir(DIR *dir)
 
620
{
 
621
    if (dir->curentry >= 0) {
 
622
        free(dir->entries[dir->curentry]);
 
623
        dir->entries[dir->curentry] = NULL;
 
624
    }
 
625
    dir->curentry++;
 
626
    if (dir->curentry >= dir->nbentries) {
 
627
        dir->offset += dir->nbentries;
 
628
        free(dir->entries);
 
629
        dir->curentry = -1;
 
630
        dir->nbentries = 0;
 
631
        if (!dir->has_more)
 
632
            return NULL;
 
633
        dir->entries = fs_list(fs_import, dir->name, dir->offset, &dir->nbentries, &dir->has_more);
 
634
        if (!dir->entries || !dir->nbentries)
 
635
            return NULL;
 
636
        dir->curentry = 0;
 
637
    }
 
638
    dir->dirent.d_name = dir->entries[dir->curentry];
 
639
    return &dir->dirent;
 
640
 
641
int closedir(DIR *dir)
 
642
{
 
643
    int i;
 
644
    for (i=0; i<dir->nbentries; i++)
 
645
        free(dir->entries[i]);
 
646
    free(dir->entries);
 
647
    free(dir->name);
 
648
    free(dir);
 
649
    return 0;
 
650
}
 
651
 
 
652
/* We assume that only the main thread calls select(). */
 
653
 
 
654
static const char file_types[] = {
 
655
    [FTYPE_NONE]        = 'N',
 
656
    [FTYPE_CONSOLE]     = 'C',
 
657
    [FTYPE_FILE]        = 'F',
 
658
    [FTYPE_XENBUS]      = 'S',
 
659
    [FTYPE_XC]          = 'X',
 
660
    [FTYPE_EVTCHN]      = 'E',
 
661
    [FTYPE_SOCKET]      = 's',
 
662
    [FTYPE_TAP]         = 'T',
 
663
    [FTYPE_BLK]         = 'B',
 
664
    [FTYPE_KBD]         = 'K',
 
665
    [FTYPE_FB]          = 'G',
 
666
};
 
667
#ifdef LIBC_DEBUG
 
668
static void dump_set(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
 
669
{
 
670
    int i, comma;
 
671
#define printfds(set) do {\
 
672
    comma = 0; \
 
673
    for (i = 0; i < nfds; i++) { \
 
674
        if (FD_ISSET(i, set)) { \
 
675
            if (comma) \
 
676
                printk(", "); \
 
677
            printk("%d(%c)", i, file_types[files[i].type]); \
 
678
            comma = 1; \
 
679
        } \
 
680
    } \
 
681
} while (0)
 
682
 
 
683
    printk("[");
 
684
    if (readfds)
 
685
        printfds(readfds);
 
686
    printk("], [");
 
687
    if (writefds)
 
688
        printfds(writefds);
 
689
    printk("], [");
 
690
    if (exceptfds)
 
691
        printfds(exceptfds);
 
692
    printk("], ");
 
693
    if (timeout)
 
694
        printk("{ %ld, %ld }", timeout->tv_sec, timeout->tv_usec);
 
695
}
 
696
#else
 
697
#define dump_set(nfds, readfds, writefds, exceptfds, timeout)
 
698
#endif
 
699
 
 
700
/* Just poll without blocking */
 
701
static int select_poll(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds)
 
702
{
 
703
    int i, n = 0;
 
704
#ifdef HAVE_LWIP
 
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};
 
708
#endif
 
709
 
 
710
#ifdef LIBC_VERBOSE
 
711
    static int nb;
 
712
    static int nbread[NOFILE], nbwrite[NOFILE], nbexcept[NOFILE];
 
713
    static s_time_t lastshown;
 
714
 
 
715
    nb++;
 
716
#endif
 
717
 
 
718
#ifdef HAVE_LWIP
 
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);
 
727
                sock_nfds = i+1;
 
728
            }
 
729
            if (FD_ISSET(i, writefds)) {
 
730
                FD_SET(files[i].socket.fd, &sock_writefds);
 
731
                sock_nfds = i+1;
 
732
            }
 
733
            if (FD_ISSET(i, exceptfds)) {
 
734
                FD_SET(files[i].socket.fd, &sock_exceptfds);
 
735
                sock_nfds = i+1;
 
736
            }
 
737
        }
 
738
    }
 
739
    if (sock_nfds > 0) {
 
740
        DEBUG("lwip_select(");
 
741
        dump_set(nfds, &sock_readfds, &sock_writefds, &sock_exceptfds, &timeout);
 
742
        DEBUG("); -> ");
 
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);
 
745
        DEBUG("\n");
 
746
    }
 
747
#endif
 
748
 
 
749
    /* Then see others as well. */
 
750
    for (i = 0; i < nfds; i++) {
 
751
        switch(files[i].type) {
 
752
        default:
 
753
            if (FD_ISSET(i, readfds) || FD_ISSET(i, writefds) || FD_ISSET(i, exceptfds))
 
754
                printk("bogus fd %d in select\n", i);
 
755
            /* Fallthrough.  */
 
756
        case FTYPE_FILE:
 
757
            FD_CLR(i, readfds);
 
758
            FD_CLR(i, writefds);
 
759
            FD_CLR(i, exceptfds);
 
760
            break;
 
761
        case FTYPE_CONSOLE:
 
762
            if (FD_ISSET(i, readfds)) {
 
763
                if (xencons_ring_avail(files[i].cons.dev))
 
764
                    n++;
 
765
                else
 
766
                    FD_CLR(i, readfds);
 
767
            }
 
768
            if (FD_ISSET(i, writefds))
 
769
                n++;
 
770
            FD_CLR(i, exceptfds);
 
771
            break;
 
772
        case FTYPE_XENBUS:
 
773
            if (FD_ISSET(i, readfds)) {
 
774
                if (files[i].xenbus.events)
 
775
                    n++;
 
776
                else
 
777
                    FD_CLR(i, readfds);
 
778
            }
 
779
            FD_CLR(i, writefds);
 
780
            FD_CLR(i, exceptfds);
 
781
            break;
 
782
        case FTYPE_EVTCHN:
 
783
        case FTYPE_TAP:
 
784
        case FTYPE_BLK:
 
785
        case FTYPE_KBD:
 
786
        case FTYPE_FB:
 
787
            if (FD_ISSET(i, readfds)) {
 
788
                if (files[i].read)
 
789
                    n++;
 
790
                else
 
791
                    FD_CLR(i, readfds);
 
792
            }
 
793
            FD_CLR(i, writefds);
 
794
            FD_CLR(i, exceptfds);
 
795
            break;
 
796
#ifdef HAVE_LWIP
 
797
        case FTYPE_SOCKET:
 
798
            if (FD_ISSET(i, readfds)) {
 
799
                /* Optimize no-network-packet case.  */
 
800
                if (sock_n && FD_ISSET(files[i].socket.fd, &sock_readfds))
 
801
                    n++;
 
802
                else
 
803
                    FD_CLR(i, readfds);
 
804
            }
 
805
            if (FD_ISSET(i, writefds)) {
 
806
                if (sock_n && FD_ISSET(files[i].socket.fd, &sock_writefds))
 
807
                    n++;
 
808
                else
 
809
                    FD_CLR(i, writefds);
 
810
            }
 
811
            if (FD_ISSET(i, exceptfds)) {
 
812
                if (sock_n && FD_ISSET(files[i].socket.fd, &sock_exceptfds))
 
813
                    n++;
 
814
                else
 
815
                    FD_CLR(i, exceptfds);
 
816
            }
 
817
            break;
 
818
#endif
 
819
        }
 
820
#ifdef LIBC_VERBOSE
 
821
        if (FD_ISSET(i, readfds))
 
822
            nbread[i]++;
 
823
        if (FD_ISSET(i, writefds))
 
824
            nbwrite[i]++;
 
825
        if (FD_ISSET(i, exceptfds))
 
826
            nbexcept[i]++;
 
827
#endif
 
828
    }
 
829
#ifdef LIBC_VERBOSE
 
830
    if (NOW() > lastshown + 1000000000ull) {
 
831
        lastshown = NOW();
 
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]);
 
837
            if (nbread[i])
 
838
                printk(" %dR", nbread[i]);
 
839
            if (nbwrite[i])
 
840
                printk(" %dW", nbwrite[i]);
 
841
            if (nbexcept[i])
 
842
                printk(" %dE", nbexcept[i]);
 
843
        }
 
844
        printk("\n");
 
845
        memset(nbread, 0, sizeof(nbread));
 
846
        memset(nbwrite, 0, sizeof(nbwrite));
 
847
        memset(nbexcept, 0, sizeof(nbexcept));
 
848
        nb = 0;
 
849
    }
 
850
#endif
 
851
    return n;
 
852
}
 
853
 
 
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)
 
861
{
 
862
    int n, ret;
 
863
    fd_set myread, mywrite, myexcept;
 
864
    struct thread *thread = get_current();
 
865
    s_time_t start = NOW(), stop;
 
866
    DEFINE_WAIT(w1);
 
867
    DEFINE_WAIT(w2);
 
868
    DEFINE_WAIT(w3);
 
869
    DEFINE_WAIT(w4);
 
870
    DEFINE_WAIT(w5);
 
871
    DEFINE_WAIT(w6);
 
872
 
 
873
    assert(thread == main_thread);
 
874
 
 
875
    DEBUG("select(%d, ", nfds);
 
876
    dump_set(nfds, readfds, writefds, exceptfds, timeout);
 
877
    DEBUG(");\n");
 
878
 
 
879
    if (timeout)
 
880
        stop = start + SECONDS(timeout->tv_sec) + timeout->tv_usec * 1000;
 
881
    else
 
882
        /* just make gcc happy */
 
883
        stop = start;
 
884
 
 
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
 
887
     * schedule() */
 
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);
 
894
 
 
895
    if (readfds)
 
896
        myread = *readfds;
 
897
    else
 
898
        FD_ZERO(&myread);
 
899
    if (writefds)
 
900
        mywrite = *writefds;
 
901
    else
 
902
        FD_ZERO(&mywrite);
 
903
    if (exceptfds)
 
904
        myexcept = *exceptfds;
 
905
    else
 
906
        FD_ZERO(&myexcept);
 
907
 
 
908
    DEBUG("polling ");
 
909
    dump_set(nfds, &myread, &mywrite, &myexcept, timeout);
 
910
    DEBUG("\n");
 
911
    n = select_poll(nfds, &myread, &mywrite, &myexcept);
 
912
 
 
913
    if (n) {
 
914
        dump_set(nfds, readfds, writefds, exceptfds, timeout);
 
915
        if (readfds)
 
916
            *readfds = myread;
 
917
        if (writefds)
 
918
            *writefds = mywrite;
 
919
        if (exceptfds)
 
920
            *exceptfds = myexcept;
 
921
        DEBUG(" -> ");
 
922
        dump_set(nfds, readfds, writefds, exceptfds, timeout);
 
923
        DEBUG("\n");
 
924
        wake(thread);
 
925
        ret = n;
 
926
        goto out;
 
927
    }
 
928
    if (timeout && NOW() >= stop) {
 
929
        if (readfds)
 
930
            FD_ZERO(readfds);
 
931
        if (writefds)
 
932
            FD_ZERO(writefds);
 
933
        if (exceptfds)
 
934
            FD_ZERO(exceptfds);
 
935
        timeout->tv_sec = 0;
 
936
        timeout->tv_usec = 0;
 
937
        wake(thread);
 
938
        ret = 0;
 
939
        goto out;
 
940
    }
 
941
 
 
942
    if (timeout)
 
943
        thread->wakeup_time = stop;
 
944
    schedule();
 
945
 
 
946
    if (readfds)
 
947
        myread = *readfds;
 
948
    else
 
949
        FD_ZERO(&myread);
 
950
    if (writefds)
 
951
        mywrite = *writefds;
 
952
    else
 
953
        FD_ZERO(&mywrite);
 
954
    if (exceptfds)
 
955
        myexcept = *exceptfds;
 
956
    else
 
957
        FD_ZERO(&myexcept);
 
958
 
 
959
    n = select_poll(nfds, &myread, &mywrite, &myexcept);
 
960
 
 
961
    if (n) {
 
962
        if (readfds)
 
963
            *readfds = myread;
 
964
        if (writefds)
 
965
            *writefds = mywrite;
 
966
        if (exceptfds)
 
967
            *exceptfds = myexcept;
 
968
        ret = n;
 
969
        goto out;
 
970
    }
 
971
    errno = EINTR;
 
972
    ret = -1;
 
973
 
 
974
out:
 
975
    remove_waiter(w1);
 
976
    remove_waiter(w2);
 
977
    remove_waiter(w3);
 
978
    remove_waiter(w4);
 
979
    remove_waiter(w5);
 
980
    remove_waiter(w6);
 
981
    return ret;
 
982
}
 
983
 
 
984
#ifdef HAVE_LWIP
 
985
int socket(int domain, int type, int protocol)
 
986
{
 
987
    int fd, res;
 
988
    fd = lwip_socket(domain, type, protocol);
 
989
    if (fd < 0)
 
990
        return -1;
 
991
    res = alloc_fd(FTYPE_SOCKET);
 
992
    printk("socket -> %d\n", res);
 
993
    files[res].socket.fd = fd;
 
994
    return res;
 
995
}
 
996
 
 
997
int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
 
998
{
 
999
    int fd, res;
 
1000
    if (files[s].type != FTYPE_SOCKET) {
 
1001
        printk("accept(%d): Bad descriptor\n", s);
 
1002
        errno = EBADF;
 
1003
        return -1;
 
1004
    }
 
1005
    fd = lwip_accept(files[s].socket.fd, addr, addrlen);
 
1006
    if (fd < 0)
 
1007
        return -1;
 
1008
    res = alloc_fd(FTYPE_SOCKET);
 
1009
    files[res].socket.fd = fd;
 
1010
    printk("accepted on %d -> %d\n", s, res);
 
1011
    return res;
 
1012
}
 
1013
 
 
1014
#define LWIP_STUB(ret, name, proto, args) \
 
1015
ret name proto \
 
1016
{ \
 
1017
    if (files[s].type != FTYPE_SOCKET) { \
 
1018
        printk(#name "(%d): Bad descriptor\n", s); \
 
1019
        errno = EBADF; \
 
1020
        return -1; \
 
1021
    } \
 
1022
    s = files[s].socket.fd; \
 
1023
    return lwip_##name args; \
 
1024
}
 
1025
 
 
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))
 
1036
#endif
 
1037
 
 
1038
static char *syslog_ident;
 
1039
void openlog(const char *ident, int option, int facility)
 
1040
{
 
1041
    if (syslog_ident)
 
1042
        free(syslog_ident);
 
1043
    syslog_ident = strdup(ident);
 
1044
}
 
1045
 
 
1046
void vsyslog(int priority, const char *format, va_list ap)
 
1047
{
 
1048
    printk("%s: ", syslog_ident);
 
1049
    print(0, format, ap);
 
1050
}
 
1051
 
 
1052
void syslog(int priority, const char *format, ...)
 
1053
{
 
1054
    va_list ap;
 
1055
    va_start(ap, format);
 
1056
    vsyslog(priority, format, ap);
 
1057
    va_end(ap);
 
1058
}
 
1059
 
 
1060
void closelog(void)
 
1061
{
 
1062
    free(syslog_ident);
 
1063
    syslog_ident = NULL;
 
1064
}
 
1065
 
 
1066
void vwarn(const char *format, va_list ap)
 
1067
{
 
1068
    int the_errno = errno;
 
1069
    printk("stubdom: ");
 
1070
    if (format) {
 
1071
        print(0, format, ap);
 
1072
        printk(", ");
 
1073
    }
 
1074
    printk("%s", strerror(the_errno));
 
1075
}
 
1076
 
 
1077
void warn(const char *format, ...)
 
1078
{
 
1079
    va_list ap;
 
1080
    va_start(ap, format);
 
1081
    vwarn(format, ap);
 
1082
    va_end(ap);
 
1083
}
 
1084
 
 
1085
void verr(int eval, const char *format, va_list ap)
 
1086
{
 
1087
    vwarn(format, ap);
 
1088
    exit(eval);
 
1089
}
 
1090
 
 
1091
void err(int eval, const char *format, ...)
 
1092
{
 
1093
    va_list ap;
 
1094
    va_start(ap, format);
 
1095
    verr(eval, format, ap);
 
1096
    va_end(ap);
 
1097
}
 
1098
 
 
1099
void vwarnx(const char *format, va_list ap)
 
1100
{
 
1101
    printk("stubdom: ");
 
1102
    if (format)
 
1103
        print(0, format, ap);
 
1104
}
 
1105
 
 
1106
void warnx(const char *format, ...)
 
1107
{
 
1108
    va_list ap;
 
1109
    va_start(ap, format);
 
1110
    vwarnx(format, ap);
 
1111
    va_end(ap);
 
1112
}
 
1113
 
 
1114
void verrx(int eval, const char *format, va_list ap)
 
1115
{
 
1116
    vwarnx(format, ap);
 
1117
    exit(eval);
 
1118
}
 
1119
 
 
1120
void errx(int eval, const char *format, ...)
 
1121
{
 
1122
    va_list ap;
 
1123
    va_start(ap, format);
 
1124
    verrx(eval, format, ap);
 
1125
    va_end(ap);
 
1126
}
 
1127
 
 
1128
int nanosleep(const struct timespec *req, struct timespec *rem)
 
1129
{
 
1130
    s_time_t start = NOW();
 
1131
    s_time_t stop = start + SECONDS(req->tv_sec) + req->tv_nsec;
 
1132
    s_time_t stopped;
 
1133
    struct thread *thread = get_current();
 
1134
 
 
1135
    thread->wakeup_time = stop;
 
1136
    clear_runnable(thread);
 
1137
    schedule();
 
1138
    stopped = NOW();
 
1139
 
 
1140
    if (rem)
 
1141
    {
 
1142
        s_time_t remaining = stop - stopped;
 
1143
        if (remaining > 0)
 
1144
        {
 
1145
            rem->tv_nsec = remaining % 1000000000ULL;
 
1146
            rem->tv_sec  = remaining / 1000000000ULL;
 
1147
        } else memset(rem, 0, sizeof(*rem));
 
1148
    }
 
1149
 
 
1150
    return 0;
 
1151
}
 
1152
 
 
1153
int usleep(useconds_t usec)
 
1154
{
 
1155
    /* "usec shall be less than one million."  */
 
1156
    struct timespec req;
 
1157
    req.tv_nsec = usec * 1000;
 
1158
    req.tv_sec = 0;
 
1159
 
 
1160
    if (nanosleep(&req, NULL))
 
1161
        return -1;
 
1162
 
 
1163
    return 0;
 
1164
}
 
1165
 
 
1166
unsigned int sleep(unsigned int seconds)
 
1167
{
 
1168
    struct timespec req, rem;
 
1169
    req.tv_sec = seconds;
 
1170
    req.tv_nsec = 0;
 
1171
 
 
1172
    if (nanosleep(&req, &rem))
 
1173
        return -1;
 
1174
 
 
1175
    if (rem.tv_nsec > 0)
 
1176
        rem.tv_sec++;
 
1177
 
 
1178
    return rem.tv_sec;
 
1179
}
 
1180
 
 
1181
int clock_gettime(clockid_t clk_id, struct timespec *tp)
 
1182
{
 
1183
    switch (clk_id) {
 
1184
        case CLOCK_MONOTONIC:
 
1185
        {
 
1186
            struct timeval tv;
 
1187
 
 
1188
            gettimeofday(&tv, NULL);
 
1189
 
 
1190
            tp->tv_sec = tv.tv_sec;
 
1191
            tp->tv_nsec = tv.tv_usec * 1000;
 
1192
 
 
1193
            break;
 
1194
        }
 
1195
        case CLOCK_REALTIME:
 
1196
        {
 
1197
            uint64_t nsec = monotonic_clock();
 
1198
 
 
1199
            tp->tv_sec = nsec / 1000000000ULL;
 
1200
            tp->tv_nsec = nsec % 1000000000ULL;
 
1201
 
 
1202
            break;
 
1203
        }
 
1204
        default:
 
1205
            print_unsupported("clock_gettime(%d)", clk_id);
 
1206
            errno = EINVAL;
 
1207
            return -1;
 
1208
    }
 
1209
 
 
1210
    return 0;
 
1211
}
 
1212
 
 
1213
uid_t getuid(void)
 
1214
{
 
1215
        return 0;
 
1216
}
 
1217
 
 
1218
uid_t geteuid(void)
 
1219
{
 
1220
        return 0;
 
1221
}
 
1222
 
 
1223
gid_t getgid(void)
 
1224
{
 
1225
        return 0;
 
1226
}
 
1227
 
 
1228
gid_t getegid(void)
 
1229
{
 
1230
        return 0;
 
1231
}
 
1232
 
 
1233
int gethostname(char *name, size_t namelen)
 
1234
{
 
1235
        strncpy(name, "mini-os", namelen);
 
1236
        return 0;
 
1237
}
 
1238
 
 
1239
size_t getpagesize(void)
 
1240
{
 
1241
    return PAGE_SIZE;
 
1242
}
 
1243
 
 
1244
void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset)
 
1245
{
 
1246
    unsigned long n = (length + PAGE_SIZE - 1) / PAGE_SIZE;
 
1247
 
 
1248
    ASSERT(!start);
 
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));
 
1252
 
 
1253
    if (fd == -1)
 
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);
 
1261
    } else ASSERT(0);
 
1262
}
 
1263
 
 
1264
int munmap(void *start, size_t length)
 
1265
{
 
1266
    int total = length / PAGE_SIZE;
 
1267
    int ret;
 
1268
 
 
1269
    ret = unmap_frames((unsigned long)start, (unsigned long)total);
 
1270
    if (ret) {
 
1271
        errno = ret;
 
1272
        return -1;
 
1273
    }
 
1274
    return 0;
 
1275
}
 
1276
 
 
1277
void sparse(unsigned long data, size_t size)
 
1278
{
 
1279
    unsigned long newdata;
 
1280
    xen_pfn_t *mfns;
 
1281
    int i, n;
 
1282
 
 
1283
    newdata = (data + PAGE_SIZE - 1) & PAGE_MASK;
 
1284
    if (newdata - data > size)
 
1285
        return;
 
1286
    size -= newdata - data;
 
1287
    data = newdata;
 
1288
    n = size / PAGE_SIZE;
 
1289
    size = n * PAGE_SIZE;
 
1290
 
 
1291
    mfns = malloc(n * sizeof(*mfns));
 
1292
    for (i = 0; i < n; i++) {
 
1293
#ifdef LIBC_DEBUG
 
1294
        int j;
 
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);
 
1298
                exit(1);
 
1299
            }
 
1300
#endif
 
1301
        mfns[i] = virtual_to_mfn(data + i * PAGE_SIZE);
 
1302
    }
 
1303
 
 
1304
    printk("sparsing %ldMB at %lx\n", size >> 20, data);
 
1305
 
 
1306
    munmap((void *) data, size);
 
1307
    free_physical_pages(mfns, n);
 
1308
    do_map_zero(data, n);
 
1309
}
 
1310
 
 
1311
int nice(int inc)
 
1312
{
 
1313
    printk("nice() stub called with inc=%d\n", inc);
 
1314
    return 0;
 
1315
}
 
1316
 
 
1317
 
 
1318
/* Not supported by FS yet.  */
 
1319
unsupported_function_crash(link);
 
1320
unsupported_function(int, readlink, -1);
 
1321
unsupported_function_crash(umask);
 
1322
 
 
1323
/* We could support that.  */
 
1324
unsupported_function_log(int, chdir, -1);
 
1325
 
 
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);
 
1331
 
 
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);
 
1343
 
 
1344
/* Unsupported */
 
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);
 
1359
 
 
1360
/* net/if.h */
 
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);
 
1365
 
 
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!
 
1369
*/
 
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);
 
1431
#endif