📄 sys_sunos32.c
字号:
siginfo_t info; static int cnt; regs = current->thread.kregs; if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) { regs->tpc &= 0xffffffff; regs->tnpc &= 0xffffffff; } info.si_signo = SIGSYS; info.si_errno = 0; info.si_code = __SI_FAULT|0x100; info.si_addr = (void *)regs->tpc; info.si_trapno = regs->u_regs[UREG_G1]; send_sig_info(SIGSYS, &info, current); if (cnt++ < 4) { printk("Process makes ni_syscall number %d, register dump:\n", (int) regs->u_regs[UREG_G1]); show_regs(regs); } return -ENOSYS;}/* This is not a real and complete implementation yet, just to keep * the easy SunOS binaries happy. */asmlinkage int sunos_fpathconf(int fd, int name){ int ret; switch(name) { case _PCONF_LINK: ret = LINK_MAX; break; case _PCONF_CANON: ret = MAX_CANON; break; case _PCONF_INPUT: ret = MAX_INPUT; break; case _PCONF_NAME: ret = NAME_MAX; break; case _PCONF_PATH: ret = PATH_MAX; break; case _PCONF_PIPE: ret = PIPE_BUF; break; case _PCONF_CHRESTRICT: /* XXX Investigate XXX */ ret = 1; break; case _PCONF_NOTRUNC: /* XXX Investigate XXX */ case _PCONF_VDISABLE: ret = 0; break; default: ret = -EINVAL; break; } return ret;}asmlinkage int sunos_pathconf(u32 u_path, int name){ int ret; ret = sunos_fpathconf(0, name); /* XXX cheese XXX */ return ret;}/* SunOS mount system call emulation */extern asmlinkage intsys32_select(int n, u32 inp, u32 outp, u32 exp, u32 tvp);struct timeval32{ int tv_sec, tv_usec;};asmlinkage int sunos_select(int width, u32 inp, u32 outp, u32 exp, u32 tvp_x){ int ret; /* SunOS binaries expect that select won't change the tvp contents */ ret = sys32_select (width, inp, outp, exp, tvp_x); if (ret == -EINTR && tvp_x) { struct timeval32 *tvp = (struct timeval32 *)A(tvp_x); time_t sec, usec; __get_user(sec, &tvp->tv_sec); __get_user(usec, &tvp->tv_usec); if (sec == 0 && usec == 0) ret = 0; } return ret;}asmlinkage void sunos_nop(void){ return;}/* XXXXXXXXXX SunOS mount/umount. XXXXXXXXXXX */#define SMNT_RDONLY 1#define SMNT_NOSUID 2#define SMNT_NEWTYPE 4#define SMNT_GRPID 8#define SMNT_REMOUNT 16#define SMNT_NOSUB 32#define SMNT_MULTI 64#define SMNT_SYS5 128struct sunos_fh_t { char fh_data [NFS_FHSIZE];};struct sunos_nfs_mount_args { struct sockaddr_in *addr; /* file server address */ struct nfs_fh *fh; /* File handle to be mounted */ int flags; /* flags */ int wsize; /* write size in bytes */ int rsize; /* read size in bytes */ int timeo; /* initial timeout in .1 secs */ int retrans; /* times to retry send */ char *hostname; /* server's hostname */ int acregmin; /* attr cache file min secs */ int acregmax; /* attr cache file max secs */ int acdirmin; /* attr cache dir min secs */ int acdirmax; /* attr cache dir max secs */ char *netname; /* server's netname */};extern asmlinkage int sys_mount(char *, char *, char *, unsigned long, void *);extern asmlinkage int sys_connect(int fd, struct sockaddr *uservaddr, int addrlen);extern asmlinkage int sys_socket(int family, int type, int protocol);extern asmlinkage int sys_bind(int fd, struct sockaddr *umyaddr, int addrlen);/* 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. *//* XXXXXXXXXXXXXXXXXXXX */static intsunos_nfs_get_server_fd (int fd, struct sockaddr_in *addr){ struct sockaddr_in local; struct sockaddr_in server; int try_port; int ret; struct socket *socket; struct inode *inode; struct file *file; file = fget(fd); if(!file) return 0; inode = file->f_dentry->d_inode; socket = &inode->u.socket_i; local.sin_family = AF_INET; local.sin_addr.s_addr = INADDR_ANY; /* IPPORT_RESERVED = 1024, can't find the definition in the kernel */ try_port = 1024; do { local.sin_port = htons (--try_port); ret = socket->ops->bind(socket, (struct sockaddr*)&local, sizeof(local)); } while (ret && try_port > (1024 / 2)); if (ret) { fput(file); return 0; } server.sin_family = AF_INET; server.sin_addr = addr->sin_addr; server.sin_port = NFS_PORT; /* Call sys_connect */ ret = socket->ops->connect (socket, (struct sockaddr *) &server, sizeof (server), file->f_flags); fput(file); if (ret < 0) return 0; return 1;}/* XXXXXXXXXXXXXXXXXXXX */static int get_default (int value, int def_value){ if (value) return value; else return def_value;}/* XXXXXXXXXXXXXXXXXXXX */static int sunos_nfs_mount(char *dir_name, int linux_flags, void *data){ int server_fd; char *the_name; struct nfs_mount_data linux_nfs_mount; struct sunos_nfs_mount_args sunos_mount; /* Ok, here comes the fun part: Linux's nfs mount needs a * socket connection to the server, but SunOS mount does not * require this, so we use the information on the destination * address to create a socket and bind it to a reserved * port on this system */ if (copy_from_user(&sunos_mount, data, sizeof(sunos_mount))) return -EFAULT; server_fd = sys_socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (server_fd < 0) return -ENXIO; if (copy_from_user(&linux_nfs_mount.addr,sunos_mount.addr, sizeof(*sunos_mount.addr)) || copy_from_user(&linux_nfs_mount.root,sunos_mount.fh, sizeof(*sunos_mount.fh))) { sys_close (server_fd); return -EFAULT; } if (!sunos_nfs_get_server_fd (server_fd, &linux_nfs_mount.addr)){ sys_close (server_fd); return -ENXIO; } /* Now, bind it to a locally reserved port */ linux_nfs_mount.version = NFS_MOUNT_VERSION; linux_nfs_mount.flags = sunos_mount.flags; linux_nfs_mount.fd = server_fd; linux_nfs_mount.rsize = get_default (sunos_mount.rsize, 8192); linux_nfs_mount.wsize = get_default (sunos_mount.wsize, 8192); linux_nfs_mount.timeo = get_default (sunos_mount.timeo, 10); linux_nfs_mount.retrans = sunos_mount.retrans; linux_nfs_mount.acregmin = sunos_mount.acregmin; linux_nfs_mount.acregmax = sunos_mount.acregmax; linux_nfs_mount.acdirmin = sunos_mount.acdirmin; linux_nfs_mount.acdirmax = sunos_mount.acdirmax; the_name = getname(sunos_mount.hostname); if(IS_ERR(the_name)) return PTR_ERR(the_name); strncpy (linux_nfs_mount.hostname, the_name, 254); linux_nfs_mount.hostname [255] = 0; putname (the_name); return do_mount ("", dir_name, "nfs", linux_flags, &linux_nfs_mount);}/* XXXXXXXXXXXXXXXXXXXX */asmlinkage intsunos_mount(char *type, char *dir, int flags, void *data){ int linux_flags = 0; int ret = -EINVAL; char *dev_fname = 0; char *dir_page, *type_page; if (!capable (CAP_SYS_ADMIN)) return -EPERM; /* We don't handle the integer fs type */ if ((flags & SMNT_NEWTYPE) == 0) goto out; /* Do not allow for those flags we don't support */ if (flags & (SMNT_GRPID|SMNT_NOSUB|SMNT_MULTI|SMNT_SYS5)) goto out; if(flags & SMNT_REMOUNT) linux_flags |= MS_REMOUNT; if(flags & SMNT_RDONLY) linux_flags |= MS_RDONLY; if(flags & SMNT_NOSUID) linux_flags |= MS_NOSUID; dir_page = getname(dir); ret = PTR_ERR(dir_page); if (IS_ERR(dir_page)) goto out; type_page = getname(type); ret = PTR_ERR(type_page); if (IS_ERR(type_page)) goto out1; if(strcmp(type_page, "ext2") == 0) { dev_fname = getname(data); } else if(strcmp(type_page, "iso9660") == 0) { dev_fname = getname(data); } else if(strcmp(type_page, "minix") == 0) { dev_fname = getname(data); } else if(strcmp(type_page, "nfs") == 0) { ret = sunos_nfs_mount (dir_page, flags, data); goto out2; } else if(strcmp(type_page, "ufs") == 0) { printk("Warning: UFS filesystem mounts unsupported.\n"); ret = -ENODEV; goto out2; } else if(strcmp(type_page, "proc")) { ret = -ENODEV; goto out2; } ret = PTR_ERR(dev_fname); if (IS_ERR(dev_fname)) goto out2; lock_kernel(); ret = do_mount(dev_fname, dir_page, type_page, linux_flags, NULL); unlock_kernel(); if (dev_fname) putname(dev_fname);out2: putname(type_page);out1: putname(dir_page);out: return ret;}extern asmlinkage int sys_setsid(void);extern asmlinkage int sys_setpgid(pid_t, pid_t);asmlinkage int sunos_setpgrp(pid_t pid, pid_t pgid){ int ret; /* So stupid... */ if((!pid || pid == current->pid) && !pgid) { sys_setsid(); ret = 0; } else { ret = sys_setpgid(pid, pgid); } return ret;}/* So stupid... */extern asmlinkage int sys32_wait4(__kernel_pid_t32 pid, u32 stat_addr, int options, u32 ru);asmlinkage int sunos_wait4(__kernel_pid_t32 pid, u32 stat_addr, int options, u32 ru){ int ret; ret = sys32_wait4((pid ? pid : ((__kernel_pid_t32)-1)), stat_addr, options, ru); return ret;}extern int kill_pg(int, int, int);asmlinkage int sunos_killpg(int pgrp, int sig){ return kill_pg(pgrp, sig, 0);}asmlinkage int sunos_audit(void){ printk ("sys_audit\n"); return -1;}extern asmlinkage u32 sunos_gethostid(void){ u32 ret; ret = (((u32)idprom->id_machtype << 24) | ((u32)idprom->id_sernum)); return ret;}/* sysconf options, for SunOS compatibility */#define _SC_ARG_MAX 1#define _SC_CHILD_MAX 2#define _SC_CLK_TCK 3#define _SC_NGROUPS_MAX 4#define _SC_OPEN_MAX 5#define _SC_JOB_CONTROL 6#define _SC_SAVED_IDS 7#define _SC_VERSION 8extern asmlinkage s32 sunos_sysconf (int name){ s32 ret; switch (name){ case _SC_ARG_MAX: ret = ARG_MAX; break; case _SC_CHILD_MAX: ret = CHILD_MAX; break; case _SC_CLK_TCK: ret = HZ; break; case _SC_NGROUPS_MAX: ret = NGROUPS_MAX; break; case _SC_OPEN_MAX: ret = OPEN_MAX; break; case _SC_JOB_CONTROL: ret = 1; /* yes, we do support job control */ break; case _SC_SAVED_IDS: ret = 1; /* yes, we do support saved uids */ break; case _SC_VERSION: /* mhm, POSIX_VERSION is in /usr/include/unistd.h * should it go on /usr/include/linux? */ ret = 199009; break; default: ret = -1; break; }; return ret;}asmlinkage int sunos_semsys(int op, u32 arg1, u32 arg2, u32 arg3, u32 ptr){ union semun arg4; int ret; switch (op) { case 0: /* Most arguments match on a 1:1 basis but cmd doesn't */ switch(arg3) { case 4: arg3=GETPID; break; case 5: arg3=GETVAL; break; case 6: arg3=GETALL; break; case 3: arg3=GETNCNT; break; case 7: arg3=GETZCNT; break; case 8: arg3=SETVAL; break; case 9: arg3=SETALL; break; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -