1 /* 2 * Copyright (c) 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This software was developed by the Computer Systems Engineering group 6 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 7 * contributed to Berkeley. 8 * 9 * %sccs.include.redist.c% 10 * 11 * @(#)news_compat.c 8.1 (Berkeley) 06/11/93 12 * 13 * from: $Hdr: sun_misc.c,v 1.12 92/07/12 13:26:10 torek Exp $ 14 */ 15 16 /* 17 * NEWS-OS compatibility module. 18 * 19 * NEWS-OS system calls that are implemented differently in BSD are 20 * handled here. 21 */ 22 23 #include <sys/param.h> 24 #include <sys/systm.h> 25 #include <sys/proc.h> 26 #include <sys/file.h> 27 #include <sys/filedesc.h> 28 #include <sys/ioctl.h> 29 #include <sys/malloc.h> 30 #include <sys/mbuf.h> 31 #include <sys/mman.h> 32 #include <sys/mount.h> 33 #include <sys/resource.h> 34 #include <sys/resourcevar.h> 35 #include <sys/signal.h> 36 #include <sys/signalvar.h> 37 #include <sys/socket.h> 38 #include <sys/vnode.h> 39 #include <sys/uio.h> 40 #include <sys/wait.h> 41 42 #include <miscfs/specfs/specdev.h> 43 44 #include <vm/vm.h> 45 46 #if 0 47 /* here is the sun layout (not used directly): */ 48 struct sun_dirent { 49 long d_off; 50 u_long d_fileno; 51 u_short d_reclen; 52 u_short d_namlen; 53 char d_name[256]; 54 }; 55 #endif 56 /* and the BSD layout: */ 57 struct bsd_dirent { 58 u_long d_fileno; 59 u_short d_reclen; 60 u_short d_namlen; 61 char d_name[256]; 62 }; 63 64 /* 65 * Read Sun-style directory entries. We suck them into kernel space so 66 * that they can be massaged before being copied out to user code. Like 67 * SunOS, we squish out `empty' entries. 68 * 69 * This is quite ugly, but what do you expect from compatibility code? 70 */ 71 struct sun_getdents_args { 72 int fd; 73 char *buf; 74 int nbytes; 75 }; 76 sun_getdents(p, uap, retval) 77 struct proc *p; 78 register struct sun_getdents_args *uap; 79 int *retval; 80 { 81 register struct vnode *vp; 82 register caddr_t inp, buf; /* BSD-format */ 83 register int len, reclen; /* BSD-format */ 84 register caddr_t outp; /* Sun-format */ 85 register int resid; /* Sun-format */ 86 struct file *fp; 87 struct uio auio; 88 struct iovec aiov; 89 off_t off; /* true file offset */ 90 long soff; /* Sun file offset */ 91 int buflen, error, eofflag; 92 #define SUN_RECLEN(reclen) (reclen + sizeof(long)) 93 94 if ((error = getvnode(p->p_fd, uap->fd, &fp)) != 0) 95 return (error); 96 if ((fp->f_flag & FREAD) == 0) 97 return (EBADF); 98 vp = (struct vnode *)fp->f_data; 99 if (vp->v_type != VDIR) /* XXX vnode readdir op should do this */ 100 return (EINVAL); 101 buflen = min(MAXBSIZE, uap->nbytes); 102 buf = malloc(buflen, M_TEMP, M_WAITOK); 103 VOP_LOCK(vp); 104 off = fp->f_offset; 105 again: 106 aiov.iov_base = buf; 107 aiov.iov_len = buflen; 108 auio.uio_iov = &aiov; 109 auio.uio_iovcnt = 1; 110 auio.uio_rw = UIO_READ; 111 auio.uio_segflg = UIO_SYSSPACE; 112 auio.uio_procp = p; 113 auio.uio_resid = buflen; 114 auio.uio_offset = off; 115 /* 116 * First we read into the malloc'ed buffer, then 117 * we massage it into user space, one record at a time. 118 */ 119 if (error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag)) 120 goto out; 121 inp = buf; 122 outp = uap->buf; 123 resid = uap->nbytes; 124 if ((len = buflen - auio.uio_resid) == 0) 125 goto eof; 126 for (; len > 0; len -= reclen) { 127 reclen = ((struct bsd_dirent *)inp)->d_reclen; 128 if (reclen & 3) 129 panic("sun_getdents"); 130 off += reclen; /* each entry points to next */ 131 if (((struct bsd_dirent *)inp)->d_fileno == 0) { 132 inp += reclen; /* it is a hole; squish it out */ 133 continue; 134 } 135 if (reclen > len || resid < SUN_RECLEN(reclen)) { 136 /* entry too big for buffer, so just stop */ 137 outp++; 138 break; 139 } 140 /* copy out a Sun-shaped dirent */ 141 ((struct bsd_dirent *)inp)->d_reclen = SUN_RECLEN(reclen); 142 soff = off; 143 if ((error = copyout((caddr_t)&soff, outp, sizeof soff)) != 0 || 144 (error = copyout(inp, outp + sizeof soff, reclen)) != 0) 145 goto out; 146 /* advance past this real entry */ 147 inp += reclen; 148 /* advance output past Sun-shaped entry */ 149 outp += SUN_RECLEN(reclen); 150 resid -= SUN_RECLEN(reclen); 151 } 152 /* if we squished out the whole block, try again */ 153 if (outp == uap->buf) 154 goto again; 155 fp->f_offset = off; /* update the vnode offset */ 156 eof: 157 *retval = uap->nbytes - resid; 158 out: 159 VOP_UNLOCK(vp); 160 free(buf, M_TEMP); 161 return (error); 162 } 163 164 #define MAXDOMAINNAME 64 165 char sun_domainname[MAXDOMAINNAME]; 166 int sun_domainnamelen = 1; 167 168 struct sun_getdomainname_args { 169 char *name; 170 int namelen; 171 }; 172 sun_getdomainname(p, uap, retval) 173 struct proc *p; 174 struct sun_getdomainname_args *uap; 175 int *retval; 176 { 177 register int l = min(uap->namelen, sun_domainnamelen + 1); 178 179 return (copyout(sun_domainname, uap->name, l)); 180 } 181 182 struct sun_setdomainname_args { 183 char *name; 184 int namelen; 185 }; 186 sun_setdomainname(p, uap, retval) 187 struct proc *p; 188 struct sun_setdomainname_args *uap; 189 int *retval; 190 { 191 register int l = uap->namelen, error; 192 193 if (l >= MAXDOMAINNAME) 194 return (EINVAL); /* ??? ENAMETOOLONG? */ 195 if (error = suser(p->p_ucred, &p->p_acflag)) 196 return (error); 197 if (error = copyin(uap->name, sun_domainname, l)) 198 return (error); 199 sun_domainname[l] = 0; 200 return (0); 201 } 202 203 /* 204 * setenvp system call 205 */ 206 struct news_setenvp_args { 207 char **envp; 208 }; 209 news_setenvp(p, args, retval) 210 struct proc *p; 211 struct news_setenvp_args *args; 212 int *retval; 213 { 214 215 return (0); 216 } 217 218 /* 219 * sysnews system call 220 */ 221 struct news_sysnews_args { 222 int ctrltype; 223 int arg1, arg2, arg3, arg4; 224 }; 225 news_sysnews(p, args, retval) 226 struct proc *p; 227 struct news_sysnews_args *args; 228 int *retval; 229 { 230 231 return (0); 232 } 233