|
|
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.10! root 17: #include <linux/tty.h>
1.1 root 18: #include <asm/segment.h>
19:
1.1.1.10! root 20: extern void fcntl_remove_locks(struct task_struct *, struct file *);
! 21:
1.1.1.6 root 22: struct file_operations * chrdev_fops[MAX_CHRDEV] = {
23: NULL,
24: };
25:
26: struct file_operations * blkdev_fops[MAX_BLKDEV] = {
27: NULL,
28: };
29:
1.1.1.2 root 30: int sys_ustat(int dev, struct ustat * ubuf)
31: {
32: return -ENOSYS;
33: }
34:
1.1.1.6 root 35: int sys_statfs(const char * path, struct statfs * buf)
36: {
1.1.1.7 root 37: struct inode * inode;
1.1.1.10! root 38: int error;
1.1.1.7 root 39:
40: verify_area(buf, sizeof(struct statfs));
1.1.1.10! root 41: error = namei(path,&inode);
! 42: if (error)
! 43: return error;
1.1.1.7 root 44: if (!inode->i_sb->s_op->statfs) {
45: iput(inode);
46: return -ENOSYS;
47: }
48: inode->i_sb->s_op->statfs(inode->i_sb, buf);
49: iput(inode);
50: return 0;
1.1.1.6 root 51: }
52:
53: int sys_fstatfs(unsigned int fd, struct statfs * buf)
54: {
1.1.1.7 root 55: struct inode * inode;
56: struct file * file;
57:
58: verify_area(buf, sizeof(struct statfs));
59: if (fd >= NR_OPEN || !(file = current->filp[fd]))
60: return -EBADF;
61: if (!(inode = file->f_inode))
62: return -ENOENT;
63: if (!inode->i_sb->s_op->statfs)
64: return -ENOSYS;
65: inode->i_sb->s_op->statfs(inode->i_sb, buf);
66: return 0;
1.1.1.6 root 67: }
68:
69: int sys_truncate(const char * path, unsigned int length)
70: {
71: struct inode * inode;
1.1.1.10! root 72: int error;
1.1.1.6 root 73:
1.1.1.10! root 74: error = namei(path,&inode);
! 75: if (error)
! 76: return error;
1.1.1.6 root 77: if (S_ISDIR(inode->i_mode) || !permission(inode,MAY_WRITE)) {
78: iput(inode);
79: return -EACCES;
80: }
1.1.1.9 root 81: if (IS_RDONLY(inode)) {
82: iput(inode);
83: return -EROFS;
84: }
1.1.1.6 root 85: inode->i_size = length;
86: if (inode->i_op && inode->i_op->truncate)
87: inode->i_op->truncate(inode);
88: inode->i_atime = inode->i_mtime = CURRENT_TIME;
89: inode->i_dirt = 1;
90: iput(inode);
91: return 0;
92: }
93:
94: int sys_ftruncate(unsigned int fd, unsigned int length)
95: {
96: struct inode * inode;
97: struct file * file;
98:
99: if (fd >= NR_OPEN || !(file = current->filp[fd]))
100: return -EBADF;
101: if (!(inode = file->f_inode))
102: return -ENOENT;
1.1.1.9 root 103: if (S_ISDIR(inode->i_mode) || !(file->f_mode & 2))
1.1.1.6 root 104: return -EACCES;
105: inode->i_size = length;
106: if (inode->i_op && inode->i_op->truncate)
107: inode->i_op->truncate(inode);
108: inode->i_atime = inode->i_mtime = CURRENT_TIME;
109: inode->i_dirt = 1;
110: return 0;
111: }
112:
1.1.1.8 root 113: /* If times==NULL, set access and modification to current time,
114: * must be owner or have write permission.
115: * Else, update from *times, must be owner or super user.
116: */
1.1 root 117: int sys_utime(char * filename, struct utimbuf * times)
118: {
1.1.1.4 root 119: struct inode * inode;
1.1 root 120: long actime,modtime;
1.1.1.10! root 121: int error;
1.1 root 122:
1.1.1.10! root 123: error = namei(filename,&inode);
! 124: if (error)
! 125: return error;
1.1.1.9 root 126: if (IS_RDONLY(inode)) {
127: iput(inode);
128: return -EROFS;
129: }
1.1 root 130: if (times) {
1.1.1.8 root 131: if ((current->euid != inode->i_uid) && !suser()) {
1.1.1.5 root 132: iput(inode);
1.1.1.8 root 133: return -EPERM;
1.1.1.5 root 134: }
1.1 root 135: actime = get_fs_long((unsigned long *) ×->actime);
136: modtime = get_fs_long((unsigned long *) ×->modtime);
1.1.1.8 root 137: } else {
138: if ((current->euid != inode->i_uid) &&
139: !permission(inode,MAY_WRITE)) {
140: iput(inode);
141: return -EACCES;
142: }
1.1 root 143: actime = modtime = CURRENT_TIME;
1.1.1.8 root 144: }
1.1 root 145: inode->i_atime = actime;
146: inode->i_mtime = modtime;
147: inode->i_dirt = 1;
148: iput(inode);
149: return 0;
150: }
151:
1.1.1.2 root 152: /*
153: * XXX should we use the real or effective uid? BSD uses the real uid,
154: * so as to make this call useful to setuid programs.
155: */
1.1 root 156: int sys_access(const char * filename,int mode)
157: {
1.1.1.4 root 158: struct inode * inode;
1.1.1.2 root 159: int res, i_mode;
1.1 root 160:
161: mode &= 0007;
1.1.1.10! root 162: res = namei(filename,&inode);
! 163: if (res)
! 164: return res;
1.1.1.2 root 165: i_mode = res = inode->i_mode & 0777;
1.1 root 166: iput(inode);
1.1.1.2 root 167: if (current->uid == inode->i_uid)
1.1 root 168: res >>= 6;
1.1.1.7 root 169: else if (in_group_p(inode->i_gid))
170: res >>= 3;
1.1 root 171: if ((res & 0007 & mode) == mode)
172: return 0;
1.1.1.2 root 173: /*
174: * XXX we are doing this test last because we really should be
175: * swapping the effective with the real user id (temporarily),
176: * and then calling suser() routine. If we do call the
177: * suser() routine, it needs to be called last.
178: */
179: if ((!current->uid) &&
180: (!(mode & 1) || (i_mode & 0111)))
181: return 0;
1.1 root 182: return -EACCES;
183: }
184:
185: int sys_chdir(const char * filename)
186: {
1.1.1.4 root 187: struct inode * inode;
1.1.1.10! root 188: int error;
1.1 root 189:
1.1.1.10! root 190: error = namei(filename,&inode);
! 191: if (error)
! 192: return error;
1.1 root 193: if (!S_ISDIR(inode->i_mode)) {
194: iput(inode);
195: return -ENOTDIR;
196: }
1.1.1.6 root 197: if (!permission(inode,MAY_EXEC)) {
198: iput(inode);
199: return -EACCES;
200: }
1.1 root 201: iput(current->pwd);
202: current->pwd = inode;
203: return (0);
204: }
205:
206: int sys_chroot(const char * filename)
207: {
1.1.1.4 root 208: struct inode * inode;
1.1.1.10! root 209: int error;
1.1 root 210:
1.1.1.10! root 211: error = namei(filename,&inode);
! 212: if (error)
! 213: return error;
1.1 root 214: if (!S_ISDIR(inode->i_mode)) {
215: iput(inode);
216: return -ENOTDIR;
217: }
1.1.1.6 root 218: if (!suser()) {
219: iput(inode);
220: return -EPERM;
221: }
1.1 root 222: iput(current->root);
223: current->root = inode;
224: return (0);
225: }
226:
1.1.1.6 root 227: int sys_fchmod(unsigned int fd, mode_t mode)
1.1 root 228: {
1.1.1.4 root 229: struct inode * inode;
1.1.1.6 root 230: struct file * file;
1.1 root 231:
1.1.1.6 root 232: if (fd >= NR_OPEN || !(file = current->filp[fd]))
233: return -EBADF;
234: if (!(inode = file->f_inode))
235: return -ENOENT;
236: if ((current->euid != inode->i_uid) && !suser())
237: return -EPERM;
1.1.1.9 root 238: if (IS_RDONLY(inode))
239: return -EROFS;
1.1.1.6 root 240: inode->i_mode = (mode & 07777) | (inode->i_mode & ~07777);
241: inode->i_dirt = 1;
242: return 0;
243: }
244:
245: int sys_chmod(const char * filename, mode_t mode)
246: {
247: struct inode * inode;
1.1.1.10! root 248: int error;
1.1.1.6 root 249:
1.1.1.10! root 250: error = namei(filename,&inode);
! 251: if (error)
! 252: return error;
1.1.1.2 root 253: if ((current->euid != inode->i_uid) && !suser()) {
254: iput(inode);
1.1.1.6 root 255: return -EPERM;
1.1.1.2 root 256: }
1.1.1.9 root 257: if (IS_RDONLY(inode)) {
258: iput(inode);
259: return -EROFS;
260: }
1.1 root 261: inode->i_mode = (mode & 07777) | (inode->i_mode & ~07777);
262: inode->i_dirt = 1;
263: iput(inode);
264: return 0;
265: }
266:
1.1.1.6 root 267: int sys_fchown(unsigned int fd, uid_t user, gid_t group)
1.1 root 268: {
1.1.1.4 root 269: struct inode * inode;
1.1.1.6 root 270: struct file * file;
1.1 root 271:
1.1.1.6 root 272: if (fd >= NR_OPEN || !(file = current->filp[fd]))
273: return -EBADF;
274: if (!(inode = file->f_inode))
1.1 root 275: return -ENOENT;
1.1.1.9 root 276: if (IS_RDONLY(inode))
277: return -EROFS;
1.1.1.6 root 278: if ((current->euid == inode->i_uid && user == inode->i_uid &&
279: (in_group_p(group) || group == inode->i_gid)) ||
280: suser()) {
281: inode->i_uid = user;
282: inode->i_gid = group;
283: inode->i_dirt=1;
284: return 0;
285: }
286: return -EPERM;
287: }
288:
289: int sys_chown(const char * filename, uid_t user, gid_t group)
290: {
291: struct inode * inode;
1.1.1.10! root 292: int error;
1.1.1.6 root 293:
1.1.1.10! root 294: error = lnamei(filename,&inode);
! 295: if (error)
! 296: return error;
1.1.1.9 root 297: if (IS_RDONLY(inode)) {
298: iput(inode);
299: return -EROFS;
300: }
1.1.1.6 root 301: if ((current->euid == inode->i_uid && user == inode->i_uid &&
302: (in_group_p(group) || group == inode->i_gid)) ||
303: suser()) {
304: inode->i_uid = user;
305: inode->i_gid = group;
306: inode->i_dirt=1;
1.1 root 307: iput(inode);
1.1.1.6 root 308: return 0;
1.1 root 309: }
310: iput(inode);
1.1.1.6 root 311: return -EPERM;
1.1 root 312: }
313:
1.1.1.10! root 314: /*
! 315: * Note that while the flag value (low two bits) for sys_open means:
! 316: * 00 - read-only
! 317: * 01 - write-only
! 318: * 10 - read-write
! 319: * 11 - special
! 320: * it is changed into
! 321: * 00 - no permissions needed
! 322: * 01 - read-permission
! 323: * 10 - write-permission
! 324: * 11 - read-write
! 325: * for the internal routines (ie open_namei()/follow_link() etc). 00 is
! 326: * used by symlinks.
! 327: */
1.1 root 328: int sys_open(const char * filename,int flag,int mode)
329: {
1.1.1.4 root 330: struct inode * inode;
1.1 root 331: struct file * f;
332: int i,fd;
333:
334: for(fd=0 ; fd<NR_OPEN ; fd++)
335: if (!current->filp[fd])
336: break;
337: if (fd>=NR_OPEN)
1.1.1.7 root 338: return -EMFILE;
1.1 root 339: current->close_on_exec &= ~(1<<fd);
1.1.1.9 root 340: f = get_empty_filp();
341: if (!f)
1.1.1.7 root 342: return -ENFILE;
1.1.1.9 root 343: current->filp[fd] = f;
1.1.1.10! root 344: f->f_flags = flag;
! 345: if (f->f_mode = (flag+1) & O_ACCMODE)
! 346: flag++;
! 347: if (flag & (O_TRUNC | O_CREAT))
! 348: flag |= 2;
! 349: i = open_namei(filename,flag,mode,&inode,NULL);
! 350: if (i) {
1.1 root 351: current->filp[fd]=NULL;
1.1.1.9 root 352: f->f_count--;
1.1 root 353: return i;
354: }
1.1.1.10! root 355: if (flag & O_TRUNC)
! 356: if (inode->i_op && inode->i_op->truncate) {
! 357: inode->i_size = 0;
! 358: inode->i_op->truncate(inode);
! 359: }
! 360: if (!IS_RDONLY(inode)) {
! 361: inode->i_atime = CURRENT_TIME;
! 362: inode->i_dirt = 1;
! 363: }
1.1 root 364: f->f_inode = inode;
365: f->f_pos = 0;
1.1.1.6 root 366: f->f_reada = 0;
367: f->f_op = NULL;
368: if (inode->i_op)
369: f->f_op = inode->i_op->default_file_ops;
370: if (f->f_op && f->f_op->open)
371: if (i = f->f_op->open(inode,f)) {
1.1.1.4 root 372: iput(inode);
1.1.1.9 root 373: f->f_count--;
1.1.1.4 root 374: current->filp[fd]=NULL;
375: return i;
376: }
1.1 root 377: return (fd);
378: }
379:
380: int sys_creat(const char * pathname, int mode)
381: {
1.1.1.4 root 382: return sys_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
1.1 root 383: }
384:
1.1.1.10! root 385: static int close_fp(struct file *filp)
! 386: {
! 387: struct inode *inode;
1.1 root 388:
1.1.1.6 root 389: if (filp->f_count == 0) {
390: printk("Close: file count is 0\n");
391: return 0;
392: }
1.1.1.10! root 393: inode = filp->f_inode;
! 394: if (S_ISREG(inode->i_mode))
! 395: fcntl_remove_locks(current, filp);
1.1.1.6 root 396: if (filp->f_count > 1) {
397: filp->f_count--;
398: return 0;
399: }
400: if (filp->f_op && filp->f_op->release)
1.1.1.9 root 401: filp->f_op->release(inode,filp);
1.1.1.6 root 402: filp->f_count--;
1.1.1.9 root 403: filp->f_inode = NULL;
404: iput(inode);
1.1.1.6 root 405: return 0;
1.1 root 406: }
1.1.1.9 root 407:
1.1.1.10! root 408: int sys_close(unsigned int fd)
! 409: {
! 410: struct file * filp;
! 411:
! 412: if (fd >= NR_OPEN)
! 413: return -EINVAL;
! 414: current->close_on_exec &= ~(1<<fd);
! 415: if (!(filp = current->filp[fd]))
! 416: return -EINVAL;
! 417: current->filp[fd] = NULL;
! 418: return (close_fp (filp));
! 419: }
! 420:
! 421: /*
! 422: * This routine looks through all the process's and closes any
! 423: * references to the current processes tty. To avoid problems with
! 424: * process sleeping on an inode which has already been iput, anyprocess
! 425: * which is sleeping on the tty is sent a sigkill (It's probably a rogue
! 426: * process.) Also no process should ever have /dev/console as it's
! 427: * controlling tty, or have it open for reading. So we don't have to
! 428: * worry about messing with all the daemons abilities to write messages
! 429: * to the console. (Besides they should be using syslog.)
! 430: */
1.1.1.9 root 431: int sys_vhangup(void)
432: {
1.1.1.10! root 433: int i,j;
! 434: struct file *filep;
! 435: struct tty_struct *tty;
! 436: extern void kill_wait (struct wait_queue **q, int signal);
! 437: extern int kill_pg (int pgrp, int sig, int priv);
! 438:
! 439: if (!suser())
! 440: return -EPERM;
! 441: /* send the SIGHUP signal. */
! 442: kill_pg(current->pgrp, SIGHUP, 0);
! 443: /* See if there is a controlling tty. */
! 444: if (current->tty < 0)
! 445: return 0;
! 446:
! 447: for (i = 0; i < NR_TASKS; i++) {
! 448: if (task[i] == NULL)
! 449: continue;
! 450: for (j = 0; j < NR_OPEN; j++) {
! 451: filep = task[i]->filp[j];
! 452: if (!filep)
! 453: continue;
! 454: if (!S_ISCHR(filep->f_inode->i_mode))
! 455: continue;
! 456: if ((MAJOR(filep->f_inode->i_rdev) == 5 ||
! 457: MAJOR(filep->f_inode->i_rdev) == 4 ) &&
! 458: (MAJOR(filep->f_rdev) == 4 &&
! 459: MINOR(filep->f_rdev) == MINOR (current->tty))) {
! 460: /* so now we have found something to close. We
! 461: need to kill every process waiting on the
! 462: inode. */
! 463: task[i]->filp[j] = NULL;
! 464: kill_wait (&filep->f_inode->i_wait, SIGKILL);
! 465:
! 466: /* now make sure they are awake before we close the
! 467: file. */
! 468:
! 469: wake_up (&filep->f_inode->i_wait);
! 470:
! 471: /* finally close the file. */
! 472:
! 473: current->close_on_exec &= ~(1<<j);
! 474: close_fp (filep);
! 475: }
! 476: }
! 477: /* can't let them keep a reference to it around.
! 478: But we can't touch current->tty until after the
! 479: loop is complete. */
! 480:
! 481: if (task[i]->tty == current->tty && task[i] != current) {
! 482: task[i]->tty = -1;
! 483: }
! 484: }
! 485: /* need to do tty->session = 0 */
! 486: tty = TTY_TABLE(MINOR(current->tty));
! 487: tty->session = 0;
! 488: tty->pgrp = -1;
! 489: current->tty = -1;
! 490: return 0;
1.1.1.9 root 491: }
1.1.1.10! root 492:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.