asmlinkage int sys_dup2(unsigned int oldfd, unsigned int newfd) { int err = -EBADF; lock_kernel(); #ifdef FDSET_DEBUG printk (KERN_ERR __FUNCTION__ " 0: oldfd = %d, newfd = %d\n", oldfd, newfd); #endif if (!fcheck(oldfd)) goto out; if (newfd >= NR_OPEN) goto out; /* following POSIX.1 6.2.1 */ err = newfd; if (newfd == oldfd) goto out; /* We must be able to do the fd setting inside dupfd() without blocking after the sys_close(). */ if ((err = expand_files(current->files, newfd)) < 0) goto out; sys_close(newfd); err = dupfd(oldfd, newfd); out: #ifdef FDSET_DEBUG printk (KERN_ERR __FUNCTION__ ": return %d\n", err); #endif unlock_kernel(); return err; }
//// 文件控制系统调用函数。 // 参数fd 是文件句柄,cmd 是操作命令(参见include/fcntl.h,23-30 行)。 int sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) { struct file * filp; // 如果文件句柄值大于一个进程最多打开文件数NR_OPEN,或者该句柄的文件结构指针为空,则出错, // 返回出错码并退出。 if (fd >= NR_OPEN || !(filp = current->filp[fd])) return -EBADF; // 根据不同命令cmd 进行分别处理。 switch (cmd) { case F_DUPFD: // 复制文件句柄。 return dupfd(fd,arg); case F_GETFD: // 取文件句柄的执行时关闭标志。 return (current->close_on_exec>>fd)&1; case F_SETFD: // 设置句柄执行时关闭标志。arg 位0 置位是设置,否则关闭。 if (arg&1) current->close_on_exec |= (1<<fd); else current->close_on_exec &= ~(1<<fd); return 0; case F_GETFL: // 取文件状态标志和访问模式。 return filp->f_flags; case F_SETFL: // 设置文件状态和访问模式(根据arg 设置添加、非阻塞标志)。 filp->f_flags &= ~(O_APPEND | O_NONBLOCK); filp->f_flags |= arg & (O_APPEND | O_NONBLOCK); return 0; case F_GETLK: case F_SETLK: case F_SETLKW: // 未实现。 return -1; default: return -1; } }
int sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) { struct file * filp; if (fd >= NR_OPEN || !(filp = current->filp[fd])) return -EBADF; switch (cmd) { case F_DUPFD: return dupfd(fd,arg); case F_GETFD: return (current->close_on_exec>>fd)&1; case F_SETFD: if (arg&1) current->close_on_exec |= (1<<fd); else current->close_on_exec &= ~(1<<fd); return 0; case F_GETFL: return filp->f_flags; case F_SETFL: filp->f_flags &= ~(O_APPEND | O_NONBLOCK); filp->f_flags |= arg & (O_APPEND | O_NONBLOCK); return 0; case F_GETLK: case F_SETLK: case F_SETLKW: return -1; default: return -1; } }
int sys_dup2(unsigned int oldfd, unsigned int newfd) { if (oldfd < NR_OPEN && current->files.fd[oldfd]) { if (newfd == oldfd) return (int) newfd; /* following POSIX.1 6.2.1, if newfd >= NR_OPEN, return -EBADF */ if (newfd < NR_OPEN) { sys_close(newfd); return dupfd(oldfd, newfd); } } return -EBADF; }
int dup2 (int fd, int desired_fd) { if (fd == desired_fd) return fd; close (desired_fd); #ifdef F_DUPFD return fcntl (fd, F_DUPFD, desired_fd); #else return dupfd (fd, desired_fd); #endif }
asmlinkage int sys_dup(unsigned int fildes) { int ret; lock_kernel(); ret = dupfd(fildes, 0); unlock_kernel(); #ifdef FDSET_DEBUG if (ret < 0) printk (KERN_ERR __FUNCTION__ ": return %d\n", ret); #endif return ret; }
int sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) { struct file *file; if (fd > NR_OPEN || !(file = (CURRENT_TASK() )->file[fd])) return -EBADF; switch (cmd) { case F_DUPFD: return dupfd(fd, arg); default: return -EIO; } }
static int dupfd (int fd, int desired_fd) { int duplicated_fd = dup (fd); if (duplicated_fd < 0 || duplicated_fd == desired_fd) return duplicated_fd; else { int r = dupfd (fd, desired_fd); int e = errno; close (duplicated_fd); errno = e; return r; } }
int sys_fcntl(unsigned int fd, unsigned int cmd, unsigned int arg) { register struct file *filp; register struct file_struct *fils = ¤t->files; int result; if (fd >= NR_OPEN || !(filp = fils->fd[fd])) return -EBADF; switch (cmd) { case F_DUPFD: result = dupfd(fd, arg); break; case F_GETFD: result = test_bit(fd, &fils->close_on_exec); break; case F_SETFD: if (arg & 1) set_bit(fd, &fils->close_on_exec); else clear_bit(fd, &fils->close_on_exec); result = 0; break; case F_GETFL: result = (int) filp->f_flags; break; case F_SETFL: /* * In the case of an append-only file, O_APPEND * cannot be cleared */ result = -EPERM; if (!IS_APPEND(filp->f_inode) || (arg & O_APPEND)) { filp->f_flags &= ~(O_APPEND | O_NONBLOCK); filp->f_flags |= arg & (O_APPEND | O_NONBLOCK); result = 0; } break; default: result = -EINVAL; break; } return result; }
int dup2 (int fd, int desired_fd) { int result = fcntl (fd, F_GETFL) < 0 ? -1 : fd; if (result == -1 || fd == desired_fd) return result; close (desired_fd); # ifdef F_DUPFD result = fcntl (fd, F_DUPFD, desired_fd); # if REPLACE_FCHDIR if (0 <= result) result = _gl_register_dup (fd, result); # endif # else result = dupfd (fd, desired_fd); # endif if (result == -1 && (errno == EMFILE || errno == EINVAL)) errno = EBADF; return result; }
int sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) { struct file * filp; extern int sock_fcntl (struct file *, unsigned int cmd, unsigned long arg); if (fd >= NR_OPEN || !(filp = current->filp[fd])) return -EBADF; switch (cmd) { case F_DUPFD: return dupfd(fd,arg); case F_GETFD: return FD_ISSET(fd, ¤t->close_on_exec); case F_SETFD: if (arg&1) FD_SET(fd, ¤t->close_on_exec); else FD_CLR(fd, ¤t->close_on_exec); return 0; case F_GETFL: return filp->f_flags; case F_SETFL: filp->f_flags &= ~(O_APPEND | O_NONBLOCK); filp->f_flags |= arg & (O_APPEND | O_NONBLOCK); return 0; case F_GETLK: return fcntl_getlk(fd, (struct flock *) arg); case F_SETLK: return fcntl_setlk(fd, cmd, (struct flock *) arg); case F_SETLKW: return fcntl_setlk(fd, cmd, (struct flock *) arg); default: /* sockets need a few special fcntls. */ if (S_ISSOCK (filp->f_inode->i_mode)) { return (sock_fcntl (filp, cmd, arg)); } return -EINVAL; } }
asmlinkage int sys_dup2(unsigned int oldfd, unsigned int newfd) { if (oldfd >= NR_OPEN || !current->files->fd[oldfd]) return -EBADF; if (newfd == oldfd) return newfd; /* * errno's for dup2() are slightly different than for fcntl(F_DUPFD) * for historical reasons. */ if (newfd > NR_OPEN) /* historical botch - should have been >= */ return -EBADF; /* dupfd() would return -EINVAL */ #if 1 if (newfd == NR_OPEN) return -EBADF; /* dupfd() does return -EINVAL and that may * even be the standard! But that is too * weird for now. */ #endif sys_close(newfd); return dupfd(oldfd,newfd); }
asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) { struct file * filp; long err = -EBADF; lock_kernel(); filp = fget(fd); if (!filp) goto out; err = 0; switch (cmd) { case F_DUPFD: err = dupfd(fd, arg); break; case F_GETFD: err = FD_ISSET(fd, current->files->close_on_exec); break; case F_SETFD: if (arg&1) FD_SET(fd, current->files->close_on_exec); else FD_CLR(fd, current->files->close_on_exec); break; case F_GETFL: err = filp->f_flags; break; case F_SETFL: err = setfl(fd, filp, arg); break; case F_GETLK: err = fcntl_getlk(fd, (struct flock *) arg); break; case F_SETLK: err = fcntl_setlk(fd, cmd, (struct flock *) arg); break; case F_SETLKW: err = fcntl_setlk(fd, cmd, (struct flock *) arg); break; case F_GETOWN: /* * XXX If f_owner is a process group, the * negative return value will get converted * into an error. Oops. If we keep the * current syscall conventions, the only way * to fix this will be in libc. */ err = filp->f_owner.pid; break; case F_SETOWN: filp->f_owner.pid = arg; filp->f_owner.uid = current->uid; filp->f_owner.euid = current->euid; if (S_ISSOCK (filp->f_dentry->d_inode->i_mode)) err = sock_fcntl (filp, F_SETOWN, arg); break; case F_GETSIG: err = filp->f_owner.signum; break; case F_SETSIG: if (arg <= 0 || arg > _NSIG) { err = -EINVAL; break; } err = 0; filp->f_owner.signum = arg; break; default: /* sockets need a few special fcntls. */ err = -EINVAL; if (S_ISSOCK (filp->f_dentry->d_inode->i_mode)) err = sock_fcntl (filp, cmd, arg); break; } fput(filp); out: unlock_kernel(); return err; }
int sys_dup(unsigned int fildes) { return dupfd(fildes,0); }
int sys_dup2(unsigned int oldfd, unsigned int newfd) { sys_close(newfd); return dupfd(oldfd,newfd); }
//// 复制文件句柄系统调用函数。 // 复制指定文件句柄oldfd,新句柄值等于newfd。如果newfd 已经打开,则首先关闭之。 int sys_dup2(unsigned int oldfd, unsigned int newfd) { sys_close(newfd); // 若句柄newfd 已经打开,则首先关闭之。 return dupfd(oldfd,newfd); // 复制并返回新句柄。 }
asmlinkage int sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) { struct file * filp; if (fd >= NR_OPEN || !(filp = current->files->fd[fd])) return -EBADF; switch (cmd) { case F_DUPFD: return dupfd(fd,arg); case F_GETFD: return FD_ISSET(fd, ¤t->files->close_on_exec); case F_SETFD: if (arg&1) FD_SET(fd, ¤t->files->close_on_exec); else FD_CLR(fd, ¤t->files->close_on_exec); return 0; case F_GETFL: return filp->f_flags; case F_SETFL: /* * In the case of an append-only file, O_APPEND * cannot be cleared */ if (IS_APPEND(filp->f_inode) && !(arg & O_APPEND)) return -EPERM; if ((arg & FASYNC) && !(filp->f_flags & FASYNC) && filp->f_op->fasync) filp->f_op->fasync(filp->f_inode, filp, 1); if (!(arg & FASYNC) && (filp->f_flags & FASYNC) && filp->f_op->fasync) filp->f_op->fasync(filp->f_inode, filp, 0); filp->f_flags &= ~(O_APPEND | O_NONBLOCK | FASYNC); filp->f_flags |= arg & (O_APPEND | O_NONBLOCK | FASYNC); return 0; case F_GETLK: return fcntl_getlk(fd, (struct flock *) arg); case F_SETLK: return fcntl_setlk(fd, cmd, (struct flock *) arg); case F_SETLKW: return fcntl_setlk(fd, cmd, (struct flock *) arg); case F_GETOWN: /* * XXX If f_owner is a process group, the * negative return value will get converted * into an error. Oops. If we keep the the * current syscall conventions, the only way * to fix this will be in libc. */ return filp->f_owner; case F_SETOWN: filp->f_owner = arg; /* XXX security implications? */ if (S_ISSOCK (filp->f_inode->i_mode)) sock_fcntl (filp, F_SETOWN, arg); return 0; default: /* sockets need a few special fcntls. */ if (S_ISSOCK (filp->f_inode->i_mode)) { return (sock_fcntl (filp, cmd, arg)); } return -EINVAL; } }