patch-2.1.97 linux/arch/sparc64/kernel/sys_sparc32.c
Next file: linux/arch/sparc64/kernel/sys_sunos32.c
Previous file: linux/arch/sparc64/kernel/sys_sparc.c
Back to the patch index
Back to the overall index
- Lines: 385
- Date:
Tue Apr 14 17:44:21 1998
- Orig file:
v2.1.96/linux/arch/sparc64/kernel/sys_sparc32.c
- Orig date:
Mon Jan 12 15:15:44 1998
diff -u --recursive --new-file v2.1.96/linux/arch/sparc64/kernel/sys_sparc32.c linux/arch/sparc64/kernel/sys_sparc32.c
@@ -1,7 +1,7 @@
-/* $Id: sys_sparc32.c,v 1.71 1997/12/11 15:15:11 jj Exp $
+/* $Id: sys_sparc32.c,v 1.77 1998/03/29 10:10:50 davem Exp $
* sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
*
- * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
* Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
*
* These routines maintain argument size conversion between 32bit and 64bit
@@ -10,11 +10,12 @@
#include <linux/config.h>
#include <linux/kernel.h>
+#include <linux/sched.h>
#include <linux/fs.h>
+#include <linux/file.h>
#include <linux/signal.h>
#include <linux/utime.h>
#include <linux/resource.h>
-#include <linux/sched.h>
#include <linux/times.h>
#include <linux/utime.h>
#include <linux/utsname.h>
@@ -41,6 +42,7 @@
#include <linux/module.h>
#include <linux/poll.h>
#include <linux/personality.h>
+#include <linux/stat.h>
#include <asm/types.h>
#include <asm/ipc.h>
@@ -59,7 +61,6 @@
extern char * getname_quicklist;
extern int getname_quickcount;
extern struct semaphore getname_quicklock;
-extern int kerneld_msqid;
/* Tuning: increase locality by reusing same pages again...
* if getname_quicklist becomes too long on low memory machines, either a limit
@@ -324,19 +325,9 @@
if (!p) err = -ENOMEM;
else {
err = 0;
- if (first == kerneld_msqid) {
- *(int *)p->mtext = 0;
- if (get_user(p->mtype, &(((struct msgbuf32 *)A(ptr))->mtype)) ||
- __copy_from_user(&p->mtext[4], &(((struct msgbuf32 *)A(ptr))->mtext[0]), 4) ||
- __copy_from_user(&p->mtext[8], &(((struct msgbuf32 *)A(ptr))->mtext[4]), second-4))
- err = -EFAULT;
- else
- second += 4;
- } else {
- if (get_user(p->mtype, &(((struct msgbuf32 *)A(ptr))->mtype)) ||
- __copy_from_user(p->mtext, &(((struct msgbuf32 *)A(ptr))->mtext), second))
- err = -EFAULT;
- }
+ if (get_user(p->mtype, &(((struct msgbuf32 *)A(ptr))->mtype)) ||
+ __copy_from_user(p->mtext, &(((struct msgbuf32 *)A(ptr))->mtext), second))
+ err = -EFAULT;
if (!err) {
mm_segment_t old_fs = get_fs();
set_fs (KERNEL_DS);
@@ -379,18 +370,9 @@
if (err < 0)
goto out;
- if (first == kerneld_msqid) {
- if (put_user (p->mtype, &(((struct msgbuf32 *)A(ptr))->mtype)) ||
- __copy_to_user(&(((struct msgbuf32 *)A(ptr))->mtext[0]), &p->mtext[4], 4) ||
- __copy_to_user(&(((struct msgbuf32 *)A(ptr))->mtext[4]), &p->mtext[8], err-8))
- err = -EFAULT;
- else
- err -= 4;
- } else {
- if (put_user (p->mtype, &(((struct msgbuf32 *)A(ptr))->mtype)) ||
- __copy_to_user(&(((struct msgbuf32 *)A(ptr))->mtext), p->mtext, err))
- err = -EFAULT;
- }
+ if (put_user (p->mtype, &(((struct msgbuf32 *)A(ptr))->mtype)) ||
+ __copy_to_user(&(((struct msgbuf32 *)A(ptr))->mtext), p->mtext, err))
+ err = -EFAULT;
kfree (p);
goto out;
}
@@ -939,14 +921,12 @@
{
int error = -EBADF;
struct file * file;
+ struct inode * inode;
struct readdir_callback32 buf;
lock_kernel();
- if(fd >= NR_OPEN)
- goto out;
-
- file = current->files->fd[fd];
- if(!file)
+ file = fget(fd);
+ if (!file)
goto out;
buf.count = 0;
@@ -954,12 +934,18 @@
error = -ENOTDIR;
if (!file->f_op || !file->f_op->readdir)
- goto out;
-
+ goto out_putf;
+
+ inode = file->f_dentry->d_inode;
+ down(&inode->i_sem);
error = file->f_op->readdir(file, &buf, fillonedir);
+ up(&inode->i_sem);
if (error < 0)
- goto out;
+ goto out_putf;
error = buf.count;
+
+out_putf:
+ fput(file);
out:
unlock_kernel();
return error;
@@ -1006,16 +992,14 @@
asmlinkage int sys32_getdents(unsigned int fd, u32 dirent, unsigned int count)
{
struct file * file;
+ struct inode * inode;
struct linux_dirent32 * lastdirent;
struct getdents_callback32 buf;
int error = -EBADF;
lock_kernel();
- if(fd >= NR_OPEN)
- goto out;
-
- file = current->files->fd[fd];
- if(!file)
+ file = fget(fd);
+ if (!file)
goto out;
buf.current_dir = (struct linux_dirent32 *) A(dirent);
@@ -1025,17 +1009,22 @@
error = -ENOTDIR;
if (!file->f_op || !file->f_op->readdir)
- goto out;
+ goto out_putf;
+ inode = file->f_dentry->d_inode;
+ down(&inode->i_sem);
error = file->f_op->readdir(file, &buf, filldir);
+ up(&inode->i_sem);
if (error < 0)
- goto out;
+ goto out_putf;
lastdirent = buf.previous;
error = buf.error;
if(lastdirent) {
put_user(file->f_pos, &lastdirent->d_off);
error = count - buf.count;
}
+out_putf:
+ fput(file);
out:
unlock_kernel();
return error;
@@ -1258,6 +1247,27 @@
return ret;
}
+extern asmlinkage int sys_xstat(int ver, char *filename, struct stat64 * statbuf);
+
+asmlinkage int sys32_xstat(int ver, u32 file, u32 statbuf)
+{
+ switch (ver & __XSTAT_VER_MASK) {
+ case __XSTAT_VER_1:
+ switch (ver & __XSTAT_VER_TYPEMASK) {
+ case __XSTAT_VER_XSTAT:
+ return sys32_newstat(file, statbuf);
+ case __XSTAT_VER_LXSTAT:
+ return sys32_newlstat(file, statbuf);
+ case __XSTAT_VER_FXSTAT:
+ return sys32_newfstat(file, statbuf);
+ }
+ return -EINVAL;
+ case __XSTAT_VER_2:
+ return sys_xstat(ver, (char *)A(file), (struct stat64 *)A(statbuf));
+ }
+ return -EINVAL;
+}
+
extern asmlinkage int sys_sysfs(int option, unsigned long arg1, unsigned long arg2);
asmlinkage int sys32_sysfs(int option, u32 arg1, u32 arg2)
@@ -2222,18 +2232,19 @@
char address[MAX_SOCK_ADDR];
struct iovec iov[UIO_FASTIOV];
unsigned char ctl[sizeof(struct cmsghdr) + 20];
- struct msghdr kern_msg;
- int err;
- int total_len;
unsigned char *ctl_buf = ctl;
+ struct msghdr kern_msg;
+ int err, total_len;
if(msghdr_from_user32_to_kern(&kern_msg, (struct msghdr32 *)A(user_msg)))
return -EFAULT;
if(kern_msg.msg_iovlen > UIO_MAXIOV)
return -EINVAL;
- total_len = verify_iovec32(&kern_msg, iov, address, VERIFY_READ);
- if(total_len < 0)
- return total_len;
+ err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ);
+ if (err < 0)
+ goto out;
+ total_len = err;
+
if(kern_msg.msg_controllen) {
struct cmsghdr32 *ucmsg = (struct cmsghdr32 *)kern_msg.msg_control;
unsigned long *kcmsg;
@@ -2241,41 +2252,40 @@
if(kern_msg.msg_controllen > sizeof(ctl) &&
kern_msg.msg_controllen <= 256) {
+ err = -ENOBUFS;
ctl_buf = kmalloc(kern_msg.msg_controllen, GFP_KERNEL);
- if(!ctl_buf) {
- if(kern_msg.msg_iov != iov)
- kfree(kern_msg.msg_iov);
- return -ENOBUFS;
- }
+ if(!ctl_buf)
+ goto out_freeiov;
}
__get_user(cmlen, &ucmsg->cmsg_len);
kcmsg = (unsigned long *) ctl_buf;
*kcmsg++ = (unsigned long)cmlen;
+ err = -EFAULT;
if(copy_from_user(kcmsg, &ucmsg->cmsg_level,
- kern_msg.msg_controllen - sizeof(__kernel_size_t32))) {
- if(ctl_buf != ctl)
- kfree_s(ctl_buf, kern_msg.msg_controllen);
- if(kern_msg.msg_iov != iov)
- kfree(kern_msg.msg_iov);
- return -EFAULT;
- }
+ kern_msg.msg_controllen - sizeof(__kernel_size_t32)))
+ goto out_freectl;
kern_msg.msg_control = ctl_buf;
}
kern_msg.msg_flags = user_flags;
lock_kernel();
- if(current->files->fd[fd]->f_flags & O_NONBLOCK)
- kern_msg.msg_flags |= MSG_DONTWAIT;
- if((sock = sockfd_lookup(fd, &err)) != NULL) {
+ sock = sockfd_lookup(fd, &err);
+ if (sock != NULL) {
+ if (sock->file->f_flags & O_NONBLOCK)
+ kern_msg.msg_flags |= MSG_DONTWAIT;
err = sock_sendmsg(sock, &kern_msg, total_len);
sockfd_put(sock);
}
unlock_kernel();
+out_freectl:
+ /* N.B. Use kfree here, as kern_msg.msg_controllen might change? */
if(ctl_buf != ctl)
- kfree_s(ctl_buf, kern_msg.msg_controllen);
+ kfree(ctl_buf);
+out_freeiov:
if(kern_msg.msg_iov != iov)
kfree(kern_msg.msg_iov);
+out:
return err;
}
@@ -2299,17 +2309,18 @@
uaddr = kern_msg.msg_name;
uaddr_len = &((struct msghdr32 *)A(user_msg))->msg_namelen;
err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE);
- if(err < 0)
- return err;
+ if (err < 0)
+ goto out;
total_len = err;
cmsg_ptr = (unsigned long) kern_msg.msg_control;
kern_msg.msg_flags = 0;
lock_kernel();
- if(current->files->fd[fd]->f_flags & O_NONBLOCK)
- user_flags |= MSG_DONTWAIT;
- if((sock = sockfd_lookup(fd, &err)) != NULL) {
+ sock = sockfd_lookup(fd, &err);
+ if (sock != NULL) {
+ if (sock->file->f_flags & O_NONBLOCK)
+ user_flags |= MSG_DONTWAIT;
err = sock_recvmsg(sock, &kern_msg, total_len, user_flags);
if(err >= 0)
len = err;
@@ -2317,8 +2328,6 @@
}
unlock_kernel();
- if(kern_msg.msg_iov != iov)
- kfree(kern_msg.msg_iov);
if(uaddr != NULL && err >= 0)
err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len);
if(err >= 0) {
@@ -2330,6 +2339,10 @@
&((struct msghdr32 *)A(user_msg))->msg_controllen);
}
}
+
+ if(kern_msg.msg_iov != iov)
+ kfree(kern_msg.msg_iov);
+out:
if(err < 0)
return err;
return len;
@@ -2838,25 +2851,25 @@
#else /* CONFIG_MODULES */
asmlinkage unsigned long
-sys_create_module(const char *name_user, size_t size)
+sys32_create_module(const char *name_user, size_t size)
{
return -ENOSYS;
}
asmlinkage int
-sys_init_module(const char *name_user, struct module *mod_user)
+sys32_init_module(const char *name_user, struct module *mod_user)
{
return -ENOSYS;
}
asmlinkage int
-sys_delete_module(const char *name_user)
+sys32_delete_module(const char *name_user)
{
return -ENOSYS;
}
asmlinkage int
-sys_query_module(const char *name_user, int which, char *buf, size_t bufsize,
+sys32_query_module(const char *name_user, int which, char *buf, size_t bufsize,
size_t *ret)
{
/* Let the program know about the new interface. Not that
@@ -2868,7 +2881,7 @@
}
asmlinkage int
-sys_get_kernel_syms(struct kernel_sym *table)
+sys32_get_kernel_syms(struct kernel_sym *table)
{
return -ENOSYS;
}
@@ -3326,4 +3339,20 @@
__kernel_size_t32 count, u32 pos)
{
return sys_pwrite(fd, (char *) A(ubuf), count, pos);
+}
+
+
+extern asmlinkage int sys_personality(unsigned long);
+
+asmlinkage int sys32_personality(unsigned long personality)
+{
+ int ret;
+ lock_kernel();
+ if (current->personality == PER_LINUX32 && personality == PER_LINUX)
+ personality = PER_LINUX32;
+ ret = sys_personality(personality);
+ unlock_kernel();
+ if (ret == PER_LINUX32)
+ ret = PER_LINUX;
+ return ret;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov