diff options
Diffstat (limited to 'linux/fs/open.c')
| -rw-r--r-- | linux/fs/open.c | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/linux/fs/open.c b/linux/fs/open.c new file mode 100644 index 0000000..6918690 --- /dev/null +++ b/linux/fs/open.c @@ -0,0 +1,188 @@ +#include <string.h> +#include <errno.h> +#include <fcntl.h> +#include <sys/types.h> +#include <utime.h> +#include <sys/stat.h> + +#include <linux/sched.h> +#include <linux/tty.h> +#include <linux/kernel.h> +#include <asm/segment.h> + +int sys_utime(char * filename, struct utimbuf * times) +{ + struct m_inode * inode; + long actime,modtime; + + if (!(inode=namei(filename))) + return -ENOENT; + if (times) { + actime = get_fs_long((unsigned long *) ×->actime); + modtime = get_fs_long((unsigned long *) ×->modtime); + } else + actime = modtime = CURRENT_TIME; + inode->i_atime = actime; + inode->i_mtime = modtime; + inode->i_dirt = 1; + iput(inode); + return 0; +} + +int sys_access(const char * filename,int mode) +{ + struct m_inode * inode; + int res; + + mode &= 0007; + if (!(inode=namei(filename))) + return -EACCES; + res = inode->i_mode & 0777; + iput(inode); + if (!(current->euid && current->uid)) + if (res & 0111) + res = 0777; + else + res = 0666; + if (current->euid == inode->i_uid) + res >>= 6; + else if (current->egid == inode->i_gid) + res >>= 6; + if ((res & 0007 & mode) == mode) + return 0; + return -EACCES; +} + +int sys_chdir(const char * filename) +{ + struct m_inode * inode; + + if (!(inode = namei(filename))) + return -ENOENT; + if (!S_ISDIR(inode->i_mode)) { + iput(inode); + return -ENOTDIR; + } + iput(current->pwd); + current->pwd = inode; + return (0); +} + +int sys_chroot(const char * filename) +{ + struct m_inode * inode; + + if (!(inode=namei(filename))) + return -ENOENT; + if (!S_ISDIR(inode->i_mode)) { + iput(inode); + return -ENOTDIR; + } + iput(current->root); + current->root = inode; + return (0); +} + +int sys_chmod(const char * filename,int mode) +{ + struct m_inode * inode; + + if (!(inode=namei(filename))) + return -ENOENT; + if (current->uid && current->euid) + if (current->uid!=inode->i_uid && current->euid!=inode->i_uid) { + iput(inode); + return -EACCES; + } else + mode = (mode & 0777) | (inode->i_mode & 07000); + inode->i_mode = (mode & 07777) | (inode->i_mode & ~07777); + inode->i_dirt = 1; + iput(inode); + return 0; +} + +int sys_chown(const char * filename,int uid,int gid) +{ + struct m_inode * inode; + + if (!(inode=namei(filename))) + return -ENOENT; + if (current->uid && current->euid) { + iput(inode); + return -EACCES; + } + inode->i_uid=uid; + inode->i_gid=gid; + inode->i_dirt=1; + iput(inode); + return 0; +} + +int sys_open(const char * filename,int flag,int mode) +{ + struct m_inode * inode; + struct file * f; + int i,fd; + + mode &= 0777 & ~current->umask; + for(fd=0 ; fd<NR_OPEN ; fd++) + if (!current->filp[fd]) + break; + if (fd>=NR_OPEN) + return -EINVAL; + current->close_on_exec &= ~(1<<fd); + f=0+file_table; + for (i=0 ; i<NR_FILE ; i++,f++) + if (!f->f_count) break; + if (i>=NR_FILE) + return -EINVAL; + (current->filp[fd]=f)->f_count++; + if ((i=open_namei(filename,flag,mode,&inode))<0) { + current->filp[fd]=NULL; + f->f_count=0; + return i; + } +/* ttys are somewhat special (ttyxx major==4, tty major==5) */ + if (S_ISCHR(inode->i_mode)) + if (MAJOR(inode->i_zone[0])==4) { + if (current->leader && current->tty<0) { + current->tty = MINOR(inode->i_zone[0]); + tty_table[current->tty].pgrp = current->pgrp; + } + } else if (MAJOR(inode->i_zone[0])==5) + if (current->tty<0) { + iput(inode); + current->filp[fd]=NULL; + f->f_count=0; + return -EPERM; + } + f->f_mode = inode->i_mode; + f->f_flags = flag; + f->f_count = 1; + f->f_inode = inode; + f->f_pos = 0; + return (fd); +} + +int sys_creat(const char * pathname, int mode) +{ + return sys_open(pathname, O_CREAT | O_TRUNC, mode); +} + +int sys_close(unsigned int fd) +{ + struct file * filp; + + if (fd >= NR_OPEN) + return -EINVAL; + current->close_on_exec &= ~(1<<fd); + if (!(filp = current->filp[fd])) + return -EINVAL; + current->filp[fd] = NULL; + if (filp->f_count == 0) + panic("Close: file count is 0"); + if (--filp->f_count) + return (0); + iput(filp->f_inode); + return (0); +} |
