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