|
|
1.1.1.2 root 1: /*
2: * linux/fs/open.c
3: *
4: * (C) 1991 Linus Torvalds
5: */
6:
1.1 root 7: #include <errno.h>
8: #include <fcntl.h>
9: #include <sys/types.h>
10: #include <utime.h>
1.1.1.6 ! root 11:
1.1 root 12: #include <sys/stat.h>
1.1.1.6 ! root 13: #include <sys/vfs.h>
1.1 root 14:
1.1.1.6 ! root 15: #include <linux/string.h>
1.1 root 16: #include <linux/sched.h>
17: #include <linux/kernel.h>
1.1.1.3 root 18:
1.1 root 19: #include <asm/segment.h>
20:
1.1.1.6 ! root 21: struct file_operations * chrdev_fops[MAX_CHRDEV] = {
! 22: NULL,
! 23: };
! 24:
! 25: struct file_operations * blkdev_fops[MAX_BLKDEV] = {
! 26: NULL,
! 27: };
! 28:
1.1.1.2 root 29: int sys_ustat(int dev, struct ustat * ubuf)
30: {
31: return -ENOSYS;
32: }
33:
1.1.1.6 ! root 34: int sys_statfs(const char * path, struct statfs * buf)
! 35: {
! 36: printk("statfs not implemented\n");
! 37: return -ENOSYS;
! 38: }
! 39:
! 40: int sys_fstatfs(unsigned int fd, struct statfs * buf)
! 41: {
! 42: printk("fstatfs not implemented\n");
! 43: return -ENOSYS;
! 44: }
! 45:
! 46: int sys_truncate(const char * path, unsigned int length)
! 47: {
! 48: struct inode * inode;
! 49:
! 50: if (!(inode = namei(path)))
! 51: return -ENOENT;
! 52: if (S_ISDIR(inode->i_mode) || !permission(inode,MAY_WRITE)) {
! 53: iput(inode);
! 54: return -EACCES;
! 55: }
! 56: inode->i_size = length;
! 57: if (inode->i_op && inode->i_op->truncate)
! 58: inode->i_op->truncate(inode);
! 59: inode->i_atime = inode->i_mtime = CURRENT_TIME;
! 60: inode->i_dirt = 1;
! 61: iput(inode);
! 62: return 0;
! 63: }
! 64:
! 65: int sys_ftruncate(unsigned int fd, unsigned int length)
! 66: {
! 67: struct inode * inode;
! 68: struct file * file;
! 69:
! 70: if (fd >= NR_OPEN || !(file = current->filp[fd]))
! 71: return -EBADF;
! 72: if (!(inode = file->f_inode))
! 73: return -ENOENT;
! 74: if (S_ISDIR(inode->i_mode) || !(file->f_flags & 2))
! 75: return -EACCES;
! 76: inode->i_size = length;
! 77: if (inode->i_op && inode->i_op->truncate)
! 78: inode->i_op->truncate(inode);
! 79: inode->i_atime = inode->i_mtime = CURRENT_TIME;
! 80: inode->i_dirt = 1;
! 81: return 0;
! 82: }
! 83:
1.1 root 84: int sys_utime(char * filename, struct utimbuf * times)
85: {
1.1.1.4 root 86: struct inode * inode;
1.1 root 87: long actime,modtime;
88:
89: if (!(inode=namei(filename)))
90: return -ENOENT;
91: if (times) {
1.1.1.5 root 92: if (current->euid != inode->i_uid &&
93: !permission(inode,MAY_WRITE)) {
94: iput(inode);
1.1.1.6 ! root 95: return -EACCES;
1.1.1.5 root 96: }
1.1 root 97: actime = get_fs_long((unsigned long *) ×->actime);
98: modtime = get_fs_long((unsigned long *) ×->modtime);
99: } else
100: actime = modtime = CURRENT_TIME;
101: inode->i_atime = actime;
102: inode->i_mtime = modtime;
103: inode->i_dirt = 1;
104: iput(inode);
105: return 0;
106: }
107:
1.1.1.2 root 108: /*
109: * XXX should we use the real or effective uid? BSD uses the real uid,
110: * so as to make this call useful to setuid programs.
111: */
1.1 root 112: int sys_access(const char * filename,int mode)
113: {
1.1.1.4 root 114: struct inode * inode;
1.1.1.2 root 115: int res, i_mode;
1.1 root 116:
117: mode &= 0007;
118: if (!(inode=namei(filename)))
119: return -EACCES;
1.1.1.2 root 120: i_mode = res = inode->i_mode & 0777;
1.1 root 121: iput(inode);
1.1.1.2 root 122: if (current->uid == inode->i_uid)
1.1 root 123: res >>= 6;
1.1.1.2 root 124: else if (current->gid == inode->i_gid)
1.1 root 125: res >>= 6;
126: if ((res & 0007 & mode) == mode)
127: return 0;
1.1.1.2 root 128: /*
129: * XXX we are doing this test last because we really should be
130: * swapping the effective with the real user id (temporarily),
131: * and then calling suser() routine. If we do call the
132: * suser() routine, it needs to be called last.
133: */
134: if ((!current->uid) &&
135: (!(mode & 1) || (i_mode & 0111)))
136: return 0;
1.1 root 137: return -EACCES;
138: }
139:
140: int sys_chdir(const char * filename)
141: {
1.1.1.4 root 142: struct inode * inode;
1.1 root 143:
144: if (!(inode = namei(filename)))
145: return -ENOENT;
146: if (!S_ISDIR(inode->i_mode)) {
147: iput(inode);
148: return -ENOTDIR;
149: }
1.1.1.6 ! root 150: if (!permission(inode,MAY_EXEC)) {
! 151: iput(inode);
! 152: return -EACCES;
! 153: }
1.1 root 154: iput(current->pwd);
155: current->pwd = inode;
156: return (0);
157: }
158:
159: int sys_chroot(const char * filename)
160: {
1.1.1.4 root 161: struct inode * inode;
1.1 root 162:
163: if (!(inode=namei(filename)))
164: return -ENOENT;
165: if (!S_ISDIR(inode->i_mode)) {
166: iput(inode);
167: return -ENOTDIR;
168: }
1.1.1.6 ! root 169: if (!suser()) {
! 170: iput(inode);
! 171: return -EPERM;
! 172: }
1.1 root 173: iput(current->root);
174: current->root = inode;
175: return (0);
176: }
177:
1.1.1.6 ! root 178: int sys_fchmod(unsigned int fd, mode_t mode)
1.1 root 179: {
1.1.1.4 root 180: struct inode * inode;
1.1.1.6 ! root 181: struct file * file;
1.1 root 182:
1.1.1.6 ! root 183: if (fd >= NR_OPEN || !(file = current->filp[fd]))
! 184: return -EBADF;
! 185: if (!(inode = file->f_inode))
! 186: return -ENOENT;
! 187: if ((current->euid != inode->i_uid) && !suser())
! 188: return -EPERM;
! 189: inode->i_mode = (mode & 07777) | (inode->i_mode & ~07777);
! 190: inode->i_dirt = 1;
! 191: return 0;
! 192: }
! 193:
! 194: int sys_chmod(const char * filename, mode_t mode)
! 195: {
! 196: struct inode * inode;
! 197:
! 198: if (!(inode = namei(filename)))
1.1 root 199: return -ENOENT;
1.1.1.2 root 200: if ((current->euid != inode->i_uid) && !suser()) {
201: iput(inode);
1.1.1.6 ! root 202: return -EPERM;
1.1.1.2 root 203: }
1.1 root 204: inode->i_mode = (mode & 07777) | (inode->i_mode & ~07777);
205: inode->i_dirt = 1;
206: iput(inode);
207: return 0;
208: }
209:
1.1.1.6 ! root 210: int sys_fchown(unsigned int fd, uid_t user, gid_t group)
1.1 root 211: {
1.1.1.4 root 212: struct inode * inode;
1.1.1.6 ! root 213: struct file * file;
1.1 root 214:
1.1.1.6 ! root 215: if (fd >= NR_OPEN || !(file = current->filp[fd]))
! 216: return -EBADF;
! 217: if (!(inode = file->f_inode))
1.1 root 218: return -ENOENT;
1.1.1.6 ! root 219: if ((current->euid == inode->i_uid && user == inode->i_uid &&
! 220: (in_group_p(group) || group == inode->i_gid)) ||
! 221: suser()) {
! 222: inode->i_uid = user;
! 223: inode->i_gid = group;
! 224: inode->i_dirt=1;
! 225: return 0;
! 226: }
! 227: return -EPERM;
! 228: }
! 229:
! 230: int sys_chown(const char * filename, uid_t user, gid_t group)
! 231: {
! 232: struct inode * inode;
! 233:
! 234: if (!(inode = lnamei(filename)))
! 235: return -ENOENT;
! 236: if ((current->euid == inode->i_uid && user == inode->i_uid &&
! 237: (in_group_p(group) || group == inode->i_gid)) ||
! 238: suser()) {
! 239: inode->i_uid = user;
! 240: inode->i_gid = group;
! 241: inode->i_dirt=1;
1.1 root 242: iput(inode);
1.1.1.6 ! root 243: return 0;
1.1 root 244: }
245: iput(inode);
1.1.1.6 ! root 246: return -EPERM;
1.1 root 247: }
248:
249: int sys_open(const char * filename,int flag,int mode)
250: {
1.1.1.4 root 251: struct inode * inode;
1.1 root 252: struct file * f;
253: int i,fd;
254:
255: for(fd=0 ; fd<NR_OPEN ; fd++)
256: if (!current->filp[fd])
257: break;
258: if (fd>=NR_OPEN)
259: return -EINVAL;
260: current->close_on_exec &= ~(1<<fd);
261: f=0+file_table;
262: for (i=0 ; i<NR_FILE ; i++,f++)
263: if (!f->f_count) break;
264: if (i>=NR_FILE)
265: return -EINVAL;
1.1.1.6 ! root 266: (current->filp[fd] = f)->f_count++;
! 267: if ((i = open_namei(filename,flag,mode,&inode))<0) {
1.1 root 268: current->filp[fd]=NULL;
269: f->f_count=0;
270: return i;
271: }
1.1.1.4 root 272: f->f_mode = "\001\002\003\000"[flag & O_ACCMODE];
1.1 root 273: f->f_flags = flag;
274: f->f_count = 1;
275: f->f_inode = inode;
276: f->f_pos = 0;
1.1.1.6 ! root 277: f->f_reada = 0;
! 278: f->f_op = NULL;
! 279: if (inode->i_op)
! 280: f->f_op = inode->i_op->default_file_ops;
! 281: if (f->f_op && f->f_op->open)
! 282: if (i = f->f_op->open(inode,f)) {
1.1.1.4 root 283: iput(inode);
284: f->f_count=0;
285: current->filp[fd]=NULL;
286: return i;
287: }
1.1 root 288: return (fd);
289: }
290:
291: int sys_creat(const char * pathname, int mode)
292: {
1.1.1.4 root 293: return sys_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
1.1 root 294: }
295:
296: int sys_close(unsigned int fd)
297: {
298: struct file * filp;
299:
300: if (fd >= NR_OPEN)
301: return -EINVAL;
302: current->close_on_exec &= ~(1<<fd);
303: if (!(filp = current->filp[fd]))
304: return -EINVAL;
305: current->filp[fd] = NULL;
1.1.1.6 ! root 306: if (filp->f_count == 0) {
! 307: printk("Close: file count is 0\n");
! 308: return 0;
! 309: }
! 310: if (filp->f_count > 1) {
! 311: filp->f_count--;
! 312: return 0;
! 313: }
! 314: if (filp->f_op && filp->f_op->release)
! 315: filp->f_op->release(filp->f_inode,filp);
1.1 root 316: iput(filp->f_inode);
1.1.1.6 ! root 317: filp->f_count--;
! 318: return 0;
1.1 root 319: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.