- register struct file *fp;
- register struct inode *from;
- register struct inode *to;
- off_t offset;
- dev_t dev;
- int rw;
- struct a {
- int device; /* actually dev_t */
- int inum; /* actually ino_t */
- int fd;
- } *uap;
-
- if (!suser()) {
- u.u_error = EPERM;
- return;
- }
- uap = (struct a *) u.u_ap;
- fp = getf(uap->fd);
- if (fp == NULL) {
- u.u_error = EBADF;
- return;
- }
- if (fp->f_type == DTYPE_SOCKET) {
- u.u_error = EINVAL;
- return;
- }
- for (from = &inode[0]; from < &inode[ninode]; from++)
- if (from->i_number == (ino_t)uap->inum
- && from->i_dev == (dev_t)uap->device)
- break;
- if (from >= &inode[ninode]) {
- u.u_error = ENXIO;
- return;
- }
- offset = fp->f_offset;
- to = fp->f_inode;
- from->i_count++;
- for (fp = &file[0]; fp < &file[nfile]; fp++) {
- if (fp->f_count > 0 && fp->f_inode == from) {
- fp->f_inode = to;
- to->i_count++;
- fp->f_offset = offset;
- rw |= fp->f_flag & FWRITE;
- iput(from);
- }
- }
- /*
- * This inode is no longer referenced.
- * Switch out to the appropriate close
- * routine, if required
- */
- dev = (dev_t)from->i_un.i_rdev;
- switch(from->i_mode & IFMT) {