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