Annotation of src/sys/compat/linux/common/linux_oldmmap.c, Revision 1.41
1.41 ! mycroft 1: /* $NetBSD: linux_misc.c,v 1.40 1998/03/03 13:44:48 fvdl Exp $ */
1.1 fvdl 2:
3: /*
4: * Copyright (c) 1995 Frank van der Linden
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed for the NetBSD Project
18: * by Frank van der Linden
19: * 4. The name of the author may not be used to endorse or promote products
20: * derived from this software without specific prior written permission
21: *
22: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32: */
33:
34: /*
35: * Linux compatibility module. Try to deal with various Linux system calls.
36: */
37:
38: #include <sys/param.h>
39: #include <sys/systm.h>
40: #include <sys/namei.h>
41: #include <sys/proc.h>
1.29 mycroft 42: #include <sys/dirent.h>
1.1 fvdl 43: #include <sys/file.h>
44: #include <sys/stat.h>
45: #include <sys/filedesc.h>
46: #include <sys/ioctl.h>
47: #include <sys/kernel.h>
48: #include <sys/malloc.h>
49: #include <sys/mbuf.h>
50: #include <sys/mman.h>
51: #include <sys/mount.h>
52: #include <sys/ptrace.h>
53: #include <sys/resource.h>
54: #include <sys/resourcevar.h>
55: #include <sys/signal.h>
56: #include <sys/signalvar.h>
57: #include <sys/socket.h>
58: #include <sys/time.h>
59: #include <sys/times.h>
60: #include <sys/vnode.h>
61: #include <sys/uio.h>
62: #include <sys/wait.h>
63: #include <sys/utsname.h>
64: #include <sys/unistd.h>
65:
66: #include <sys/syscallargs.h>
67:
68: #include <vm/vm.h>
69: #include <vm/vm_param.h>
70:
71: #include <compat/linux/linux_types.h>
72: #include <compat/linux/linux_fcntl.h>
73: #include <compat/linux/linux_mmap.h>
1.11 mycroft 74: #include <compat/linux/linux_signal.h>
1.1 fvdl 75: #include <compat/linux/linux_syscallargs.h>
76: #include <compat/linux/linux_util.h>
77: #include <compat/linux/linux_dirent.h>
78:
1.26 christos 79: /* linux_misc.c */
80: static void bsd_to_linux_wstat __P((int *));
81: static void bsd_to_linux_statfs __P((struct statfs *, struct linux_statfs *));
82: int linux_select1 __P((struct proc *, register_t *, int, fd_set *, fd_set *,
83: fd_set *, struct timeval *));
84:
1.1 fvdl 85: /*
86: * The information on a terminated (or stopped) process needs
87: * to be converted in order for Linux binaries to get a valid signal
88: * number out of it.
89: */
1.25 mycroft 90: static void
1.1 fvdl 91: bsd_to_linux_wstat(status)
92: int *status;
93: {
1.21 mycroft 94:
1.1 fvdl 95: if (WIFSIGNALED(*status))
96: *status = (*status & ~0177) |
1.12 mycroft 97: bsd_to_linux_sig[WTERMSIG(*status)];
1.1 fvdl 98: else if (WIFSTOPPED(*status))
99: *status = (*status & ~0xff00) |
1.12 mycroft 100: (bsd_to_linux_sig[WSTOPSIG(*status)] << 8);
1.1 fvdl 101: }
102:
103: /*
104: * waitpid(2). Passed on to the NetBSD call, surrounded by code to
105: * reserve some space for a NetBSD-style wait status, and converting
106: * it to what Linux wants.
107: */
108: int
1.21 mycroft 109: linux_sys_waitpid(p, v, retval)
1.1 fvdl 110: struct proc *p;
1.20 thorpej 111: void *v;
112: register_t *retval;
113: {
1.21 mycroft 114: struct linux_sys_waitpid_args /* {
1.1 fvdl 115: syscallarg(int) pid;
116: syscallarg(int *) status;
117: syscallarg(int) options;
1.20 thorpej 118: } */ *uap = v;
1.21 mycroft 119: struct sys_wait4_args w4a;
1.1 fvdl 120: int error, *status, tstat;
121: caddr_t sg;
122:
1.16 fvdl 123: if (SCARG(uap, status) != NULL) {
124: sg = stackgap_init(p->p_emul);
125: status = (int *) stackgap_alloc(&sg, sizeof status);
126: } else
127: status = NULL;
1.1 fvdl 128:
129: SCARG(&w4a, pid) = SCARG(uap, pid);
130: SCARG(&w4a, status) = status;
131: SCARG(&w4a, options) = SCARG(uap, options);
132: SCARG(&w4a, rusage) = NULL;
133:
1.21 mycroft 134: if ((error = sys_wait4(p, &w4a, retval)))
1.1 fvdl 135: return error;
136:
1.18 fvdl 137: p->p_siglist &= ~sigmask(SIGCHLD);
138:
1.16 fvdl 139: if (status != NULL) {
140: if ((error = copyin(status, &tstat, sizeof tstat)))
141: return error;
142:
143: bsd_to_linux_wstat(&tstat);
144: return copyout(&tstat, SCARG(uap, status), sizeof tstat);
145: }
1.1 fvdl 146:
1.16 fvdl 147: return 0;
1.1 fvdl 148: }
149:
150: /*
151: * This is very much the same as waitpid()
152: */
153: int
1.21 mycroft 154: linux_sys_wait4(p, v, retval)
1.1 fvdl 155: struct proc *p;
1.20 thorpej 156: void *v;
157: register_t *retval;
158: {
1.21 mycroft 159: struct linux_sys_wait4_args /* {
1.1 fvdl 160: syscallarg(int) pid;
161: syscallarg(int *) status;
162: syscallarg(int) options;
163: syscallarg(struct rusage *) rusage;
1.20 thorpej 164: } */ *uap = v;
1.21 mycroft 165: struct sys_wait4_args w4a;
1.1 fvdl 166: int error, *status, tstat;
167: caddr_t sg;
168:
1.16 fvdl 169: if (SCARG(uap, status) != NULL) {
170: sg = stackgap_init(p->p_emul);
171: status = (int *) stackgap_alloc(&sg, sizeof status);
172: } else
173: status = NULL;
1.1 fvdl 174:
175: SCARG(&w4a, pid) = SCARG(uap, pid);
176: SCARG(&w4a, status) = status;
177: SCARG(&w4a, options) = SCARG(uap, options);
178: SCARG(&w4a, rusage) = SCARG(uap, rusage);
179:
1.21 mycroft 180: if ((error = sys_wait4(p, &w4a, retval)))
1.1 fvdl 181: return error;
182:
1.18 fvdl 183: p->p_siglist &= ~sigmask(SIGCHLD);
184:
1.16 fvdl 185: if (status != NULL) {
186: if ((error = copyin(status, &tstat, sizeof tstat)))
187: return error;
188:
189: bsd_to_linux_wstat(&tstat);
190: return copyout(&tstat, SCARG(uap, status), sizeof tstat);
191: }
1.1 fvdl 192:
1.16 fvdl 193: return 0;
1.1 fvdl 194: }
195:
196: /*
197: * This is the old brk(2) call. I don't think anything in the Linux
198: * world uses this anymore
199: */
200: int
1.21 mycroft 201: linux_sys_break(p, v, retval)
1.1 fvdl 202: struct proc *p;
1.20 thorpej 203: void *v;
204: register_t *retval;
205: {
1.26 christos 206: #if 0
1.21 mycroft 207: struct linux_sys_brk_args /* {
1.1 fvdl 208: syscallarg(char *) nsize;
1.20 thorpej 209: } */ *uap = v;
1.26 christos 210: #endif
1.20 thorpej 211:
1.1 fvdl 212: return ENOSYS;
213: }
214:
215: /*
216: * Linux brk(2). The check if the new address is >= the old one is
217: * done in the kernel in Linux. NetBSD does it in the library.
218: */
219: int
1.21 mycroft 220: linux_sys_brk(p, v, retval)
1.1 fvdl 221: struct proc *p;
1.20 thorpej 222: void *v;
223: register_t *retval;
224: {
1.21 mycroft 225: struct linux_sys_brk_args /* {
1.1 fvdl 226: syscallarg(char *) nsize;
1.20 thorpej 227: } */ *uap = v;
1.1 fvdl 228: char *nbrk = SCARG(uap, nsize);
1.21 mycroft 229: struct sys_obreak_args oba;
1.1 fvdl 230: struct vmspace *vm = p->p_vmspace;
1.26 christos 231: caddr_t oldbrk;
1.1 fvdl 232:
233: oldbrk = vm->vm_daddr + ctob(vm->vm_dsize);
234: /*
235: * XXX inconsistent.. Linux always returns at least the old
236: * brk value, but it will be page-aligned if this fails,
237: * and possibly not page aligned if it succeeds (the user
238: * supplied pointer is returned).
239: */
240: SCARG(&oba, nsize) = nbrk;
241:
1.21 mycroft 242: if ((caddr_t) nbrk > vm->vm_daddr && sys_obreak(p, &oba, retval) == 0)
243: retval[0] = (register_t)nbrk;
1.1 fvdl 244: else
1.21 mycroft 245: retval[0] = (register_t)oldbrk;
1.1 fvdl 246:
247: return 0;
248: }
249:
250: /*
251: * I wonder why Linux has gettimeofday() _and_ time().. Still, we
252: * need to deal with it.
253: */
254: int
1.21 mycroft 255: linux_sys_time(p, v, retval)
1.1 fvdl 256: struct proc *p;
1.20 thorpej 257: void *v;
258: register_t *retval;
259: {
1.21 mycroft 260: struct linux_sys_time_args /* {
1.1 fvdl 261: linux_time_t *t;
1.20 thorpej 262: } */ *uap = v;
1.1 fvdl 263: struct timeval atv;
264: linux_time_t tt;
265: int error;
266:
267: microtime(&atv);
268:
269: tt = atv.tv_sec;
270: if (SCARG(uap, t) && (error = copyout(&tt, SCARG(uap, t), sizeof tt)))
271: return error;
272:
273: retval[0] = tt;
274: return 0;
275: }
276:
277: /*
1.2 fvdl 278: * Convert BSD statfs structure to Linux statfs structure.
279: * The Linux structure has less fields, and it also wants
280: * the length of a name in a dir entry in a field, which
281: * we fake (probably the wrong way).
282: */
283: static void
284: bsd_to_linux_statfs(bsp, lsp)
285: struct statfs *bsp;
286: struct linux_statfs *lsp;
287: {
1.21 mycroft 288:
1.2 fvdl 289: lsp->l_ftype = bsp->f_type;
290: lsp->l_fbsize = bsp->f_bsize;
291: lsp->l_fblocks = bsp->f_blocks;
292: lsp->l_fbfree = bsp->f_bfree;
293: lsp->l_fbavail = bsp->f_bavail;
294: lsp->l_ffiles = bsp->f_files;
295: lsp->l_fffree = bsp->f_ffree;
296: lsp->l_ffsid.val[0] = bsp->f_fsid.val[0];
297: lsp->l_ffsid.val[1] = bsp->f_fsid.val[1];
298: lsp->l_fnamelen = MAXNAMLEN; /* XXX */
299: }
300:
301: /*
302: * Implement the fs stat functions. Straightforward.
1.1 fvdl 303: */
304: int
1.21 mycroft 305: linux_sys_statfs(p, v, retval)
1.1 fvdl 306: struct proc *p;
1.20 thorpej 307: void *v;
308: register_t *retval;
309: {
1.21 mycroft 310: struct linux_sys_statfs_args /* {
1.1 fvdl 311: syscallarg(char *) path;
312: syscallarg(struct linux_statfs *) sp;
1.20 thorpej 313: } */ *uap = v;
1.2 fvdl 314: struct statfs btmp, *bsp;
315: struct linux_statfs ltmp;
1.21 mycroft 316: struct sys_statfs_args bsa;
1.2 fvdl 317: caddr_t sg;
318: int error;
319:
1.9 christos 320: sg = stackgap_init(p->p_emul);
1.2 fvdl 321: bsp = (struct statfs *) stackgap_alloc(&sg, sizeof (struct statfs));
322:
1.9 christos 323: LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
1.2 fvdl 324:
325: SCARG(&bsa, path) = SCARG(uap, path);
326: SCARG(&bsa, buf) = bsp;
327:
1.21 mycroft 328: if ((error = sys_statfs(p, &bsa, retval)))
1.2 fvdl 329: return error;
330:
331: if ((error = copyin((caddr_t) bsp, (caddr_t) &btmp, sizeof btmp)))
332: return error;
333:
334: bsd_to_linux_statfs(&btmp, <mp);
335:
336: return copyout((caddr_t) <mp, (caddr_t) SCARG(uap, sp), sizeof ltmp);
1.1 fvdl 337: }
338:
339: int
1.21 mycroft 340: linux_sys_fstatfs(p, v, retval)
1.1 fvdl 341: struct proc *p;
1.20 thorpej 342: void *v;
343: register_t *retval;
344: {
1.21 mycroft 345: struct linux_sys_fstatfs_args /* {
1.2 fvdl 346: syscallarg(int) fd;
1.1 fvdl 347: syscallarg(struct linux_statfs *) sp;
1.20 thorpej 348: } */ *uap = v;
1.2 fvdl 349: struct statfs btmp, *bsp;
350: struct linux_statfs ltmp;
1.21 mycroft 351: struct sys_fstatfs_args bsa;
1.2 fvdl 352: caddr_t sg;
353: int error;
354:
1.9 christos 355: sg = stackgap_init(p->p_emul);
1.2 fvdl 356: bsp = (struct statfs *) stackgap_alloc(&sg, sizeof (struct statfs));
357:
358: SCARG(&bsa, fd) = SCARG(uap, fd);
359: SCARG(&bsa, buf) = bsp;
360:
1.21 mycroft 361: if ((error = sys_fstatfs(p, &bsa, retval)))
1.2 fvdl 362: return error;
363:
364: if ((error = copyin((caddr_t) bsp, (caddr_t) &btmp, sizeof btmp)))
365: return error;
366:
367: bsd_to_linux_statfs(&btmp, <mp);
368:
369: return copyout((caddr_t) <mp, (caddr_t) SCARG(uap, sp), sizeof ltmp);
1.1 fvdl 370: }
371:
372: /*
373: * uname(). Just copy the info from the various strings stored in the
374: * kernel, and put it in the Linux utsname structure. That structure
375: * is almost the same as the NetBSD one, only it has fields 65 characters
376: * long, and an extra domainname field.
377: */
378: int
1.21 mycroft 379: linux_sys_uname(p, v, retval)
1.1 fvdl 380: struct proc *p;
1.20 thorpej 381: void *v;
382: register_t *retval;
383: {
1.21 mycroft 384: struct linux_sys_uname_args /* {
1.1 fvdl 385: syscallarg(struct linux_utsname *) up;
1.20 thorpej 386: } */ *uap = v;
1.15 mycroft 387: extern char ostype[], hostname[], osrelease[], version[], machine[],
388: domainname[];
389: struct linux_utsname luts;
1.1 fvdl 390: int len;
391: char *cp;
392:
1.15 mycroft 393: strncpy(luts.l_sysname, ostype, sizeof(luts.l_sysname));
394: strncpy(luts.l_nodename, hostname, sizeof(luts.l_nodename));
395: strncpy(luts.l_release, osrelease, sizeof(luts.l_release));
396: strncpy(luts.l_version, version, sizeof(luts.l_version));
397: strncpy(luts.l_machine, machine, sizeof(luts.l_machine));
398: strncpy(luts.l_domainname, domainname, sizeof(luts.l_domainname));
1.1 fvdl 399:
400: /* This part taken from the the uname() in libc */
1.15 mycroft 401: len = sizeof(luts.l_version);
402: for (cp = luts.l_version; len--; ++cp)
1.1 fvdl 403: if (*cp == '\n' || *cp == '\t')
404: if (len > 1)
405: *cp = ' ';
406: else
407: *cp = '\0';
408:
1.15 mycroft 409: return copyout(&luts, SCARG(uap, up), sizeof(luts));
410: }
411:
412: int
1.21 mycroft 413: linux_sys_olduname(p, v, retval)
1.15 mycroft 414: struct proc *p;
1.20 thorpej 415: void *v;
416: register_t *retval;
417: {
1.21 mycroft 418: struct linux_sys_uname_args /* {
1.15 mycroft 419: syscallarg(struct linux_oldutsname *) up;
1.20 thorpej 420: } */ *uap = v;
1.15 mycroft 421: extern char ostype[], hostname[], osrelease[], version[], machine[];
422: struct linux_oldutsname luts;
423: int len;
424: char *cp;
425:
426: strncpy(luts.l_sysname, ostype, sizeof(luts.l_sysname));
427: strncpy(luts.l_nodename, hostname, sizeof(luts.l_nodename));
428: strncpy(luts.l_release, osrelease, sizeof(luts.l_release));
429: strncpy(luts.l_version, version, sizeof(luts.l_version));
430: strncpy(luts.l_machine, machine, sizeof(luts.l_machine));
431:
432: /* This part taken from the the uname() in libc */
433: len = sizeof(luts.l_version);
434: for (cp = luts.l_version; len--; ++cp)
435: if (*cp == '\n' || *cp == '\t')
436: if (len > 1)
437: *cp = ' ';
438: else
439: *cp = '\0';
440:
441: return copyout(&luts, SCARG(uap, up), sizeof(luts));
442: }
443:
444: int
1.21 mycroft 445: linux_sys_oldolduname(p, v, retval)
1.15 mycroft 446: struct proc *p;
1.20 thorpej 447: void *v;
448: register_t *retval;
449: {
1.21 mycroft 450: struct linux_sys_uname_args /* {
1.15 mycroft 451: syscallarg(struct linux_oldoldutsname *) up;
1.20 thorpej 452: } */ *uap = v;
1.15 mycroft 453: extern char ostype[], hostname[], osrelease[], version[], machine[];
454: struct linux_oldoldutsname luts;
455: int len;
456: char *cp;
457:
458: strncpy(luts.l_sysname, ostype, sizeof(luts.l_sysname));
459: strncpy(luts.l_nodename, hostname, sizeof(luts.l_nodename));
460: strncpy(luts.l_release, osrelease, sizeof(luts.l_release));
461: strncpy(luts.l_version, version, sizeof(luts.l_version));
462: strncpy(luts.l_machine, machine, sizeof(luts.l_machine));
463:
464: /* This part taken from the the uname() in libc */
465: len = sizeof(luts.l_version);
466: for (cp = luts.l_version; len--; ++cp)
467: if (*cp == '\n' || *cp == '\t')
468: if (len > 1)
469: *cp = ' ';
470: else
471: *cp = '\0';
472:
473: return copyout(&luts, SCARG(uap, up), sizeof(luts));
1.1 fvdl 474: }
475:
476: /*
477: * Linux wants to pass everything to a syscall in registers. However,
478: * mmap() has 6 of them. Oops: out of register error. They just pass
479: * everything in a structure.
480: */
481: int
1.21 mycroft 482: linux_sys_mmap(p, v, retval)
1.1 fvdl 483: struct proc *p;
1.20 thorpej 484: void *v;
485: register_t *retval;
486: {
1.21 mycroft 487: struct linux_sys_mmap_args /* {
1.1 fvdl 488: syscallarg(struct linux_mmap *) lmp;
1.20 thorpej 489: } */ *uap = v;
1.1 fvdl 490: struct linux_mmap lmap;
1.21 mycroft 491: struct sys_mmap_args cma;
1.1 fvdl 492: int error, flags;
493:
494: if ((error = copyin(SCARG(uap, lmp), &lmap, sizeof lmap)))
495: return error;
496:
497: flags = 0;
498: flags |= cvtto_bsd_mask(lmap.lm_flags, LINUX_MAP_SHARED, MAP_SHARED);
499: flags |= cvtto_bsd_mask(lmap.lm_flags, LINUX_MAP_PRIVATE, MAP_PRIVATE);
500: flags |= cvtto_bsd_mask(lmap.lm_flags, LINUX_MAP_FIXED, MAP_FIXED);
501: flags |= cvtto_bsd_mask(lmap.lm_flags, LINUX_MAP_ANON, MAP_ANON);
502:
503: SCARG(&cma,addr) = lmap.lm_addr;
504: SCARG(&cma,len) = lmap.lm_len;
1.31 augustss 505: if (lmap.lm_prot & VM_PROT_WRITE) /* XXX */
506: lmap.lm_prot |= VM_PROT_READ;
1.1 fvdl 507: SCARG(&cma,prot) = lmap.lm_prot;
508: SCARG(&cma,flags) = flags;
509: SCARG(&cma,fd) = lmap.lm_fd;
510: SCARG(&cma,pad) = 0;
511: SCARG(&cma,pos) = lmap.lm_pos;
512:
1.21 mycroft 513: return sys_mmap(p, &cma, retval);
1.34 mycroft 514: }
515:
516: int
517: linux_sys_mremap(p, v, retval)
518: struct proc *p;
519: void *v;
520: register_t *retval;
521: {
522: #ifdef notyet
523: struct linux_sys_mremap_args /* {
524: syscallarg(void *) old_address;
525: syscallarg(size_t) old_size;
526: syscallarg(size_t) new_size;
527: syscallarg(u_long) flags;
528: } */ *uap = v;
529: #endif
530:
531: return ENOMEM;
1.24 fvdl 532: }
533:
534: int
535: linux_sys_msync(p, v, retval)
536: struct proc *p;
537: void *v;
538: register_t *retval;
539: {
540: struct linux_sys_msync_args /* {
541: syscallarg(caddr_t) addr;
542: syscallarg(int) len;
543: syscallarg(int) fl;
544: } */ *uap = v;
545:
1.36 fvdl 546: struct sys___msync13_args bma;
1.24 fvdl 547:
548: /* flags are ignored */
549: SCARG(&bma, addr) = SCARG(uap, addr);
550: SCARG(&bma, len) = SCARG(uap, len);
1.36 fvdl 551: SCARG(&bma, flags) = SCARG(uap, fl);
1.24 fvdl 552:
1.36 fvdl 553: return sys___msync13(p, &bma, retval);
1.1 fvdl 554: }
555:
556: /*
557: * This code is partly stolen from src/lib/libc/compat-43/times.c
558: * XXX - CLK_TCK isn't declared in /sys, just in <time.h>, done here
559: */
560:
561: #define CLK_TCK 100
562: #define CONVTCK(r) (r.tv_sec * CLK_TCK + r.tv_usec / (1000000 / CLK_TCK))
563:
564: int
1.21 mycroft 565: linux_sys_times(p, v, retval)
1.1 fvdl 566: struct proc *p;
1.20 thorpej 567: void *v;
568: register_t *retval;
569: {
1.21 mycroft 570: struct linux_sys_times_args /* {
1.1 fvdl 571: syscallarg(struct times *) tms;
1.20 thorpej 572: } */ *uap = v;
1.1 fvdl 573: struct timeval t;
574: struct linux_tms ltms;
575: struct rusage ru;
1.4 mycroft 576: int error, s;
1.1 fvdl 577:
578: calcru(p, &ru.ru_utime, &ru.ru_stime, NULL);
579: ltms.ltms_utime = CONVTCK(ru.ru_utime);
580: ltms.ltms_stime = CONVTCK(ru.ru_stime);
581:
582: ltms.ltms_cutime = CONVTCK(p->p_stats->p_cru.ru_utime);
583: ltms.ltms_cstime = CONVTCK(p->p_stats->p_cru.ru_stime);
584:
585: if ((error = copyout(<ms, SCARG(uap, tms), sizeof ltms)))
586: return error;
587:
1.4 mycroft 588: s = splclock();
589: timersub(&time, &boottime, &t);
590: splx(s);
1.1 fvdl 591:
592: retval[0] = ((linux_clock_t)(CONVTCK(t)));
593: return 0;
594: }
595:
596: /*
597: * NetBSD passes fd[0] in retval[0], and fd[1] in retval[1].
598: * Linux directly passes the pointer.
599: */
600: int
1.21 mycroft 601: linux_sys_pipe(p, v, retval)
1.1 fvdl 602: struct proc *p;
1.20 thorpej 603: void *v;
604: register_t *retval;
605: {
1.21 mycroft 606: struct linux_sys_pipe_args /* {
1.1 fvdl 607: syscallarg(int *) pfds;
1.20 thorpej 608: } */ *uap = v;
1.1 fvdl 609: int error;
610:
1.21 mycroft 611: if ((error = sys_pipe(p, 0, retval)))
1.1 fvdl 612: return error;
613:
614: /* Assumes register_t is an int */
615:
616: if ((error = copyout(retval, SCARG(uap, pfds), 2 * sizeof (int))))
617: return error;
618:
619: retval[0] = 0;
620: return 0;
621: }
622:
623: /*
1.21 mycroft 624: * Alarm. This is a libc call which uses setitimer(2) in NetBSD.
1.1 fvdl 625: * Fiddle with the timers to make it work.
626: */
627: int
1.21 mycroft 628: linux_sys_alarm(p, v, retval)
1.1 fvdl 629: struct proc *p;
1.20 thorpej 630: void *v;
631: register_t *retval;
632: {
1.21 mycroft 633: struct linux_sys_alarm_args /* {
1.1 fvdl 634: syscallarg(unsigned int) secs;
1.20 thorpej 635: } */ *uap = v;
1.26 christos 636: int s;
1.1 fvdl 637: struct itimerval *itp, it;
638:
639: itp = &p->p_realtimer;
640: s = splclock();
641: /*
642: * Clear any pending timer alarms.
643: */
644: untimeout(realitexpire, p);
645: timerclear(&itp->it_interval);
646: if (timerisset(&itp->it_value) &&
647: timercmp(&itp->it_value, &time, >))
1.3 mycroft 648: timersub(&itp->it_value, &time, &itp->it_value);
1.1 fvdl 649: /*
650: * Return how many seconds were left (rounded up)
651: */
652: retval[0] = itp->it_value.tv_sec;
653: if (itp->it_value.tv_usec)
654: retval[0]++;
655:
656: /*
657: * alarm(0) just resets the timer.
658: */
659: if (SCARG(uap, secs) == 0) {
660: timerclear(&itp->it_value);
661: splx(s);
662: return 0;
663: }
664:
665: /*
666: * Check the new alarm time for sanity, and set it.
667: */
668: timerclear(&it.it_interval);
669: it.it_value.tv_sec = SCARG(uap, secs);
670: it.it_value.tv_usec = 0;
671: if (itimerfix(&it.it_value) || itimerfix(&it.it_interval)) {
672: splx(s);
673: return (EINVAL);
674: }
675:
676: if (timerisset(&it.it_value)) {
1.3 mycroft 677: timeradd(&it.it_value, &time, &it.it_value);
1.1 fvdl 678: timeout(realitexpire, p, hzto(&it.it_value));
679: }
680: p->p_realtimer = it;
681: splx(s);
682:
683: return 0;
684: }
685:
686: /*
687: * utime(). Do conversion to things that utimes() understands,
688: * and pass it on.
689: */
690: int
1.21 mycroft 691: linux_sys_utime(p, v, retval)
1.1 fvdl 692: struct proc *p;
1.20 thorpej 693: void *v;
694: register_t *retval;
695: {
1.21 mycroft 696: struct linux_sys_utime_args /* {
1.1 fvdl 697: syscallarg(char *) path;
698: syscallarg(struct linux_utimbuf *)times;
1.20 thorpej 699: } */ *uap = v;
1.1 fvdl 700: caddr_t sg;
701: int error;
1.21 mycroft 702: struct sys_utimes_args ua;
1.1 fvdl 703: struct timeval tv[2], *tvp;
704: struct linux_utimbuf lut;
705:
1.9 christos 706: sg = stackgap_init(p->p_emul);
707: LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
1.1 fvdl 708:
709: SCARG(&ua, path) = SCARG(uap, path);
710:
711: if (SCARG(uap, times) != NULL) {
712: if ((error = copyin(SCARG(uap, times), &lut, sizeof lut)))
713: return error;
714: tv[0].tv_usec = tv[1].tv_usec = 0;
715: tv[0].tv_sec = lut.l_actime;
716: tv[1].tv_sec = lut.l_modtime;
1.9 christos 717: tvp = (struct timeval *) stackgap_alloc(&sg, sizeof(tv));
1.1 fvdl 718: if ((error = copyout(tv, tvp, sizeof tv)))
719: return error;
720: SCARG(&ua, tptr) = tvp;
721: }
722: else
723: SCARG(&ua, tptr) = NULL;
724:
1.41 ! mycroft 725: return sys_utimes(p, &ua, retval);
1.1 fvdl 726: }
727:
728: /*
1.17 fvdl 729: * The old Linux readdir was only able to read one entry at a time,
730: * even though it had a 'count' argument. In fact, the emulation
731: * of the old call was better than the original, because it did handle
732: * the count arg properly. Don't bother with it anymore now, and use
733: * it to distinguish between old and new. The difference is that the
734: * newer one actually does multiple entries, and the reclen field
735: * really is the reclen, not the namelength.
736: */
737: int
1.21 mycroft 738: linux_sys_readdir(p, v, retval)
1.17 fvdl 739: struct proc *p;
1.20 thorpej 740: void *v;
741: register_t *retval;
742: {
1.21 mycroft 743: struct linux_sys_readdir_args /* {
1.17 fvdl 744: syscallarg(int) fd;
745: syscallarg(struct linux_dirent *) dent;
746: syscallarg(unsigned int) count;
1.20 thorpej 747: } */ *uap = v;
748:
1.17 fvdl 749: SCARG(uap, count) = 1;
1.21 mycroft 750: return linux_sys_getdents(p, uap, retval);
1.17 fvdl 751: }
752:
753: /*
1.1 fvdl 754: * Linux 'readdir' call. This code is mostly taken from the
755: * SunOS getdents call (see compat/sunos/sunos_misc.c), though
756: * an attempt has been made to keep it a little cleaner (failing
757: * miserably, because of the cruft needed if count 1 is passed).
758: *
1.17 fvdl 759: * The d_off field should contain the offset of the next valid entry,
760: * but in Linux it has the offset of the entry itself. We emulate
761: * that bug here.
762: *
1.1 fvdl 763: * Read in BSD-style entries, convert them, and copy them out.
764: *
765: * Note that this doesn't handle union-mounted filesystems.
766: */
767: int
1.21 mycroft 768: linux_sys_getdents(p, v, retval)
1.1 fvdl 769: struct proc *p;
1.20 thorpej 770: void *v;
771: register_t *retval;
772: {
1.21 mycroft 773: struct linux_sys_readdir_args /* {
1.1 fvdl 774: syscallarg(int) fd;
1.21 mycroft 775: syscallarg(caddr_t) dent;
1.1 fvdl 776: syscallarg(unsigned int) count;
1.20 thorpej 777: } */ *uap = v;
1.1 fvdl 778: register struct dirent *bdp;
779: struct vnode *vp;
1.26 christos 780: caddr_t inp, buf; /* BSD-format */
781: int len, reclen; /* BSD-format */
782: caddr_t outp; /* Linux-format */
783: int resid, linux_reclen = 0; /* Linux-format */
1.1 fvdl 784: struct file *fp;
785: struct uio auio;
786: struct iovec aiov;
787: struct linux_dirent idb;
788: off_t off; /* true file offset */
1.17 fvdl 789: int buflen, error, eofflag, nbytes, oldcall;
1.1 fvdl 790: struct vattr va;
1.40 fvdl 791: off_t *cookiebuf = NULL, *cookie;
1.22 mycroft 792: int ncookies;
1.1 fvdl 793:
794: if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
795: return (error);
796:
797: if ((fp->f_flag & FREAD) == 0)
798: return (EBADF);
799:
1.5 mycroft 800: vp = (struct vnode *)fp->f_data;
1.1 fvdl 801:
802: if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)))
803: return error;
804:
805: nbytes = SCARG(uap, count);
1.17 fvdl 806: if (nbytes == 1) { /* emulating old, broken behaviour */
1.1 fvdl 807: nbytes = sizeof (struct linux_dirent);
1.5 mycroft 808: buflen = max(va.va_blocksize, nbytes);
1.17 fvdl 809: oldcall = 1;
1.5 mycroft 810: } else {
811: buflen = min(MAXBSIZE, nbytes);
1.33 fvdl 812: if (buflen < va.va_blocksize)
813: buflen = va.va_blocksize;
1.17 fvdl 814: oldcall = 0;
1.1 fvdl 815: }
816: buf = malloc(buflen, M_TEMP, M_WAITOK);
1.33 fvdl 817:
1.39 fvdl 818: vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1.1 fvdl 819: off = fp->f_offset;
820: again:
821: aiov.iov_base = buf;
822: aiov.iov_len = buflen;
823: auio.uio_iov = &aiov;
824: auio.uio_iovcnt = 1;
825: auio.uio_rw = UIO_READ;
826: auio.uio_segflg = UIO_SYSSPACE;
827: auio.uio_procp = p;
828: auio.uio_resid = buflen;
829: auio.uio_offset = off;
830: /*
831: * First we read into the malloc'ed buffer, then
832: * we massage it into user space, one record at a time.
833: */
1.39 fvdl 834: error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
835: &ncookies);
1.1 fvdl 836: if (error)
837: goto out;
838:
839: inp = buf;
1.21 mycroft 840: outp = SCARG(uap, dent);
1.1 fvdl 841: resid = nbytes;
1.35 fvdl 842: if ((len = buflen - auio.uio_resid) == 0)
1.1 fvdl 843: goto eof;
844:
1.22 mycroft 845: for (cookie = cookiebuf; len > 0; len -= reclen) {
1.5 mycroft 846: bdp = (struct dirent *)inp;
847: reclen = bdp->d_reclen;
1.1 fvdl 848: if (reclen & 3)
849: panic("linux_readdir");
850: if (bdp->d_fileno == 0) {
851: inp += reclen; /* it is a hole; squish it out */
1.22 mycroft 852: off = *cookie++;
1.1 fvdl 853: continue;
854: }
1.21 mycroft 855: linux_reclen = LINUX_RECLEN(&idb, bdp->d_namlen);
856: if (reclen > len || resid < linux_reclen) {
1.1 fvdl 857: /* entry too big for buffer, so just stop */
858: outp++;
859: break;
860: }
861: /*
862: * Massage in place to make a Linux-shaped dirent (otherwise
863: * we have to worry about touching user memory outside of
864: * the copyout() call).
865: */
1.22 mycroft 866: idb.d_ino = (linux_ino_t)bdp->d_fileno;
1.17 fvdl 867: /*
1.21 mycroft 868: * The old readdir() call misuses the offset and reclen fields.
1.17 fvdl 869: */
1.22 mycroft 870: if (oldcall) {
871: idb.d_off = (linux_off_t)linux_reclen;
872: idb.d_reclen = (u_short)bdp->d_namlen;
873: } else {
1.33 fvdl 874: if (sizeof (linux_off_t) < 4 && (off >> 32) != 0) {
875: compat_offseterr(vp, "linux_getdents");
876: error = EINVAL;
877: goto out;
878: }
1.22 mycroft 879: idb.d_off = (linux_off_t)off;
880: idb.d_reclen = (u_short)linux_reclen;
881: }
1.5 mycroft 882: strcpy(idb.d_name, bdp->d_name);
1.21 mycroft 883: if ((error = copyout((caddr_t)&idb, outp, linux_reclen)))
1.1 fvdl 884: goto out;
885: /* advance past this real entry */
886: inp += reclen;
1.22 mycroft 887: off = *cookie++; /* each entry points to itself */
1.1 fvdl 888: /* advance output past Linux-shaped entry */
1.21 mycroft 889: outp += linux_reclen;
890: resid -= linux_reclen;
1.17 fvdl 891: if (oldcall)
1.1 fvdl 892: break;
893: }
894:
895: /* if we squished out the whole block, try again */
1.21 mycroft 896: if (outp == SCARG(uap, dent))
1.1 fvdl 897: goto again;
898: fp->f_offset = off; /* update the vnode offset */
899:
1.17 fvdl 900: if (oldcall)
1.21 mycroft 901: nbytes = resid + linux_reclen;
1.1 fvdl 902:
903: eof:
904: *retval = nbytes - resid;
905: out:
1.39 fvdl 906: VOP_UNLOCK(vp, 0);
1.40 fvdl 907: if (cookiebuf)
908: free(cookiebuf, M_TEMP);
1.1 fvdl 909: free(buf, M_TEMP);
910: return error;
911: }
912:
913: /*
1.17 fvdl 914: * Not sure why the arguments to this older version of select() were put
915: * into a structure, because there are 5, and that can all be handled
916: * in registers on the i386 like Linux wants to.
917: */
918: int
1.21 mycroft 919: linux_sys_oldselect(p, v, retval)
1.17 fvdl 920: struct proc *p;
1.20 thorpej 921: void *v;
922: register_t *retval;
923: {
1.21 mycroft 924: struct linux_sys_oldselect_args /* {
1.17 fvdl 925: syscallarg(struct linux_select *) lsp;
1.20 thorpej 926: } */ *uap = v;
1.17 fvdl 927: struct linux_select ls;
928: int error;
929:
930: if ((error = copyin(SCARG(uap, lsp), &ls, sizeof(ls))))
931: return error;
932:
933: return linux_select1(p, retval, ls.nfds, ls.readfds, ls.writefds,
934: ls.exceptfds, ls.timeout);
935: }
936:
937: /*
938: * Even when just using registers to pass arguments to syscalls you can
939: * have 5 of them on the i386. So this newer version of select() does
940: * this.
1.1 fvdl 941: */
942: int
1.21 mycroft 943: linux_sys_select(p, v, retval)
1.1 fvdl 944: struct proc *p;
1.20 thorpej 945: void *v;
946: register_t *retval;
947: {
1.21 mycroft 948: struct linux_sys_select_args /* {
1.17 fvdl 949: syscallarg(int) nfds;
950: syscallarg(fd_set *) readfds;
951: syscallarg(fd_set *) writefds;
952: syscallarg(fd_set *) exceptfds;
953: syscallarg(struct timeval *) timeout;
1.20 thorpej 954: } */ *uap = v;
955:
1.17 fvdl 956: return linux_select1(p, retval, SCARG(uap, nfds), SCARG(uap, readfds),
957: SCARG(uap, writefds), SCARG(uap, exceptfds), SCARG(uap, timeout));
958: }
959:
960: /*
961: * Common code for the old and new versions of select(). A couple of
962: * things are important:
963: * 1) return the amount of time left in the 'timeout' parameter
964: * 2) select never returns ERESTART on Linux, always return EINTR
965: */
966: int
967: linux_select1(p, retval, nfds, readfds, writefds, exceptfds, timeout)
968: struct proc *p;
969: register_t *retval;
970: int nfds;
971: fd_set *readfds, *writefds, *exceptfds;
972: struct timeval *timeout;
973: {
1.21 mycroft 974: struct sys_select_args bsa;
1.13 mycroft 975: struct timeval tv0, tv1, utv, *tvp;
976: caddr_t sg;
1.1 fvdl 977: int error;
978:
1.17 fvdl 979: SCARG(&bsa, nd) = nfds;
980: SCARG(&bsa, in) = readfds;
981: SCARG(&bsa, ou) = writefds;
982: SCARG(&bsa, ex) = exceptfds;
983: SCARG(&bsa, tv) = timeout;
1.1 fvdl 984:
1.7 fvdl 985: /*
986: * Store current time for computation of the amount of
987: * time left.
988: */
1.17 fvdl 989: if (timeout) {
990: if ((error = copyin(timeout, &utv, sizeof(utv))))
1.13 mycroft 991: return error;
992: if (itimerfix(&utv)) {
993: /*
994: * The timeval was invalid. Convert it to something
995: * valid that will act as it does under Linux.
996: */
997: sg = stackgap_init(p->p_emul);
998: tvp = stackgap_alloc(&sg, sizeof(utv));
999: utv.tv_sec += utv.tv_usec / 1000000;
1000: utv.tv_usec %= 1000000;
1001: if (utv.tv_usec < 0) {
1002: utv.tv_sec -= 1;
1003: utv.tv_usec += 1000000;
1004: }
1005: if (utv.tv_sec < 0)
1006: timerclear(&utv);
1007: if ((error = copyout(&utv, tvp, sizeof(utv))))
1008: return error;
1009: SCARG(&bsa, tv) = tvp;
1010: }
1.7 fvdl 1011: microtime(&tv0);
1.13 mycroft 1012: }
1.7 fvdl 1013:
1.21 mycroft 1014: error = sys_select(p, &bsa, retval);
1.10 mycroft 1015: if (error) {
1016: /*
1017: * See fs/select.c in the Linux kernel. Without this,
1018: * Maelstrom doesn't work.
1019: */
1020: if (error == ERESTART)
1021: error = EINTR;
1.7 fvdl 1022: return error;
1.10 mycroft 1023: }
1.7 fvdl 1024:
1.17 fvdl 1025: if (timeout) {
1.14 mycroft 1026: if (*retval) {
1.7 fvdl 1027: /*
1.13 mycroft 1028: * Compute how much time was left of the timeout,
1.7 fvdl 1029: * by subtracting the current time and the time
1030: * before we started the call, and subtracting
1031: * that result from the user-supplied value.
1032: */
1033: microtime(&tv1);
1034: timersub(&tv1, &tv0, &tv1);
1035: timersub(&utv, &tv1, &utv);
1.14 mycroft 1036: if (utv.tv_sec < 0)
1037: timerclear(&utv);
1038: } else
1039: timerclear(&utv);
1.17 fvdl 1040: if ((error = copyout(&utv, timeout, sizeof(utv))))
1.7 fvdl 1041: return error;
1042: }
1.13 mycroft 1043:
1.7 fvdl 1044: return 0;
1.1 fvdl 1045: }
1046:
1047: /*
1048: * Get the process group of a certain process. Look it up
1049: * and return the value.
1050: */
1051: int
1.21 mycroft 1052: linux_sys_getpgid(p, v, retval)
1.1 fvdl 1053: struct proc *p;
1.20 thorpej 1054: void *v;
1055: register_t *retval;
1056: {
1.21 mycroft 1057: struct linux_sys_getpgid_args /* {
1.1 fvdl 1058: syscallarg(int) pid;
1.20 thorpej 1059: } */ *uap = v;
1.1 fvdl 1060: struct proc *targp;
1061:
1.26 christos 1062: if (SCARG(uap, pid) != 0 && SCARG(uap, pid) != p->p_pid) {
1.1 fvdl 1063: if ((targp = pfind(SCARG(uap, pid))) == 0)
1064: return ESRCH;
1.26 christos 1065: }
1.1 fvdl 1066: else
1067: targp = p;
1068:
1069: retval[0] = targp->p_pgid;
1.6 fvdl 1070: return 0;
1071: }
1072:
1073: /*
1074: * Set the 'personality' (emulation mode) for the current process. Only
1075: * accept the Linux personality here (0). This call is needed because
1076: * the Linux ELF crt0 issues it in an ugly kludge to make sure that
1077: * ELF binaries run in Linux mode, not SVR4 mode.
1078: */
1079: int
1.21 mycroft 1080: linux_sys_personality(p, v, retval)
1.6 fvdl 1081: struct proc *p;
1.20 thorpej 1082: void *v;
1083: register_t *retval;
1084: {
1.21 mycroft 1085: struct linux_sys_personality_args /* {
1.6 fvdl 1086: syscallarg(int) per;
1.20 thorpej 1087: } */ *uap = v;
1088:
1.6 fvdl 1089: if (SCARG(uap, per) != 0)
1090: return EINVAL;
1091: retval[0] = 0;
1.1 fvdl 1092: return 0;
1.18 fvdl 1093: }
1094:
1095: /*
1096: * The calls are here because of type conversions.
1097: */
1098: int
1.21 mycroft 1099: linux_sys_setreuid(p, v, retval)
1.18 fvdl 1100: struct proc *p;
1.20 thorpej 1101: void *v;
1102: register_t *retval;
1103: {
1.21 mycroft 1104: struct linux_sys_setreuid_args /* {
1.18 fvdl 1105: syscallarg(int) ruid;
1106: syscallarg(int) euid;
1.20 thorpej 1107: } */ *uap = v;
1.28 mycroft 1108: struct sys_setreuid_args bsa;
1.18 fvdl 1109:
1110: SCARG(&bsa, ruid) = ((linux_uid_t)SCARG(uap, ruid) == (linux_uid_t)-1) ?
1111: (uid_t)-1 : SCARG(uap, ruid);
1112: SCARG(&bsa, euid) = ((linux_uid_t)SCARG(uap, euid) == (linux_uid_t)-1) ?
1113: (uid_t)-1 : SCARG(uap, euid);
1114:
1.28 mycroft 1115: return sys_setreuid(p, &bsa, retval);
1.18 fvdl 1116: }
1117:
1118: int
1.21 mycroft 1119: linux_sys_setregid(p, v, retval)
1.18 fvdl 1120: struct proc *p;
1.20 thorpej 1121: void *v;
1122: register_t *retval;
1123: {
1.21 mycroft 1124: struct linux_sys_setregid_args /* {
1.18 fvdl 1125: syscallarg(int) rgid;
1126: syscallarg(int) egid;
1.20 thorpej 1127: } */ *uap = v;
1.28 mycroft 1128: struct sys_setregid_args bsa;
1.18 fvdl 1129:
1130: SCARG(&bsa, rgid) = ((linux_gid_t)SCARG(uap, rgid) == (linux_gid_t)-1) ?
1131: (uid_t)-1 : SCARG(uap, rgid);
1132: SCARG(&bsa, egid) = ((linux_gid_t)SCARG(uap, egid) == (linux_gid_t)-1) ?
1133: (uid_t)-1 : SCARG(uap, egid);
1134:
1.28 mycroft 1135: return sys_setregid(p, &bsa, retval);
1.27 fvdl 1136: }
1137:
1138: int
1139: linux_sys___sysctl(p, v, retval)
1140: struct proc *p;
1141: void *v;
1142: register_t *retval;
1143: {
1144: struct linux_sys___sysctl_args /* {
1145: syscallarg(struct linux___sysctl *) lsp;
1146: } */ *uap = v;
1147: struct linux___sysctl ls;
1148: struct sys___sysctl_args bsa;
1149: int error;
1150:
1151: if ((error = copyin(SCARG(uap, lsp), &ls, sizeof ls)))
1152: return error;
1153: SCARG(&bsa, name) = ls.name;
1154: SCARG(&bsa, namelen) = ls.namelen;
1155: SCARG(&bsa, old) = ls.old;
1156: SCARG(&bsa, oldlenp) = ls.oldlenp;
1157: SCARG(&bsa, new) = ls.new;
1158: SCARG(&bsa, newlen) = ls.newlen;
1159:
1160: return sys___sysctl(p, &bsa, retval);
1.30 augustss 1161: }
1162:
1163: int
1164: linux_sys_nice(p, v, retval)
1165: struct proc *p;
1166: void *v;
1167: register_t *retval;
1168: {
1169: struct linux_sys_nice_args /* {
1170: syscallarg(int) incr;
1171: } */ *uap = v;
1172: struct sys_setpriority_args bsa;
1173:
1174: SCARG(&bsa, which) = PRIO_PROCESS;
1175: SCARG(&bsa, who) = 0;
1176: SCARG(&bsa, prio) = SCARG(uap, incr);
1177: return sys_setpriority(p, &bsa, retval);
1.1 fvdl 1178: }
CVSweb <webmaster@jp.NetBSD.org>