Import 2.4.0-test3pre8
[davej-history.git] / arch / mips64 / kernel / linux32.c
blob70746da227b4917ffdb5b4583f1393172235e25e
1 /*
2 * Conversion between 32-bit and 64-bit native system calls.
4 * Copyright (C) 2000 Silicon Graphics, Inc.
5 * Written by Ulf Carlsson (ulfc@engr.sgi.com)
6 * sys32_execve from ia64/ia32 code, Feb 2000, Kanoj Sarcar (kanoj@sgi.com)
7 */
9 #include <linux/mm.h>
10 #include <linux/errno.h>
11 #include <linux/file.h>
12 #include <linux/smp_lock.h>
13 #include <linux/highuid.h>
14 #include <linux/dirent.h>
15 #include <linux/resource.h>
16 #include <linux/highmem.h>
17 #include <linux/time.h>
18 #include <linux/poll.h>
19 #include <linux/slab.h>
20 #include <linux/skbuff.h>
21 #include <linux/filter.h>
23 #include <asm/uaccess.h>
24 #include <asm/mman.h>
27 #define A(__x) ((unsigned long)(__x))
30 * Revalidate the inode. This is required for proper NFS attribute caching.
32 static __inline__ int
33 do_revalidate(struct dentry *dentry)
35 struct inode * inode = dentry->d_inode;
37 if (inode->i_op && inode->i_op->revalidate)
38 return inode->i_op->revalidate(dentry);
40 return 0;
43 static int cp_new_stat32(struct inode * inode, struct stat32 * statbuf)
45 struct stat32 tmp;
46 unsigned int blocks, indirect;
48 memset(&tmp, 0, sizeof(tmp));
49 tmp.st_dev = kdev_t_to_nr(inode->i_dev);
50 tmp.st_ino = inode->i_ino;
51 tmp.st_mode = inode->i_mode;
52 tmp.st_nlink = inode->i_nlink;
53 SET_STAT_UID(tmp, inode->i_uid);
54 SET_STAT_GID(tmp, inode->i_gid);
55 tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
56 tmp.st_size = inode->i_size;
57 tmp.st_atime = inode->i_atime;
58 tmp.st_mtime = inode->i_mtime;
59 tmp.st_ctime = inode->i_ctime;
62 * st_blocks and st_blksize are approximated with a simple algorithm if
63 * they aren't supported directly by the filesystem. The minix and msdos
64 * filesystems don't keep track of blocks, so they would either have to
65 * be counted explicitly (by delving into the file itself), or by using
66 * this simple algorithm to get a reasonable (although not 100%
67 * accurate) value.
71 * Use minix fs values for the number of direct and indirect blocks.
72 * The count is now exact for the minix fs except that it counts zero
73 * blocks. Everything is in units of BLOCK_SIZE until the assignment
74 * to tmp.st_blksize.
76 #define D_B 7
77 #define I_B (BLOCK_SIZE / sizeof(unsigned short))
79 if (!inode->i_blksize) {
80 blocks = (tmp.st_size + BLOCK_SIZE - 1) / BLOCK_SIZE;
81 if (blocks > D_B) {
82 indirect = (blocks - D_B + I_B - 1) / I_B;
83 blocks += indirect;
84 if (indirect > 1) {
85 indirect = (indirect - 1 + I_B - 1) / I_B;
86 blocks += indirect;
87 if (indirect > 1)
88 blocks++;
91 tmp.st_blocks = (BLOCK_SIZE / 512) * blocks;
92 tmp.st_blksize = BLOCK_SIZE;
93 } else {
94 tmp.st_blocks = inode->i_blocks;
95 tmp.st_blksize = inode->i_blksize;
98 return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
101 asmlinkage int sys32_newstat(char * filename, struct stat32 *statbuf)
103 struct nameidata nd;
104 int error;
106 error = user_path_walk(filename, &nd);
107 if (!error) {
108 error = do_revalidate(nd.dentry);
109 if (!error)
110 error = cp_new_stat32(nd.dentry->d_inode, statbuf);
112 path_release(&nd);
115 return error;
118 asmlinkage int sys32_newlstat(char * filename, struct stat32 *statbuf)
120 struct nameidata nd;
121 int error;
123 error = user_path_walk_link(filename, &nd);
124 if (!error) {
125 error = do_revalidate(nd.dentry);
126 if (!error)
127 error = cp_new_stat32(nd.dentry->d_inode, statbuf);
129 path_release(&nd);
132 return error;
135 asmlinkage long sys32_newfstat(unsigned int fd, struct stat32 * statbuf)
137 struct file * f;
138 int err = -EBADF;
140 f = fget(fd);
141 if (f) {
142 struct dentry * dentry = f->f_dentry;
144 err = do_revalidate(dentry);
145 if (!err)
146 err = cp_new_stat32(dentry->d_inode, statbuf);
147 fput(f);
150 return err;
153 asmlinkage int sys_mmap2(void) {return 0;}
155 asmlinkage long sys_truncate(const char * path, unsigned long length);
157 asmlinkage int sys_truncate64(const char *path, unsigned int high,
158 unsigned int low)
160 if ((int)high < 0)
161 return -EINVAL;
162 return sys_truncate(path, ((long) high << 32) | low);
165 asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length);
167 asmlinkage int sys_ftruncate64(unsigned int fd, unsigned int high,
168 unsigned int low)
170 if ((int)high < 0)
171 return -EINVAL;
172 return sys_ftruncate(fd, ((long) high << 32) | low);
175 #if 0
177 * count32() counts the number of arguments/envelopes
179 static int count32(u32 * argv, int max)
181 int i = 0;
183 if (argv != NULL) {
184 for (;;) {
185 u32 p;
186 /* egcs is stupid */
187 if (!access_ok(VERIFY_READ, argv, sizeof (u32)))
188 return -EFAULT;
189 __get_user(p,argv);
190 if (!p)
191 break;
192 argv++;
193 if(++i > max)
194 return -E2BIG;
197 return i;
202 * 'copy_strings32()' copies argument/envelope strings from user
203 * memory to free pages in kernel mem. These are in a format ready
204 * to be put directly into the top of new user memory.
206 int copy_strings32(int argc, u32 * argv, struct linux_binprm *bprm)
208 while (argc-- > 0) {
209 u32 str;
210 int len;
211 unsigned long pos;
213 if (get_user(str, argv+argc) || !str ||
214 !(len = strnlen_user((char *)A(str), bprm->p)))
215 return -EFAULT;
216 if (bprm->p < len)
217 return -E2BIG;
219 bprm->p -= len;
220 /* XXX: add architecture specific overflow check here. */
222 pos = bprm->p;
223 while (len > 0) {
224 char *kaddr;
225 int i, new, err;
226 struct page *page;
227 int offset, bytes_to_copy;
229 offset = pos % PAGE_SIZE;
230 i = pos/PAGE_SIZE;
231 page = bprm->page[i];
232 new = 0;
233 if (!page) {
234 page = alloc_page(GFP_HIGHUSER);
235 bprm->page[i] = page;
236 if (!page)
237 return -ENOMEM;
238 new = 1;
240 kaddr = (char *)kmap(page);
242 if (new && offset)
243 memset(kaddr, 0, offset);
244 bytes_to_copy = PAGE_SIZE - offset;
245 if (bytes_to_copy > len) {
246 bytes_to_copy = len;
247 if (new)
248 memset(kaddr+offset+len, 0,
249 PAGE_SIZE-offset-len);
251 err = copy_from_user(kaddr + offset, (char *)A(str),
252 bytes_to_copy);
253 flush_page_to_ram(page);
254 kunmap(page);
256 if (err)
257 return -EFAULT;
259 pos += bytes_to_copy;
260 str += bytes_to_copy;
261 len -= bytes_to_copy;
264 return 0;
269 * sys_execve32() executes a new program.
271 int do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs)
273 struct linux_binprm bprm;
274 struct dentry * dentry;
275 int retval;
276 int i;
278 bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
279 memset(bprm.page, 0, MAX_ARG_PAGES*sizeof(bprm.page[0]));
281 dentry = open_namei(filename, 0, 0);
282 retval = PTR_ERR(dentry);
283 if (IS_ERR(dentry))
284 return retval;
286 bprm.dentry = dentry;
287 bprm.filename = filename;
288 bprm.sh_bang = 0;
289 bprm.loader = 0;
290 bprm.exec = 0;
291 if ((bprm.argc = count32(argv, bprm.p / sizeof(u32))) < 0) {
292 dput(dentry);
293 return bprm.argc;
296 if ((bprm.envc = count32(envp, bprm.p / sizeof(u32))) < 0) {
297 dput(dentry);
298 return bprm.envc;
301 retval = prepare_binprm(&bprm);
302 if (retval < 0)
303 goto out;
305 retval = copy_strings_kernel(1, &bprm.filename, &bprm);
306 if (retval < 0)
307 goto out;
309 bprm.exec = bprm.p;
310 retval = copy_strings32(bprm.envc, envp, &bprm);
311 if (retval < 0)
312 goto out;
314 retval = copy_strings32(bprm.argc, argv, &bprm);
315 if (retval < 0)
316 goto out;
318 retval = search_binary_handler(&bprm,regs);
319 if (retval >= 0)
320 /* execve success */
321 return retval;
323 out:
324 /* Something went wrong, return the inode and free the argument pages*/
325 if (bprm.dentry)
326 dput(bprm.dentry);
328 /* Assumes that free_page() can take a NULL argument. */
329 /* I hope this is ok for all architectures */
330 for (i = 0 ; i < MAX_ARG_PAGES ; i++)
331 if (bprm.page[i])
332 __free_page(bprm.page[i]);
334 return retval;
338 * sys_execve() executes a new program.
340 asmlinkage int sys32_execve(abi64_no_regargs, struct pt_regs regs)
342 int error;
343 char * filename;
345 filename = getname((char *) (long)regs.regs[4]);
346 printk("Executing: %s\n", filename);
347 error = PTR_ERR(filename);
348 if (IS_ERR(filename))
349 goto out;
350 error = do_execve32(filename, (u32 *) (long)regs.regs[5],
351 (u32 *) (long)regs.regs[6], &regs);
352 putname(filename);
354 out:
355 return error;
357 #else
358 static int
359 nargs(unsigned int arg, char **ap)
361 char *ptr;
362 int n;
364 n = 0;
365 do {
366 /* egcs is stupid */
367 if (!access_ok(VERIFY_READ, arg, sizeof (unsigned int)))
368 return -EFAULT;
369 __get_user((long)ptr,(int *)A(arg));
370 if (ap)
371 *ap++ = ptr;
372 arg += sizeof(unsigned int);
373 n++;
374 } while (ptr);
375 return(n - 1);
378 asmlinkage int
379 sys32_execve(abi64_no_regargs, struct pt_regs regs)
381 extern asmlinkage int sys_execve(abi64_no_regargs, struct pt_regs regs);
382 extern asmlinkage long sys_munmap(unsigned long addr, size_t len);
383 unsigned int argv = (unsigned int)regs.regs[5];
384 unsigned int envp = (unsigned int)regs.regs[6];
385 char **av, **ae;
386 int na, ne, r, len;
387 char * filename;
389 na = nargs(argv, NULL);
390 ne = nargs(envp, NULL);
391 len = (na + ne + 2) * sizeof(*av);
393 * kmalloc won't work because the `sys_exec' code will attempt
394 * to do a `get_user' on the arg list and `get_user' will fail
395 * on a kernel address (simplifies `get_user'). Instead we
396 * do an mmap to get a user address. Note that since a successful
397 * `execve' frees all current memory we only have to do an
398 * `munmap' if the `execve' failes.
400 down(&current->mm->mmap_sem);
401 av = (char **) do_mmap_pgoff(0, 0, len, PROT_READ | PROT_WRITE,
402 MAP_PRIVATE | MAP_ANONYMOUS, 0);
403 up(&current->mm->mmap_sem);
405 if (IS_ERR(av))
406 return((long) av);
407 ae = av + na + 1;
408 av[na] = (char *)0;
409 ae[ne] = (char *)0;
410 (void)nargs(argv, av);
411 (void)nargs(envp, ae);
412 filename = getname((char *) (long)regs.regs[4]);
413 r = PTR_ERR(filename);
414 if (IS_ERR(filename))
415 return(r);
417 r = do_execve(filename, av, ae, &regs);
418 putname(filename);
419 if (IS_ERR(r))
420 sys_munmap((unsigned long)av, len);
421 return(r);
423 #endif
425 struct dirent32 {
426 unsigned int d_ino;
427 unsigned int d_off;
428 unsigned short d_reclen;
429 char d_name[NAME_MAX + 1];
432 static void
433 xlate_dirent(void *dirent64, void *dirent32, long n)
435 long off;
436 struct dirent *dirp;
437 struct dirent32 *dirp32;
439 off = 0;
440 while (off < n) {
441 dirp = (struct dirent *)(dirent64 + off);
442 dirp32 = (struct dirent32 *)(dirent32 + off);
443 off += dirp->d_reclen;
444 dirp32->d_ino = dirp->d_ino;
445 dirp32->d_off = (unsigned int)dirp->d_off;
446 dirp32->d_reclen = dirp->d_reclen;
447 strncpy(dirp32->d_name, dirp->d_name, dirp->d_reclen - ((3 * 4) + 2));
449 return;
452 asmlinkage long sys_getdents(unsigned int fd, void * dirent, unsigned int count);
454 asmlinkage long
455 sys32_getdents(unsigned int fd, void * dirent32, unsigned int count)
457 long n;
458 void *dirent64;
460 dirent64 = (void *)((unsigned long)(dirent32 + (sizeof(long) - 1)) & ~(sizeof(long) - 1));
461 if ((n = sys_getdents(fd, dirent64, count - (dirent64 - dirent32))) < 0)
462 return(n);
463 xlate_dirent(dirent64, dirent32, n);
464 return(n);
467 asmlinkage int old_readdir(unsigned int fd, void * dirent, unsigned int count);
469 asmlinkage int
470 sys32_readdir(unsigned int fd, void * dirent32, unsigned int count)
472 int n;
473 struct dirent dirent64;
475 if ((n = old_readdir(fd, &dirent64, count)) < 0)
476 return(n);
477 xlate_dirent(&dirent64, dirent32, dirent64.d_reclen);
478 return(n);
481 struct timeval32
483 int tv_sec, tv_usec;
486 struct itimerval32
488 struct timeval32 it_interval;
489 struct timeval32 it_value;
492 struct rusage32 {
493 struct timeval32 ru_utime;
494 struct timeval32 ru_stime;
495 int ru_maxrss;
496 int ru_ixrss;
497 int ru_idrss;
498 int ru_isrss;
499 int ru_minflt;
500 int ru_majflt;
501 int ru_nswap;
502 int ru_inblock;
503 int ru_oublock;
504 int ru_msgsnd;
505 int ru_msgrcv;
506 int ru_nsignals;
507 int ru_nvcsw;
508 int ru_nivcsw;
511 static int
512 put_rusage (struct rusage32 *ru, struct rusage *r)
514 int err;
516 err = put_user (r->ru_utime.tv_sec, &ru->ru_utime.tv_sec);
517 err |= __put_user (r->ru_utime.tv_usec, &ru->ru_utime.tv_usec);
518 err |= __put_user (r->ru_stime.tv_sec, &ru->ru_stime.tv_sec);
519 err |= __put_user (r->ru_stime.tv_usec, &ru->ru_stime.tv_usec);
520 err |= __put_user (r->ru_maxrss, &ru->ru_maxrss);
521 err |= __put_user (r->ru_ixrss, &ru->ru_ixrss);
522 err |= __put_user (r->ru_idrss, &ru->ru_idrss);
523 err |= __put_user (r->ru_isrss, &ru->ru_isrss);
524 err |= __put_user (r->ru_minflt, &ru->ru_minflt);
525 err |= __put_user (r->ru_majflt, &ru->ru_majflt);
526 err |= __put_user (r->ru_nswap, &ru->ru_nswap);
527 err |= __put_user (r->ru_inblock, &ru->ru_inblock);
528 err |= __put_user (r->ru_oublock, &ru->ru_oublock);
529 err |= __put_user (r->ru_msgsnd, &ru->ru_msgsnd);
530 err |= __put_user (r->ru_msgrcv, &ru->ru_msgrcv);
531 err |= __put_user (r->ru_nsignals, &ru->ru_nsignals);
532 err |= __put_user (r->ru_nvcsw, &ru->ru_nvcsw);
533 err |= __put_user (r->ru_nivcsw, &ru->ru_nivcsw);
534 return err;
537 extern asmlinkage int sys_wait4(pid_t pid, unsigned int * stat_addr,
538 int options, struct rusage * ru);
540 asmlinkage int
541 sys32_wait4(__kernel_pid_t32 pid, unsigned int * stat_addr, int options,
542 struct rusage32 * ru)
544 if (!ru)
545 return sys_wait4(pid, stat_addr, options, NULL);
546 else {
547 struct rusage r;
548 int ret;
549 unsigned int status;
550 mm_segment_t old_fs = get_fs();
552 set_fs(KERNEL_DS);
553 ret = sys_wait4(pid, stat_addr ? &status : NULL, options, &r);
554 set_fs(old_fs);
555 if (put_rusage (ru, &r)) return -EFAULT;
556 if (stat_addr && put_user (status, stat_addr))
557 return -EFAULT;
558 return ret;
562 asmlinkage int
563 sys32_waitpid(__kernel_pid_t32 pid, unsigned int *stat_addr, int options)
565 return sys32_wait4(pid, stat_addr, options, NULL);
568 #define RLIM_INFINITY32 0x7fffffff
569 #define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x)
571 struct rlimit32 {
572 int rlim_cur;
573 int rlim_max;
576 extern asmlinkage int sys_old_getrlimit(unsigned int resource, struct rlimit *rlim);
578 asmlinkage int
579 sys32_getrlimit(unsigned int resource, struct rlimit32 *rlim)
581 struct rlimit r;
582 int ret;
583 mm_segment_t old_fs = get_fs ();
585 set_fs (KERNEL_DS);
586 ret = sys_old_getrlimit(resource, &r);
587 set_fs (old_fs);
588 if (!ret) {
589 ret = put_user (RESOURCE32(r.rlim_cur), &rlim->rlim_cur);
590 ret |= __put_user (RESOURCE32(r.rlim_max), &rlim->rlim_max);
592 return ret;
595 extern asmlinkage int sys_setrlimit(unsigned int resource, struct rlimit *rlim);
597 asmlinkage int
598 sys32_setrlimit(unsigned int resource, struct rlimit32 *rlim)
600 struct rlimit r;
601 int ret;
602 mm_segment_t old_fs = get_fs ();
604 if (resource >= RLIM_NLIMITS) return -EINVAL;
605 if (get_user (r.rlim_cur, &rlim->rlim_cur) ||
606 __get_user (r.rlim_max, &rlim->rlim_max))
607 return -EFAULT;
608 if (r.rlim_cur == RLIM_INFINITY32)
609 r.rlim_cur = RLIM_INFINITY;
610 if (r.rlim_max == RLIM_INFINITY32)
611 r.rlim_max = RLIM_INFINITY;
612 set_fs (KERNEL_DS);
613 ret = sys_setrlimit(resource, &r);
614 set_fs (old_fs);
615 return ret;
618 struct statfs32 {
619 int f_type;
620 int f_bsize;
621 int f_frsize;
622 int f_blocks;
623 int f_bfree;
624 int f_files;
625 int f_ffree;
626 int f_bavail;
627 __kernel_fsid_t32 f_fsid;
628 int f_namelen;
629 int f_spare[6];
632 static inline int
633 put_statfs (struct statfs32 *ubuf, struct statfs *kbuf)
635 int err;
637 err = put_user (kbuf->f_type, &ubuf->f_type);
638 err |= __put_user (kbuf->f_bsize, &ubuf->f_bsize);
639 err |= __put_user (kbuf->f_blocks, &ubuf->f_blocks);
640 err |= __put_user (kbuf->f_bfree, &ubuf->f_bfree);
641 err |= __put_user (kbuf->f_bavail, &ubuf->f_bavail);
642 err |= __put_user (kbuf->f_files, &ubuf->f_files);
643 err |= __put_user (kbuf->f_ffree, &ubuf->f_ffree);
644 err |= __put_user (kbuf->f_namelen, &ubuf->f_namelen);
645 err |= __put_user (kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]);
646 err |= __put_user (kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]);
647 return err;
650 extern asmlinkage int sys_statfs(const char * path, struct statfs * buf);
652 asmlinkage int
653 sys32_statfs(const char * path, struct statfs32 *buf)
655 int ret;
656 struct statfs s;
657 mm_segment_t old_fs = get_fs();
659 set_fs (KERNEL_DS);
660 ret = sys_statfs((const char *)path, &s);
661 set_fs (old_fs);
662 if (put_statfs(buf, &s))
663 return -EFAULT;
664 return ret;
667 extern asmlinkage int sys_fstatfs(unsigned int fd, struct statfs * buf);
669 asmlinkage int
670 sys32_fstatfs(unsigned int fd, struct statfs32 *buf)
672 int ret;
673 struct statfs s;
674 mm_segment_t old_fs = get_fs();
676 set_fs (KERNEL_DS);
677 ret = sys_fstatfs(fd, &s);
678 set_fs (old_fs);
679 if (put_statfs(buf, &s))
680 return -EFAULT;
681 return ret;
684 extern asmlinkage int
685 sys_getrusage(int who, struct rusage *ru);
687 asmlinkage int
688 sys32_getrusage(int who, struct rusage32 *ru)
690 struct rusage r;
691 int ret;
692 mm_segment_t old_fs = get_fs();
694 set_fs (KERNEL_DS);
695 ret = sys_getrusage(who, &r);
696 set_fs (old_fs);
697 if (put_rusage (ru, &r)) return -EFAULT;
698 return ret;
701 static inline long
702 get_tv32(struct timeval *o, struct timeval32 *i)
704 return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
705 (__get_user(o->tv_sec, &i->tv_sec) |
706 __get_user(o->tv_usec, &i->tv_usec)));
707 return ENOSYS;
710 static inline long
711 get_it32(struct itimerval *o, struct itimerval32 *i)
713 return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
714 (__get_user(o->it_interval.tv_sec, &i->it_interval.tv_sec) |
715 __get_user(o->it_interval.tv_usec, &i->it_interval.tv_usec) |
716 __get_user(o->it_value.tv_sec, &i->it_value.tv_sec) |
717 __get_user(o->it_value.tv_usec, &i->it_value.tv_usec)));
718 return ENOSYS;
721 static inline long
722 put_tv32(struct timeval32 *o, struct timeval *i)
724 return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
725 (__put_user(i->tv_sec, &o->tv_sec) |
726 __put_user(i->tv_usec, &o->tv_usec)));
729 static inline long
730 put_it32(struct itimerval32 *o, struct itimerval *i)
732 return (!access_ok(VERIFY_WRITE, i, sizeof(*i)) ||
733 (__put_user(i->it_interval.tv_sec, &o->it_interval.tv_sec) |
734 __put_user(i->it_interval.tv_usec, &o->it_interval.tv_usec) |
735 __put_user(i->it_value.tv_sec, &o->it_value.tv_sec) |
736 __put_user(i->it_value.tv_usec, &o->it_value.tv_usec)));
737 return ENOSYS;
740 extern int do_getitimer(int which, struct itimerval *value);
742 asmlinkage int
743 sys32_getitimer(int which, struct itimerval32 *it)
745 struct itimerval kit;
746 int error;
748 error = do_getitimer(which, &kit);
749 if (!error && put_it32(it, &kit))
750 error = -EFAULT;
752 return error;
755 extern int do_setitimer(int which, struct itimerval *, struct itimerval *);
758 asmlinkage int
759 sys32_setitimer(int which, struct itimerval32 *in, struct itimerval32 *out)
761 struct itimerval kin, kout;
762 int error;
764 if (in) {
765 if (get_it32(&kin, in))
766 return -EFAULT;
767 } else
768 memset(&kin, 0, sizeof(kin));
770 error = do_setitimer(which, &kin, out ? &kout : NULL);
771 if (error || !out)
772 return error;
773 if (put_it32(out, &kout))
774 return -EFAULT;
776 return 0;
779 asmlinkage unsigned long
780 sys32_alarm(unsigned int seconds)
782 struct itimerval it_new, it_old;
783 unsigned int oldalarm;
785 it_new.it_interval.tv_sec = it_new.it_interval.tv_usec = 0;
786 it_new.it_value.tv_sec = seconds;
787 it_new.it_value.tv_usec = 0;
788 do_setitimer(ITIMER_REAL, &it_new, &it_old);
789 oldalarm = it_old.it_value.tv_sec;
790 /* ehhh.. We can't return 0 if we have an alarm pending.. */
791 /* And we'd better return too much than too little anyway */
792 if (it_old.it_value.tv_usec)
793 oldalarm++;
794 return oldalarm;
797 /* Translations due to time_t size differences. Which affects all
798 sorts of things, like timeval and itimerval. */
801 extern struct timezone sys_tz;
802 extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz);
804 asmlinkage int
805 sys32_gettimeofday(struct timeval32 *tv, struct timezone *tz)
807 if (tv) {
808 struct timeval ktv;
809 do_gettimeofday(&ktv);
810 if (put_tv32(tv, &ktv))
811 return -EFAULT;
813 if (tz) {
814 if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
815 return -EFAULT;
817 return 0;
820 asmlinkage int
821 sys32_settimeofday(struct timeval32 *tv, struct timezone *tz)
823 struct timeval ktv;
824 struct timezone ktz;
826 if (tv) {
827 if (get_tv32(&ktv, tv))
828 return -EFAULT;
830 if (tz) {
831 if (copy_from_user(&ktz, tz, sizeof(ktz)))
832 return -EFAULT;
835 return do_sys_settimeofday(tv ? &ktv : NULL, tz ? &ktz : NULL);
838 extern asmlinkage long sys_llseek(unsigned int fd, unsigned long offset_high,
839 unsigned long offset_low, loff_t * result,
840 unsigned int origin);
842 extern asmlinkage int sys32_llseek(unsigned int fd, unsigned int offset_high,
843 unsigned int offset_low, loff_t * result,
844 unsigned int origin)
846 return sys_llseek(fd, offset_high, offset_low, result, origin);
849 struct iovec32 { unsigned int iov_base; int iov_len; };
851 typedef ssize_t (*IO_fn_t)(struct file *, char *, size_t, loff_t *);
853 static long
854 do_readv_writev32(int type, struct file *file, const struct iovec32 *vector,
855 u32 count)
857 unsigned long tot_len;
858 struct iovec iovstack[UIO_FASTIOV];
859 struct iovec *iov=iovstack, *ivp;
860 struct inode *inode;
861 long retval, i;
862 IO_fn_t fn;
864 /* First get the "struct iovec" from user memory and
865 * verify all the pointers
867 if (!count)
868 return 0;
869 if(verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count))
870 return -EFAULT;
871 if (count > UIO_MAXIOV)
872 return -EINVAL;
873 if (count > UIO_FASTIOV) {
874 iov = kmalloc(count*sizeof(struct iovec), GFP_KERNEL);
875 if (!iov)
876 return -ENOMEM;
879 tot_len = 0;
880 i = count;
881 ivp = iov;
882 while (i > 0) {
883 u32 len;
884 u32 buf;
886 __get_user(len, &vector->iov_len);
887 __get_user(buf, &vector->iov_base);
888 tot_len += len;
889 ivp->iov_base = (void *)A(buf);
890 ivp->iov_len = (__kernel_size_t) len;
891 vector++;
892 ivp++;
893 i--;
896 inode = file->f_dentry->d_inode;
897 /* VERIFY_WRITE actually means a read, as we write to user space */
898 retval = locks_verify_area((type == VERIFY_WRITE
899 ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE),
900 inode, file, file->f_pos, tot_len);
901 if (retval) {
902 if (iov != iovstack)
903 kfree(iov);
904 return retval;
907 /* Then do the actual IO. Note that sockets need to be handled
908 * specially as they have atomicity guarantees and can handle
909 * iovec's natively
911 if (inode->i_sock) {
912 int err;
913 err = sock_readv_writev(type, inode, file, iov, count, tot_len);
914 if (iov != iovstack)
915 kfree(iov);
916 return err;
919 if (!file->f_op) {
920 if (iov != iovstack)
921 kfree(iov);
922 return -EINVAL;
924 /* VERIFY_WRITE actually means a read, as we write to user space */
925 fn = file->f_op->read;
926 if (type == VERIFY_READ)
927 fn = (IO_fn_t) file->f_op->write;
928 ivp = iov;
929 while (count > 0) {
930 void * base;
931 int len, nr;
933 base = ivp->iov_base;
934 len = ivp->iov_len;
935 ivp++;
936 count--;
937 nr = fn(file, base, len, &file->f_pos);
938 if (nr < 0) {
939 if (retval)
940 break;
941 retval = nr;
942 break;
944 retval += nr;
945 if (nr != len)
946 break;
948 if (iov != iovstack)
949 kfree(iov);
951 return retval;
954 asmlinkage long
955 sys32_readv(int fd, struct iovec32 *vector, u32 count)
957 struct file *file;
958 ssize_t ret;
960 ret = -EBADF;
961 file = fget(fd);
962 if (!file)
963 goto bad_file;
964 if (file->f_op && (file->f_mode & FMODE_READ) &&
965 (file->f_op->readv || file->f_op->read))
966 ret = do_readv_writev32(VERIFY_WRITE, file, vector, count);
968 fput(file);
970 bad_file:
971 return ret;
974 asmlinkage long
975 sys32_writev(int fd, struct iovec32 *vector, u32 count)
977 struct file *file;
978 ssize_t ret;
980 ret = -EBADF;
981 file = fget(fd);
982 if(!file)
983 goto bad_file;
984 if (file->f_op && (file->f_mode & FMODE_WRITE) &&
985 (file->f_op->writev || file->f_op->write))
986 ret = do_readv_writev32(VERIFY_READ, file, vector, count);
987 fput(file);
989 bad_file:
990 return ret;
994 * Ooo, nasty. We need here to frob 32-bit unsigned longs to
995 * 64-bit unsigned longs.
998 static inline int
999 get_fd_set32(unsigned long n, unsigned long *fdset, u32 *ufdset)
1001 #ifdef __MIPSEB__
1002 if (ufdset) {
1003 unsigned long odd;
1005 if (verify_area(VERIFY_WRITE, ufdset, n*sizeof(u32)))
1006 return -EFAULT;
1008 odd = n & 1UL;
1009 n &= ~1UL;
1010 while (n) {
1011 unsigned long h, l;
1012 __get_user(l, ufdset);
1013 __get_user(h, ufdset+1);
1014 ufdset += 2;
1015 *fdset++ = h << 32 | l;
1016 n -= 2;
1018 if (odd)
1019 __get_user(*fdset, ufdset);
1020 } else {
1021 /* Tricky, must clear full unsigned long in the
1022 * kernel fdset at the end, this makes sure that
1023 * actually happens.
1025 memset(fdset, 0, ((n + 1) & ~1)*sizeof(u32));
1027 return 0;
1028 #else
1029 <<Bomb - little endian support must define this>>
1030 #endif
1033 static inline void
1034 set_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset)
1036 unsigned long odd;
1038 if (!ufdset)
1039 return;
1041 odd = n & 1UL;
1042 n &= ~1UL;
1043 while (n) {
1044 unsigned long h, l;
1045 l = *fdset++;
1046 h = l >> 32;
1047 __put_user(l, ufdset);
1048 __put_user(h, ufdset+1);
1049 ufdset += 2;
1050 n -= 2;
1052 if (odd)
1053 __put_user(*fdset, ufdset);
1057 * We can actually return ERESTARTSYS instead of EINTR, but I'd
1058 * like to be certain this leads to no problems. So I return
1059 * EINTR just for safety.
1061 * Update: ERESTARTSYS breaks at least the xview clock binary, so
1062 * I'm trying ERESTARTNOHAND which restart only when you want to.
1064 #define MAX_SELECT_SECONDS \
1065 ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
1067 asmlinkage int sys32_select(int n, u32 *inp, u32 *outp, u32 *exp, struct timeval32 *tvp)
1069 fd_set_bits fds;
1070 char *bits;
1071 unsigned long nn;
1072 long timeout;
1073 int ret, size;
1075 timeout = MAX_SCHEDULE_TIMEOUT;
1076 if (tvp) {
1077 time_t sec, usec;
1079 if ((ret = verify_area(VERIFY_READ, tvp, sizeof(*tvp)))
1080 || (ret = __get_user(sec, &tvp->tv_sec))
1081 || (ret = __get_user(usec, &tvp->tv_usec)))
1082 goto out_nofds;
1084 ret = -EINVAL;
1085 if(sec < 0 || usec < 0)
1086 goto out_nofds;
1088 if ((unsigned long) sec < MAX_SELECT_SECONDS) {
1089 timeout = (usec + 1000000/HZ - 1) / (1000000/HZ);
1090 timeout += sec * (unsigned long) HZ;
1094 ret = -EINVAL;
1095 if (n < 0)
1096 goto out_nofds;
1097 if (n > current->files->max_fdset)
1098 n = current->files->max_fdset;
1101 * We need 6 bitmaps (in/out/ex for both incoming and outgoing),
1102 * since we used fdset we need to allocate memory in units of
1103 * long-words.
1105 ret = -ENOMEM;
1106 size = FDS_BYTES(n);
1107 bits = kmalloc(6 * size, GFP_KERNEL);
1108 if (!bits)
1109 goto out_nofds;
1110 fds.in = (unsigned long *) bits;
1111 fds.out = (unsigned long *) (bits + size);
1112 fds.ex = (unsigned long *) (bits + 2*size);
1113 fds.res_in = (unsigned long *) (bits + 3*size);
1114 fds.res_out = (unsigned long *) (bits + 4*size);
1115 fds.res_ex = (unsigned long *) (bits + 5*size);
1117 nn = (n + 8*sizeof(u32) - 1) / (8*sizeof(u32));
1118 if ((ret = get_fd_set32(nn, fds.in, inp)) ||
1119 (ret = get_fd_set32(nn, fds.out, outp)) ||
1120 (ret = get_fd_set32(nn, fds.ex, exp)))
1121 goto out;
1122 zero_fd_set(n, fds.res_in);
1123 zero_fd_set(n, fds.res_out);
1124 zero_fd_set(n, fds.res_ex);
1126 ret = do_select(n, &fds, &timeout);
1128 if (tvp && !(current->personality & STICKY_TIMEOUTS)) {
1129 time_t sec = 0, usec = 0;
1130 if (timeout) {
1131 sec = timeout / HZ;
1132 usec = timeout % HZ;
1133 usec *= (1000000/HZ);
1135 put_user(sec, &tvp->tv_sec);
1136 put_user(usec, &tvp->tv_usec);
1139 if (ret < 0)
1140 goto out;
1141 if (!ret) {
1142 ret = -ERESTARTNOHAND;
1143 if (signal_pending(current))
1144 goto out;
1145 ret = 0;
1148 set_fd_set32(nn, inp, fds.res_in);
1149 set_fd_set32(nn, outp, fds.res_out);
1150 set_fd_set32(nn, exp, fds.res_ex);
1152 out:
1153 kfree(bits);
1154 out_nofds:
1155 return ret;
1160 struct timespec32 {
1161 int tv_sec;
1162 int tv_nsec;
1165 extern asmlinkage int sys_sched_rr_get_interval(pid_t pid,
1166 struct timespec *interval);
1168 asmlinkage int
1169 sys32_sched_rr_get_interval(__kernel_pid_t32 pid, struct timespec32 *interval)
1171 struct timespec t;
1172 int ret;
1173 mm_segment_t old_fs = get_fs ();
1175 set_fs (KERNEL_DS);
1176 ret = sys_sched_rr_get_interval(pid, &t);
1177 set_fs (old_fs);
1178 if (put_user (t.tv_sec, &interval->tv_sec) ||
1179 __put_user (t.tv_nsec, &interval->tv_nsec))
1180 return -EFAULT;
1181 return ret;
1185 extern asmlinkage int sys_nanosleep(struct timespec *rqtp,
1186 struct timespec *rmtp);
1188 asmlinkage int
1189 sys32_nanosleep(struct timespec32 *rqtp, struct timespec32 *rmtp)
1191 struct timespec t;
1192 int ret;
1193 mm_segment_t old_fs = get_fs ();
1195 if (get_user (t.tv_sec, &rqtp->tv_sec) ||
1196 __get_user (t.tv_nsec, &rqtp->tv_nsec))
1197 return -EFAULT;
1199 set_fs (KERNEL_DS);
1200 ret = sys_nanosleep(&t, rmtp ? &t : NULL);
1201 set_fs (old_fs);
1202 if (rmtp && ret == -EINTR) {
1203 if (__put_user (t.tv_sec, &rmtp->tv_sec) ||
1204 __put_user (t.tv_nsec, &rmtp->tv_nsec))
1205 return -EFAULT;
1207 return ret;
1210 struct tms32 {
1211 int tms_utime;
1212 int tms_stime;
1213 int tms_cutime;
1214 int tms_cstime;
1217 extern asmlinkage long sys_times(struct tms * tbuf);
1218 asmlinkage long sys32_times(struct tms32 *tbuf)
1220 struct tms t;
1221 long ret;
1222 mm_segment_t old_fs = get_fs();
1223 int err;
1225 set_fs(KERNEL_DS);
1226 ret = sys_times(tbuf ? &t : NULL);
1227 set_fs(old_fs);
1228 if (tbuf) {
1229 err = put_user (t.tms_utime, &tbuf->tms_utime);
1230 err |= __put_user (t.tms_stime, &tbuf->tms_stime);
1231 err |= __put_user (t.tms_cutime, &tbuf->tms_cutime);
1232 err |= __put_user (t.tms_cstime, &tbuf->tms_cstime);
1233 if (err)
1234 ret = -EFAULT;
1236 return ret;
1239 extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
1240 char *optval, int optlen);
1242 asmlinkage int sys32_setsockopt(int fd, int level, int optname,
1243 char *optval, int optlen)
1245 if (optname == SO_ATTACH_FILTER) {
1246 struct sock_fprog32 {
1247 __u16 len;
1248 __u32 filter;
1249 } *fprog32 = (struct sock_fprog32 *)optval;
1250 struct sock_fprog kfprog;
1251 struct sock_filter *kfilter;
1252 unsigned int fsize;
1253 mm_segment_t old_fs;
1254 __u32 uptr;
1255 int ret;
1257 if (get_user(kfprog.len, &fprog32->len) ||
1258 __get_user(uptr, &fprog32->filter))
1259 return -EFAULT;
1260 kfprog.filter = (struct sock_filter *)A(uptr);
1261 fsize = kfprog.len * sizeof(struct sock_filter);
1262 kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL);
1263 if (kfilter == NULL)
1264 return -ENOMEM;
1265 if (copy_from_user(kfilter, kfprog.filter, fsize)) {
1266 kfree(kfilter);
1267 return -EFAULT;
1269 kfprog.filter = kfilter;
1270 old_fs = get_fs();
1271 set_fs(KERNEL_DS);
1272 ret = sys_setsockopt(fd, level, optname,
1273 (char *)&kfprog, sizeof(kfprog));
1274 set_fs(old_fs);
1275 kfree(kfilter);
1276 return ret;
1278 return sys_setsockopt(fd, level, optname, optval, optlen);
1281 struct flock32 {
1282 short l_type;
1283 short l_whence;
1284 __kernel_off_t32 l_start;
1285 __kernel_off_t32 l_len;
1286 __kernel_pid_t32 l_pid;
1287 short __unused;
1290 static inline int get_flock(struct flock *kfl, struct flock32 *ufl)
1292 int err;
1294 err = get_user(kfl->l_type, &ufl->l_type);
1295 err |= __get_user(kfl->l_whence, &ufl->l_whence);
1296 err |= __get_user(kfl->l_start, &ufl->l_start);
1297 err |= __get_user(kfl->l_len, &ufl->l_len);
1298 err |= __get_user(kfl->l_pid, &ufl->l_pid);
1299 return err;
1302 static inline int put_flock(struct flock *kfl, struct flock32 *ufl)
1304 int err;
1306 err = __put_user(kfl->l_type, &ufl->l_type);
1307 err |= __put_user(kfl->l_whence, &ufl->l_whence);
1308 err |= __put_user(kfl->l_start, &ufl->l_start);
1309 err |= __put_user(kfl->l_len, &ufl->l_len);
1310 err |= __put_user(kfl->l_pid, &ufl->l_pid);
1311 return err;
1314 extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg);
1316 asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
1318 switch (cmd) {
1319 case F_GETLK:
1320 case F_SETLK:
1321 case F_SETLKW:
1323 struct flock f;
1324 mm_segment_t old_fs;
1325 long ret;
1327 if(get_flock(&f, (struct flock32 *)arg))
1328 return -EFAULT;
1329 old_fs = get_fs(); set_fs (KERNEL_DS);
1330 ret = sys_fcntl(fd, cmd, (unsigned long)&f);
1331 set_fs (old_fs);
1332 if(put_flock(&f, (struct flock32 *)arg))
1333 return -EFAULT;
1334 return ret;
1336 default:
1337 return sys_fcntl(fd, cmd, (unsigned long)arg);