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 inode->i_dirt = 1;
247 return notify_change(inode);
248 }
249
250 int sys_chmod(const char * filename, mode_t mode)
251 {
252 struct inode * inode;
253 int error;
254
255 error = namei(filename,&inode);
256 if (error)
257 return error;
258 if ((current->euid != inode->i_uid) && !suser()) {
259 iput(inode);
260 return -EPERM;
261 }
262 if (IS_RDONLY(inode)) {
263 iput(inode);
264 return -EROFS;
265 }
266 inode->i_mode = (mode & 07777) | (inode->i_mode & ~07777);
267 inode->i_dirt = 1;
268 error = notify_change(inode);
269 iput(inode);
270 return error;
271 }
272
273 int sys_fchown(unsigned int fd, uid_t user, gid_t group)
274 {
275 struct inode * inode;
276 struct file * file;
277
278 if (fd >= NR_OPEN || !(file = current->filp[fd]))
279 return -EBADF;
280 if (!(inode = file->f_inode))
281 return -ENOENT;
282 if (IS_RDONLY(inode))
283 return -EROFS;
284 if (user == (uid_t) -1)
285 user = inode->i_uid;
286 if (group == (gid_t) -1)
287 group = inode->i_gid;
288 if ((current->euid == inode->i_uid && user == inode->i_uid &&
289 (in_group_p(group) || group == inode->i_gid)) ||
290 suser()) {
291 inode->i_uid = user;
292 inode->i_gid = group;
293 inode->i_dirt = 1;
294 return notify_change(inode);
295 }
296 return -EPERM;
297 }
298
299 int sys_chown(const char * filename, uid_t user, gid_t group)
300 {
301 struct inode * inode;
302 int error;
303
304 error = lnamei(filename,&inode);
305 if (error)
306 return error;
307 if (IS_RDONLY(inode)) {
308 iput(inode);
309 return -EROFS;
310 }
311 if (user == (uid_t) -1)
312 user = inode->i_uid;
313 if (group == (gid_t) -1)
314 group = inode->i_gid;
315 if ((current->euid == inode->i_uid && user == inode->i_uid &&
316 (in_group_p(group) || group == inode->i_gid)) ||
317 suser()) {
318 inode->i_uid = user;
319 inode->i_gid = group;
320 inode->i_dirt = 1;
321 error = notify_change(inode);
322 iput(inode);
323 return error;
324 }
325 iput(inode);
326 return -EPERM;
327 }
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343 int sys_open(const char * filename,int flag,int mode)
344 {
345 struct inode * inode;
346 struct file * f;
347 int i,fd;
348
349 for(fd=0 ; fd<NR_OPEN ; fd++)
350 if (!current->filp[fd])
351 break;
352 if (fd>=NR_OPEN)
353 return -EMFILE;
354 FD_CLR(fd,¤t->close_on_exec);
355 f = get_empty_filp();
356 if (!f)
357 return -ENFILE;
358 current->filp[fd] = f;
359 f->f_flags = flag;
360 f->f_mode = (flag+1) & O_ACCMODE;
361 if (f->f_mode)
362 flag++;
363 if (flag & (O_TRUNC | O_CREAT))
364 flag |= 2;
365 i = open_namei(filename,flag,mode,&inode,NULL);
366 if (i) {
367 current->filp[fd]=NULL;
368 f->f_count--;
369 return i;
370 }
371 if (flag & O_TRUNC) {
372 inode->i_size = 0;
373 if (inode->i_op && inode->i_op->truncate)
374 inode->i_op->truncate(inode);
375 if ((i = notify_change(inode))) {
376 iput(inode);
377 current->filp[fd] = NULL;
378 f->f_count--;
379 return i;
380 }
381 }
382 if (!IS_RDONLY(inode)) {
383 inode->i_atime = CURRENT_TIME;
384 inode->i_dirt = 1;
385 }
386 f->f_inode = inode;
387 f->f_pos = 0;
388 f->f_reada = 0;
389 f->f_op = NULL;
390 if (inode->i_op)
391 f->f_op = inode->i_op->default_file_ops;
392 if (f->f_op && f->f_op->open) {
393 i = f->f_op->open(inode,f);
394 if (i) {
395 iput(inode);
396 f->f_count--;
397 current->filp[fd]=NULL;
398 return i;
399 }
400 }
401 f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
402 return (fd);
403 }
404
405 int sys_creat(const char * pathname, int mode)
406 {
407 return sys_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
408 }
409
410 int close_fp(struct file *filp)
411 {
412 struct inode *inode;
413
414 if (filp->f_count == 0) {
415 printk("Close: file count is 0\n");
416 return 0;
417 }
418 inode = filp->f_inode;
419 if (S_ISREG(inode->i_mode))
420 fcntl_remove_locks(current, filp);
421 if (filp->f_count > 1) {
422 filp->f_count--;
423 return 0;
424 }
425 if (filp->f_op && filp->f_op->release)
426 filp->f_op->release(inode,filp);
427 filp->f_count--;
428 filp->f_inode = NULL;
429 iput(inode);
430 return 0;
431 }
432
433 int sys_close(unsigned int fd)
434 {
435 struct file * filp;
436
437 if (fd >= NR_OPEN)
438 return -EINVAL;
439 FD_CLR(fd, ¤t->close_on_exec);
440 if (!(filp = current->filp[fd]))
441 return -EINVAL;
442 current->filp[fd] = NULL;
443 return (close_fp (filp));
444 }
445
446
447
448
449
450
451
452 static void kill_wait(struct wait_queue **q, int sig)
453 {
454 struct wait_queue *next;
455 struct wait_queue *tmp;
456 struct task_struct *p;
457
458 if (!q || !(next = *q))
459 return;
460 do {
461 tmp = next;
462 next = tmp->next;
463 if ((p = tmp->task) != NULL)
464 send_sig (sig, p , 1);
465 } while (next && next != *q);
466 }
467
468
469
470
471
472
473
474
475
476
477
478 int sys_vhangup(void)
479 {
480 int j;
481 struct task_struct ** process;
482 struct file *filep;
483 struct inode *inode;
484 struct tty_struct *tty;
485 extern int kill_pg (int pgrp, int sig, int priv);
486
487 if (!suser())
488 return -EPERM;
489
490 kill_pg(current->pgrp, SIGHUP, 0);
491
492 if (current->tty < 0)
493 return 0;
494
495 for (process = task + 0; process < task + NR_TASKS; process++) {
496 for (j = 0; j < NR_OPEN; j++) {
497 if (!*process)
498 break;
499 if (!(filep = (*process)->filp[j]))
500 continue;
501 if (!(inode = filep->f_inode))
502 continue;
503 if (!S_ISCHR(inode->i_mode))
504 continue;
505 if ((MAJOR(inode->i_rdev) == 5 ||
506 MAJOR(inode->i_rdev) == 4 ) &&
507 (MAJOR(filep->f_rdev) == 4 &&
508 MINOR(filep->f_rdev) == MINOR (current->tty))) {
509
510
511
512 (*process)->filp[j] = NULL;
513 kill_wait (&inode->i_wait, SIGKILL);
514
515
516
517
518 wake_up (&inode->i_wait);
519
520
521
522 FD_CLR(j, &(*process)->close_on_exec);
523 close_fp (filep);
524 }
525 }
526
527
528
529
530 if (*process && (*process)->tty == current->tty && *process != current) {
531 (*process)->tty = -1;
532 }
533 }
534
535 tty = TTY_TABLE(MINOR(current->tty));
536 if (tty) {
537 tty->session = 0;
538 tty->pgrp = -1;
539 current->tty = -1;
540 }
541 return 0;
542 }
543