This source file includes following definitions.
- sys_ustat
- sys_statfs
- sys_fstatfs
- sys_truncate
- sys_ftruncate
- sys_utime
- sys_access
- sys_chdir
- sys_chroot
- sys_fchmod
- sys_chmod
- sys_fchown
- sys_chown
- sys_open
- sys_creat
- close_fp
- sys_close
- kill_wait
- sys_vhangup
1
2
3
4
5
6
7 #include <linux/vfs.h>
8 #include <linux/types.h>
9 #include <linux/utime.h>
10 #include <linux/errno.h>
11 #include <linux/fcntl.h>
12 #include <linux/stat.h>
13 #include <linux/string.h>
14 #include <linux/sched.h>
15 #include <linux/kernel.h>
16 #include <linux/signal.h>
17 #include <linux/tty.h>
18 #include <linux/time.h>
19
20 #include <asm/segment.h>
21
22 extern void fcntl_remove_locks(struct task_struct *, struct file *);
23
24 struct file_operations * chrdev_fops[MAX_CHRDEV] = {
25 NULL,
26 };
27
28 struct file_operations * blkdev_fops[MAX_BLKDEV] = {
29 NULL,
30 };
31
32 int sys_ustat(int dev, struct ustat * ubuf)
33 {
34 return -ENOSYS;
35 }
36
37 int sys_statfs(const char * path, struct statfs * buf)
38 {
39 struct inode * inode;
40 int error;
41
42 verify_area(buf, sizeof(struct statfs));
43 error = namei(path,&inode);
44 if (error)
45 return error;
46 if (!inode->i_sb->s_op->statfs) {
47 iput(inode);
48 return -ENOSYS;
49 }
50 inode->i_sb->s_op->statfs(inode->i_sb, buf);
51 iput(inode);
52 return 0;
53 }
54
55 int sys_fstatfs(unsigned int fd, struct statfs * buf)
56 {
57 struct inode * inode;
58 struct file * file;
59
60 verify_area(buf, sizeof(struct statfs));
61 if (fd >= NR_OPEN || !(file = current->filp[fd]))
62 return -EBADF;
63 if (!(inode = file->f_inode))
64 return -ENOENT;
65 if (!inode->i_sb->s_op->statfs)
66 return -ENOSYS;
67 inode->i_sb->s_op->statfs(inode->i_sb, buf);
68 return 0;
69 }
70
71 int sys_truncate(const char * path, unsigned int length)
72 {
73 struct inode * inode;
74 int error;
75
76 error = namei(path,&inode);
77 if (error)
78 return error;
79 if (S_ISDIR(inode->i_mode) || !permission(inode,MAY_WRITE)) {
80 iput(inode);
81 return -EACCES;
82 }
83 if (IS_RDONLY(inode)) {
84 iput(inode);
85 return -EROFS;
86 }
87 inode->i_size = length;
88 if (inode->i_op && inode->i_op->truncate)
89 inode->i_op->truncate(inode);
90 inode->i_atime = inode->i_mtime = CURRENT_TIME;
91 inode->i_dirt = 1;
92 error = notify_change(inode);
93 iput(inode);
94 return error;
95 }
96
97 int sys_ftruncate(unsigned int fd, unsigned int length)
98 {
99 struct inode * inode;
100 struct file * file;
101
102 if (fd >= NR_OPEN || !(file = current->filp[fd]))
103 return -EBADF;
104 if (!(inode = file->f_inode))
105 return -ENOENT;
106 if (S_ISDIR(inode->i_mode) || !(file->f_mode & 2))
107 return -EACCES;
108 inode->i_size = length;
109 if (inode->i_op && inode->i_op->truncate)
110 inode->i_op->truncate(inode);
111 inode->i_atime = inode->i_mtime = CURRENT_TIME;
112 inode->i_dirt = 1;
113 return notify_change(inode);
114 }
115
116
117
118
119
120 int sys_utime(char * filename, struct utimbuf * times)
121 {
122 struct inode * inode;
123 long actime,modtime;
124 int error;
125
126 error = namei(filename,&inode);
127 if (error)
128 return error;
129 if (IS_RDONLY(inode)) {
130 iput(inode);
131 return -EROFS;
132 }
133 if (times) {
134 if ((current->euid != inode->i_uid) && !suser()) {
135 iput(inode);
136 return -EPERM;
137 }
138 actime = get_fs_long((unsigned long *) ×->actime);
139 modtime = get_fs_long((unsigned long *) ×->modtime);
140 } else {
141 if ((current->euid != inode->i_uid) &&
142 !permission(inode,MAY_WRITE)) {
143 iput(inode);
144 return -EACCES;
145 }
146 actime = modtime = CURRENT_TIME;
147 }
148 inode->i_atime = actime;
149 inode->i_mtime = modtime;
150 inode->i_ctime = CURRENT_TIME;
151 inode->i_dirt = 1;
152 error = notify_change(inode);
153 iput(inode);
154 return error;
155 }
156
157
158
159
160
161 int sys_access(const char * filename,int mode)
162 {
163 struct inode * inode;
164 int res, i_mode;
165
166 mode &= 0007;
167 res = namei(filename,&inode);
168 if (res)
169 return res;
170 i_mode = res = inode->i_mode & 0777;
171 iput(inode);
172 if (current->uid == inode->i_uid)
173 res >>= 6;
174 else if (in_group_p(inode->i_gid))
175 res >>= 3;
176 if ((res & 0007 & mode) == mode)
177 return 0;
178
179
180
181
182
183
184 if ((!current->uid) &&
185 (!(mode & 1) || (i_mode & 0111)))
186 return 0;
187 return -EACCES;
188 }
189
190 int sys_chdir(const char * filename)
191 {
192 struct inode * inode;
193 int error;
194
195 error = namei(filename,&inode);
196 if (error)
197 return error;
198 if (!S_ISDIR(inode->i_mode)) {
199 iput(inode);
200 return -ENOTDIR;
201 }
202 if (!permission(inode,MAY_EXEC)) {
203 iput(inode);
204 return -EACCES;
205 }
206 iput(current->pwd);
207 current->pwd = inode;
208 return (0);
209 }
210
211 int sys_chroot(const char * filename)
212 {
213 struct inode * inode;
214 int error;
215
216 error = namei(filename,&inode);
217 if (error)
218 return error;
219 if (!S_ISDIR(inode->i_mode)) {
220 iput(inode);
221 return -ENOTDIR;
222 }
223 if (!suser()) {
224 iput(inode);
225 return -EPERM;
226 }
227 iput(current->root);
228 current->root = inode;
229 return (0);
230 }
231
232 int sys_fchmod(unsigned int fd, mode_t mode)
233 {
234 struct inode * inode;
235 struct file * file;
236
237 if (fd >= NR_OPEN || !(file = current->filp[fd]))
238 return -EBADF;
239 if (!(inode = file->f_inode))
240 return -ENOENT;
241 if ((current->euid != inode->i_uid) && !suser())
242 return -EPERM;
243 if (IS_RDONLY(inode))
244 return -EROFS;
245 inode->i_mode = (mode & 07777) | (inode->i_mode & ~07777);
246 if (!suser() && !in_group_p(inode->i_gid))
247 inode->i_mode &= ~S_ISGID;
248 inode->i_ctime = CURRENT_TIME;
249 inode->i_dirt = 1;
250 return notify_change(inode);
251 }
252
253 int sys_chmod(const char * filename, mode_t mode)
254 {
255 struct inode * inode;
256 int error;
257
258 error = namei(filename,&inode);
259 if (error)
260 return error;
261 if ((current->euid != inode->i_uid) && !suser()) {
262 iput(inode);
263 return -EPERM;
264 }
265 if (IS_RDONLY(inode)) {
266 iput(inode);
267 return -EROFS;
268 }
269 inode->i_mode = (mode & 07777) | (inode->i_mode & ~07777);
270 if (!suser() && !in_group_p(inode->i_gid))
271 inode->i_mode &= ~S_ISGID;
272 inode->i_ctime = CURRENT_TIME;
273 inode->i_dirt = 1;
274 error = notify_change(inode);
275 iput(inode);
276 return error;
277 }
278
279 int sys_fchown(unsigned int fd, uid_t user, gid_t group)
280 {
281 struct inode * inode;
282 struct file * file;
283
284 if (fd >= NR_OPEN || !(file = current->filp[fd]))
285 return -EBADF;
286 if (!(inode = file->f_inode))
287 return -ENOENT;
288 if (IS_RDONLY(inode))
289 return -EROFS;
290 if (user == (uid_t) -1)
291 user = inode->i_uid;
292 if (group == (gid_t) -1)
293 group = inode->i_gid;
294 if ((current->euid == inode->i_uid && user == inode->i_uid &&
295 (in_group_p(group) || group == inode->i_gid)) ||
296 suser()) {
297 inode->i_uid = user;
298 inode->i_gid = group;
299 inode->i_ctime = CURRENT_TIME;
300 inode->i_dirt = 1;
301 return notify_change(inode);
302 }
303 return -EPERM;
304 }
305
306 int sys_chown(const char * filename, uid_t user, gid_t group)
307 {
308 struct inode * inode;
309 int error;
310
311 error = lnamei(filename,&inode);
312 if (error)
313 return error;
314 if (IS_RDONLY(inode)) {
315 iput(inode);
316 return -EROFS;
317 }
318 if (user == (uid_t) -1)
319 user = inode->i_uid;
320 if (group == (gid_t) -1)
321 group = inode->i_gid;
322 if ((current->euid == inode->i_uid && user == inode->i_uid &&
323 (in_group_p(group) || group == inode->i_gid)) ||
324 suser()) {
325 inode->i_uid = user;
326 inode->i_gid = group;
327 inode->i_ctime = CURRENT_TIME;
328 inode->i_dirt = 1;
329 error = notify_change(inode);
330 iput(inode);
331 return error;
332 }
333 iput(inode);
334 return -EPERM;
335 }
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351 int sys_open(const char * filename,int flag,int mode)
352 {
353 struct inode * inode;
354 struct file * f;
355 int i,fd;
356
357 for(fd=0 ; fd<NR_OPEN ; fd++)
358 if (!current->filp[fd])
359 break;
360 if (fd>=NR_OPEN)
361 return -EMFILE;
362 FD_CLR(fd,¤t->close_on_exec);
363 f = get_empty_filp();
364 if (!f)
365 return -ENFILE;
366 current->filp[fd] = f;
367 f->f_flags = flag;
368 f->f_mode = (flag+1) & O_ACCMODE;
369 if (f->f_mode)
370 flag++;
371 if (flag & (O_TRUNC | O_CREAT))
372 flag |= 2;
373 i = open_namei(filename,flag,mode,&inode,NULL);
374 if (i) {
375 current->filp[fd]=NULL;
376 f->f_count--;
377 return i;
378 }
379 if (flag & O_TRUNC) {
380 inode->i_size = 0;
381 if (inode->i_op && inode->i_op->truncate)
382 inode->i_op->truncate(inode);
383 if ((i = notify_change(inode))) {
384 iput(inode);
385 current->filp[fd] = NULL;
386 f->f_count--;
387 return i;
388 }
389 }
390 if (!IS_RDONLY(inode)) {
391 inode->i_atime = CURRENT_TIME;
392 inode->i_dirt = 1;
393 }
394 f->f_inode = inode;
395 f->f_pos = 0;
396 f->f_reada = 0;
397 f->f_op = NULL;
398 if (inode->i_op)
399 f->f_op = inode->i_op->default_file_ops;
400 if (f->f_op && f->f_op->open) {
401 i = f->f_op->open(inode,f);
402 if (i) {
403 iput(inode);
404 f->f_count--;
405 current->filp[fd]=NULL;
406 return i;
407 }
408 }
409 f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
410 return (fd);
411 }
412
413 int sys_creat(const char * pathname, int mode)
414 {
415 return sys_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
416 }
417
418 int close_fp(struct file *filp)
419 {
420 struct inode *inode;
421
422 if (filp->f_count == 0) {
423 printk("Close: file count is 0\n");
424 return 0;
425 }
426 inode = filp->f_inode;
427 if (inode && S_ISREG(inode->i_mode))
428 fcntl_remove_locks(current, filp);
429 if (filp->f_count > 1) {
430 filp->f_count--;
431 return 0;
432 }
433 if (filp->f_op && filp->f_op->release)
434 filp->f_op->release(inode,filp);
435 filp->f_count--;
436 filp->f_inode = NULL;
437 iput(inode);
438 return 0;
439 }
440
441 int sys_close(unsigned int fd)
442 {
443 struct file * filp;
444
445 if (fd >= NR_OPEN)
446 return -EINVAL;
447 FD_CLR(fd, ¤t->close_on_exec);
448 if (!(filp = current->filp[fd]))
449 return -EINVAL;
450 current->filp[fd] = NULL;
451 return (close_fp (filp));
452 }
453
454
455
456
457
458
459
460 static void kill_wait(struct wait_queue **q, int sig)
461 {
462 struct wait_queue *next;
463 struct wait_queue *tmp;
464 struct task_struct *p;
465
466 if (!q || !(next = *q))
467 return;
468 do {
469 tmp = next;
470 next = tmp->next;
471 if ((p = tmp->task) != NULL)
472 send_sig (sig, p , 1);
473 } while (next && next != *q);
474 }
475
476
477
478
479
480
481
482
483
484
485
486 int sys_vhangup(void)
487 {
488 int j;
489 struct task_struct ** process;
490 struct file *filep;
491 struct inode *inode;
492 struct tty_struct *tty;
493 extern int kill_pg (int pgrp, int sig, int priv);
494
495 if (!suser())
496 return -EPERM;
497
498 if (current->tty < 0)
499 return 0;
500
501 tty = TTY_TABLE(current->tty);
502 if (tty && tty->pgrp > 0)
503 kill_pg(tty->pgrp, SIGHUP, 0);
504
505 for (process = task + 0; process < task + NR_TASKS; process++) {
506 for (j = 0; j < NR_OPEN; j++) {
507 if (!*process)
508 break;
509 if (!(filep = (*process)->filp[j]))
510 continue;
511 if (!(inode = filep->f_inode))
512 continue;
513 if (!S_ISCHR(inode->i_mode))
514 continue;
515 if ((MAJOR(inode->i_rdev) == 5 ||
516 MAJOR(inode->i_rdev) == 4 ) &&
517 (MAJOR(filep->f_rdev) == 4 &&
518 MINOR(filep->f_rdev) == MINOR (current->tty))) {
519
520
521
522 (*process)->filp[j] = NULL;
523 kill_wait (&inode->i_wait, SIGKILL);
524
525
526
527
528 wake_up (&inode->i_wait);
529
530
531
532 FD_CLR(j, &(*process)->close_on_exec);
533 close_fp (filep);
534 }
535 }
536
537
538
539
540 if (*process && (*process)->tty == current->tty && *process != current) {
541 (*process)->tty = -1;
542 }
543 }
544
545 tty = TTY_TABLE(MINOR(current->tty));
546 if (tty) {
547 tty->session = 0;
548 tty->pgrp = -1;
549 current->tty = -1;
550 }
551 return 0;
552 }
553