patch-2.1.97 linux/arch/sparc/kernel/sys_sunos.c
Next file: linux/arch/sparc/kernel/systbls.S
Previous file: linux/arch/sparc/kernel/sys_sparc.c
Back to the patch index
Back to the overall index
- Lines: 318
- Date:
Tue Apr 14 17:44:19 1998
- Orig file:
v2.1.96/linux/arch/sparc/kernel/sys_sunos.c
- Orig date:
Mon Jan 12 15:15:43 1998
diff -u --recursive --new-file v2.1.96/linux/arch/sparc/kernel/sys_sunos.c linux/arch/sparc/kernel/sys_sunos.c
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos.c,v 1.83 1997/12/14 23:24:28 ecd Exp $
+/* $Id: sys_sunos.c,v 1.87 1998/03/29 03:48:16 shadow Exp $
* sys_sunos.c: SunOS specific syscall compatibility support.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -17,6 +17,7 @@
#include <linux/mm.h>
#include <linux/swap.h>
#include <linux/fs.h>
+#include <linux/file.h>
#include <linux/resource.h>
#include <linux/ipc.h>
#include <linux/shm.h>
@@ -77,14 +78,19 @@
flags &= ~MAP_NORESERVE;
}
retval = -EBADF;
- if(!(flags & MAP_ANONYMOUS))
- if (fd >= SUNOS_NR_OPEN || !(file = current->files->fd[fd]))
+ if(!(flags & MAP_ANONYMOUS)) {
+ if (fd >= SUNOS_NR_OPEN)
goto out;
+ file = fget(fd);
+ if (!file)
+ goto out;
+ }
+
retval = -ENOMEM;
if(!(flags & MAP_FIXED) && !addr) {
addr = get_unmapped_area(addr, len);
if(!addr)
- goto out;
+ goto out_putf;
}
/* If this is ld.so or a shared library doing an mmap
* of /dev/zero, transform it into an anonymous mapping.
@@ -105,18 +111,22 @@
/* See asm-sparc/uaccess.h */
retval = -EINVAL;
if((len > (TASK_SIZE - PAGE_SIZE)) || (addr > (TASK_SIZE-len-PAGE_SIZE)))
- goto out;
+ goto out_putf;
- if(sparc_cpu_model == sun4c) {
+ if(ARCH_SUN4C_SUN4) {
if(((addr >= 0x20000000) && (addr < 0xe0000000))) {
retval = current->mm->brk;
- goto out;
+ goto out_putf;
}
}
retval = do_mmap(file, addr, len, prot, flags, off);
if(!ret_type)
retval = ((retval < PAGE_OFFSET) ? 0 : retval);
+
+out_putf:
+ if (file)
+ fput(file);
out:
unlock_kernel();
return retval;
@@ -139,7 +149,7 @@
unsigned long newbrk, oldbrk;
lock_kernel();
- if(sparc_cpu_model == sun4c) {
+ if(ARCH_SUN4C_SUN4) {
if(brk >= 0x20000000 && brk < 0xe0000000) {
goto out;
}
@@ -423,39 +433,48 @@
asmlinkage int sunos_getdents(unsigned int fd, void * dirent, int cnt)
{
struct file * file;
+ struct inode * inode;
struct sunos_dirent * lastdirent;
struct sunos_dirent_callback buf;
int error = -EBADF;
lock_kernel();
- if(fd >= SUNOS_NR_OPEN)
+ if (fd >= SUNOS_NR_OPEN)
goto out;
- file = current->files->fd[fd];
- if(!file)
+ file = fget(fd);
+ if (!file)
goto out;
error = -ENOTDIR;
if (!file->f_op || !file->f_op->readdir)
- goto out;
+ goto out_putf;
error = -EINVAL;
- if(cnt < (sizeof(struct sunos_dirent) + 255))
- goto out;
+ if (cnt < (sizeof(struct sunos_dirent) + 255))
+ goto out_putf;
buf.curr = (struct sunos_dirent *) dirent;
buf.previous = NULL;
buf.count = cnt;
buf.error = 0;
+
+ inode = file->f_dentry->d_inode;
+ down(&inode->i_sem);
error = file->f_op->readdir(file, &buf, sunos_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 = cnt - buf.count;
}
+
+out_putf:
+ fput(file);
out:
unlock_kernel();
return error;
@@ -503,39 +522,48 @@
asmlinkage int sunos_getdirentries(unsigned int fd, void * dirent, int cnt, unsigned int *basep)
{
struct file * file;
+ struct inode * inode;
struct sunos_direntry * lastdirent;
struct sunos_direntry_callback buf;
int error = -EBADF;
lock_kernel();
- if(fd >= SUNOS_NR_OPEN)
+ if (fd >= SUNOS_NR_OPEN)
goto out;
- file = current->files->fd[fd];
- if(!file)
+ file = fget(fd);
+ if (!file)
goto out;
error = -ENOTDIR;
if (!file->f_op || !file->f_op->readdir)
- goto out;
+ goto out_putf;
error = -EINVAL;
if(cnt < (sizeof(struct sunos_direntry) + 255))
- goto out;
+ goto out_putf;
buf.curr = (struct sunos_direntry *) dirent;
buf.previous = NULL;
buf.count = cnt;
buf.error = 0;
+
+ inode = file->f_dentry->d_inode;
+ down(&inode->i_sem);
error = file->f_op->readdir(file, &buf, sunos_filldirentry);
+ 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, basep);
error = cnt - buf.count;
}
+
+out_putf:
+ fput(file);
out:
unlock_kernel();
return error;
@@ -669,6 +697,15 @@
lock_kernel();
current->personality |= STICKY_TIMEOUTS;
ret = sys_select (width, inp, outp, exp, tvp);
+ if (ret == -EINTR && tvp) {
+ time_t sec, usec;
+
+ __get_user(sec, &tvp->tv_sec);
+ __get_user(usec, &tvp->tv_usec);
+
+ if (sec == 0 && usec == 0)
+ ret = 0;
+ }
unlock_kernel();
return ret;
}
@@ -720,7 +757,7 @@
/* Bind the socket on a local reserved port and connect it to the
* remote server. This on Linux/i386 is done by the mount program,
- * not by the kernel.
+ * not by the kernel.
*/
static int
sunos_nfs_get_server_fd (int fd, struct sockaddr_in *addr)
@@ -728,16 +765,16 @@
struct sockaddr_in local;
struct sockaddr_in server;
int try_port;
- int ret;
struct socket *socket;
- struct dentry *dentry;
struct inode *inode;
struct file *file;
+ int ret, result = 0;
- file = current->files->fd [fd];
- dentry = file->f_dentry;
- if(!dentry || !(inode = dentry->d_inode))
- return 0;
+ file = fget(fd);
+ if (!file)
+ goto out;
+ if (!file->f_dentry || !(inode = file->f_dentry->d_inode))
+ goto out_putf;
socket = &inode->u.socket_i;
local.sin_family = AF_INET;
@@ -752,7 +789,7 @@
} while (ret && try_port > (1024 / 2));
if (ret)
- return 0;
+ goto out_putf;
server.sin_family = AF_INET;
server.sin_addr = addr->sin_addr;
@@ -761,9 +798,13 @@
/* Call sys_connect */
ret = socket->ops->connect (socket, (struct sockaddr *) &server,
sizeof (server), file->f_flags);
- if (ret < 0)
- return 0;
- return 1;
+ if (ret >= 0)
+ result = 1;
+
+out_putf:
+ fput(file);
+out:
+ return result;
}
static int get_default (int value, int def_value)
@@ -1139,10 +1180,13 @@
file descriptors that have been set non-blocking
using 4.2BSD style calls. (tridge) */
-static inline int check_nonblock(int ret,int fd)
+static inline int check_nonblock(int ret, int fd)
{
- if (ret == -EAGAIN && (current->files->fd[fd]->f_flags & O_NDELAY))
- return -SUNOS_EWOULDBLOCK;
+ if (ret == -EAGAIN) {
+ struct file * file = fcheck(fd);
+ if (file && (file->f_flags & O_NDELAY))
+ ret = -SUNOS_EWOULDBLOCK;
+ }
return ret;
}
@@ -1215,12 +1259,41 @@
return ret;
}
+extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
+ char *optval, int optlen);
+
+asmlinkage int sunos_socket(int family, int type, int protocol)
+{
+ int ret, one = 1;
+
+ lock_kernel();
+ ret = sys_socket(family, type, protocol);
+ if (ret < 0)
+ goto out;
+
+ sys_setsockopt(ret, SOL_SOCKET, SO_BSDCOMPAT,
+ (char *)&one, sizeof(one));
+out:
+ unlock_kernel();
+ return ret;
+}
+
asmlinkage int sunos_accept(int fd, struct sockaddr *sa, int *addrlen)
{
- int ret;
+ int ret, one = 1;
lock_kernel();
- ret = check_nonblock(sys_accept(fd,sa,addrlen),fd);
+ while (1) {
+ ret = check_nonblock(sys_accept(fd,sa,addrlen),fd);
+ if (ret != -ENETUNREACH && ret != -EHOSTUNREACH)
+ break;
+ }
+ if (ret < 0)
+ goto out;
+
+ sys_setsockopt(ret, SOL_SOCKET, SO_BSDCOMPAT,
+ (char *)&one, sizeof(one));
+out:
unlock_kernel();
return ret;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov