This source file includes following definitions.
- sys_statfs
- sys_fstatfs
- do_truncate
- sys_truncate
- sys_ftruncate
- sys_utime
- sys_utimes
- sys_access
- sys_chdir
- sys_fchdir
- sys_chroot
- sys_fchmod
- sys_chmod
- sys_fchown
- sys_chown
- do_open
- sys_open
- sys_creat
- close_fp
- sys_close
- 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 #include <linux/mm.h>
20
21 #include <asm/segment.h>
22
23 asmlinkage int sys_statfs(const char * path, struct statfs * buf)
24 {
25 struct inode * inode;
26 int error;
27
28 error = verify_area(VERIFY_WRITE, buf, sizeof(struct statfs));
29 if (error)
30 return error;
31 error = namei(path,&inode);
32 if (error)
33 return error;
34 if (!inode->i_sb->s_op->statfs) {
35 iput(inode);
36 return -ENOSYS;
37 }
38 inode->i_sb->s_op->statfs(inode->i_sb, buf, sizeof(struct statfs));
39 iput(inode);
40 return 0;
41 }
42
43 asmlinkage int sys_fstatfs(unsigned int fd, struct statfs * buf)
44 {
45 struct inode * inode;
46 struct file * file;
47 int error;
48
49 error = verify_area(VERIFY_WRITE, buf, sizeof(struct statfs));
50 if (error)
51 return error;
52 if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
53 return -EBADF;
54 if (!(inode = file->f_inode))
55 return -ENOENT;
56 if (!inode->i_sb->s_op->statfs)
57 return -ENOSYS;
58 inode->i_sb->s_op->statfs(inode->i_sb, buf, sizeof(struct statfs));
59 return 0;
60 }
61
62 int do_truncate(struct inode *inode, unsigned long length)
63 {
64 int error;
65 struct iattr newattrs;
66
67 down(&inode->i_sem);
68 newattrs.ia_size = length;
69 newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
70 error = notify_change(inode, &newattrs);
71 if (!error) {
72
73 vmtruncate(inode, length);
74 if (inode->i_op && inode->i_op->truncate)
75 inode->i_op->truncate(inode);
76 }
77 up(&inode->i_sem);
78 return error;
79 }
80
81 asmlinkage int sys_truncate(const char * path, unsigned long length)
82 {
83 struct inode * inode;
84 int error;
85
86 error = namei(path,&inode);
87 if (error)
88 return error;
89 if (S_ISDIR(inode->i_mode)) {
90 iput(inode);
91 return -EACCES;
92 }
93 if ((error = permission(inode,MAY_WRITE)) != 0) {
94 iput(inode);
95 return error;
96 }
97 if (IS_RDONLY(inode)) {
98 iput(inode);
99 return -EROFS;
100 }
101 if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
102 iput(inode);
103 return -EPERM;
104 }
105 error = get_write_access(inode);
106 if (error) {
107 iput(inode);
108 return error;
109 }
110 error = locks_verify_area(FLOCK_VERIFY_WRITE, inode, NULL,
111 length < inode->i_size ? length : inode->i_size,
112 abs(inode->i_size - length));
113 if (error)
114 return error;
115 error = do_truncate(inode, length);
116 put_write_access(inode);
117 iput(inode);
118 return error;
119 }
120
121 asmlinkage int sys_ftruncate(unsigned int fd, unsigned long length)
122 {
123 struct inode * inode;
124 struct file * file;
125 int error;
126
127 if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
128 return -EBADF;
129 if (!(inode = file->f_inode))
130 return -ENOENT;
131 if (S_ISDIR(inode->i_mode) || !(file->f_mode & FMODE_WRITE))
132 return -EACCES;
133 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
134 return -EPERM;
135 error = locks_verify_area(FLOCK_VERIFY_WRITE, inode, file,
136 length < inode->i_size ? length : inode->i_size,
137 abs(inode->i_size - length));
138 if (error)
139 return error;
140 return do_truncate(inode, length);
141 }
142
143 #ifndef __alpha__
144
145
146
147
148
149
150
151
152
153
154
155
156 asmlinkage int sys_utime(char * filename, struct utimbuf * times)
157 {
158 int error;
159 struct inode * inode;
160 struct iattr newattrs;
161
162 error = namei(filename,&inode);
163 if (error)
164 return error;
165 if (IS_RDONLY(inode)) {
166 iput(inode);
167 return -EROFS;
168 }
169
170 newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;
171 if (times) {
172 error = verify_area(VERIFY_READ, times, sizeof(*times));
173 if (error) {
174 iput(inode);
175 return error;
176 }
177 newattrs.ia_atime = get_user(×->actime);
178 newattrs.ia_mtime = get_user(×->modtime);
179 newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
180 } else {
181 if ((error = permission(inode,MAY_WRITE)) != 0) {
182 iput(inode);
183 return error;
184 }
185 }
186 error = notify_change(inode, &newattrs);
187 iput(inode);
188 return error;
189 }
190
191 #endif
192
193
194
195
196
197 asmlinkage int sys_utimes(char * filename, struct timeval * utimes)
198 {
199 int error;
200 struct inode * inode;
201 struct iattr newattrs;
202
203 error = namei(filename,&inode);
204 if (error)
205 return error;
206 if (IS_RDONLY(inode)) {
207 iput(inode);
208 return -EROFS;
209 }
210
211 newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;
212 if (utimes) {
213 struct timeval times[2];
214 error = verify_area(VERIFY_READ, utimes, sizeof(times));
215 if (error) {
216 iput(inode);
217 return error;
218 }
219 memcpy_fromfs(×, utimes, sizeof(times));
220 newattrs.ia_atime = times[0].tv_sec;
221 newattrs.ia_mtime = times[1].tv_sec;
222 newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
223 } else {
224 if ((error = permission(inode,MAY_WRITE)) != 0) {
225 iput(inode);
226 return error;
227 }
228 }
229 error = notify_change(inode, &newattrs);
230 iput(inode);
231 return error;
232 }
233
234
235
236
237
238 asmlinkage int sys_access(const char * filename, int mode)
239 {
240 struct inode * inode;
241 int old_fsuid, old_fsgid;
242 int res;
243
244 if (mode != (mode & S_IRWXO))
245 return -EINVAL;
246 old_fsuid = current->fsuid;
247 old_fsgid = current->fsgid;
248 current->fsuid = current->uid;
249 current->fsgid = current->gid;
250 res = namei(filename,&inode);
251 if (!res) {
252 res = permission(inode, mode);
253 iput(inode);
254 }
255 current->fsuid = old_fsuid;
256 current->fsgid = old_fsgid;
257 return res;
258 }
259
260 asmlinkage int sys_chdir(const char * filename)
261 {
262 struct inode * inode;
263 int error;
264
265 error = namei(filename,&inode);
266 if (error)
267 return error;
268 if (!S_ISDIR(inode->i_mode)) {
269 iput(inode);
270 return -ENOTDIR;
271 }
272 if ((error = permission(inode,MAY_EXEC)) != 0) {
273 iput(inode);
274 return error;
275 }
276 iput(current->fs->pwd);
277 current->fs->pwd = inode;
278 return (0);
279 }
280
281 asmlinkage int sys_fchdir(unsigned int fd)
282 {
283 struct inode * inode;
284 struct file * file;
285 int error;
286
287 if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
288 return -EBADF;
289 if (!(inode = file->f_inode))
290 return -ENOENT;
291 if (!S_ISDIR(inode->i_mode))
292 return -ENOTDIR;
293 if ((error = permission(inode,MAY_EXEC)) != 0)
294 return error;
295 iput(current->fs->pwd);
296 current->fs->pwd = inode;
297 inode->i_count++;
298 return (0);
299 }
300
301 asmlinkage int sys_chroot(const char * filename)
302 {
303 struct inode * inode;
304 int error;
305
306 error = namei(filename,&inode);
307 if (error)
308 return error;
309 if (!S_ISDIR(inode->i_mode)) {
310 iput(inode);
311 return -ENOTDIR;
312 }
313 if (!fsuser()) {
314 iput(inode);
315 return -EPERM;
316 }
317 iput(current->fs->root);
318 current->fs->root = inode;
319 return (0);
320 }
321
322 asmlinkage int sys_fchmod(unsigned int fd, mode_t mode)
323 {
324 struct inode * inode;
325 struct file * file;
326 struct iattr newattrs;
327
328 if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
329 return -EBADF;
330 if (!(inode = file->f_inode))
331 return -ENOENT;
332 if (IS_RDONLY(inode))
333 return -EROFS;
334 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
335 return -EPERM;
336 if (mode == (mode_t) -1)
337 mode = inode->i_mode;
338 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
339 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
340 inode->i_dirt = 1;
341 return notify_change(inode, &newattrs);
342 }
343
344 asmlinkage int sys_chmod(const char * filename, mode_t mode)
345 {
346 struct inode * inode;
347 int error;
348 struct iattr newattrs;
349
350 error = namei(filename,&inode);
351 if (error)
352 return error;
353 if (IS_RDONLY(inode)) {
354 iput(inode);
355 return -EROFS;
356 }
357 if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
358 iput(inode);
359 return -EPERM;
360 }
361 if (mode == (mode_t) -1)
362 mode = inode->i_mode;
363 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
364 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
365 inode->i_dirt = 1;
366 error = notify_change(inode, &newattrs);
367 iput(inode);
368 return error;
369 }
370
371 asmlinkage int sys_fchown(unsigned int fd, uid_t user, gid_t group)
372 {
373 struct inode * inode;
374 struct file * file;
375 struct iattr newattrs;
376 int error;
377
378 if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
379 return -EBADF;
380 if (!(inode = file->f_inode))
381 return -ENOENT;
382 if (IS_RDONLY(inode))
383 return -EROFS;
384 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
385 return -EPERM;
386 if (user == (uid_t) -1)
387 user = inode->i_uid;
388 if (group == (gid_t) -1)
389 group = inode->i_gid;
390 newattrs.ia_mode = inode->i_mode;
391 newattrs.ia_uid = user;
392 newattrs.ia_gid = group;
393 newattrs.ia_valid = ATTR_UID | ATTR_GID | ATTR_CTIME;
394
395
396
397 if (user != inode->i_uid && (inode->i_mode & S_ISUID)) {
398 newattrs.ia_mode &= ~S_ISUID;
399 newattrs.ia_valid |= ATTR_MODE;
400 }
401
402
403
404
405
406
407 if (group != inode->i_gid &&
408 ((inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP))) {
409 newattrs.ia_mode &= ~S_ISGID;
410 newattrs.ia_valid |= ATTR_MODE;
411 }
412 inode->i_dirt = 1;
413 if (inode->i_sb && inode->i_sb->dq_op) {
414 inode->i_sb->dq_op->initialize(inode, -1);
415 if (inode->i_sb->dq_op->transfer(inode, &newattrs, 0))
416 return -EDQUOT;
417 error = notify_change(inode, &newattrs);
418 if (error)
419 inode->i_sb->dq_op->transfer(inode, &newattrs, 1);
420 } else
421 error = notify_change(inode, &newattrs);
422 return error;
423 }
424
425 asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group)
426 {
427 struct inode * inode;
428 int error;
429 struct iattr newattrs;
430
431 error = lnamei(filename,&inode);
432 if (error)
433 return error;
434 if (IS_RDONLY(inode)) {
435 iput(inode);
436 return -EROFS;
437 }
438 if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
439 iput(inode);
440 return -EPERM;
441 }
442 if (user == (uid_t) -1)
443 user = inode->i_uid;
444 if (group == (gid_t) -1)
445 group = inode->i_gid;
446 newattrs.ia_mode = inode->i_mode;
447 newattrs.ia_uid = user;
448 newattrs.ia_gid = group;
449 newattrs.ia_valid = ATTR_UID | ATTR_GID | ATTR_CTIME;
450
451
452
453 if (user != inode->i_uid && (inode->i_mode & S_ISUID)) {
454 newattrs.ia_mode &= ~S_ISUID;
455 newattrs.ia_valid |= ATTR_MODE;
456 }
457
458
459
460
461
462
463 if (group != inode->i_gid &&
464 ((inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP))) {
465 newattrs.ia_mode &= ~S_ISGID;
466 newattrs.ia_valid |= ATTR_MODE;
467 }
468 inode->i_dirt = 1;
469 if (inode->i_sb->dq_op) {
470 inode->i_sb->dq_op->initialize(inode, -1);
471 if (inode->i_sb->dq_op->transfer(inode, &newattrs, 0))
472 return -EDQUOT;
473 error = notify_change(inode, &newattrs);
474 if (error)
475 inode->i_sb->dq_op->transfer(inode, &newattrs, 1);
476 } else
477 error = notify_change(inode, &newattrs);
478 iput(inode);
479 return(error);
480 }
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496 int do_open(const char * filename,int flags,int mode)
497 {
498 struct inode * inode;
499 struct file * f;
500 int flag,error,fd;
501
502 f = get_empty_filp();
503 if (!f)
504 return -ENFILE;
505 f->f_flags = flag = flags;
506 f->f_mode = (flag+1) & O_ACCMODE;
507 if (f->f_mode)
508 flag++;
509 if (flag & (O_TRUNC | O_CREAT))
510 flag |= 2;
511 error = open_namei(filename,flag,mode,&inode,NULL);
512 if (error)
513 goto cleanup_file;
514 if (f->f_mode & FMODE_WRITE) {
515 error = get_write_access(inode);
516 if (error)
517 goto cleanup_inode;
518 }
519
520 f->f_inode = inode;
521 f->f_pos = 0;
522 f->f_reada = 0;
523 f->f_op = NULL;
524 if (inode->i_op)
525 f->f_op = inode->i_op->default_file_ops;
526 if (f->f_op && f->f_op->open) {
527 error = f->f_op->open(inode,f);
528 if (error)
529 goto cleanup_all;
530 }
531 f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
532
533
534
535
536
537
538 for(fd = 0; fd < NR_OPEN && fd < current->rlim[RLIMIT_NOFILE].rlim_cur; fd++) {
539 if (!current->files->fd[fd]) {
540 current->files->fd[fd] = f;
541 FD_CLR(fd,¤t->files->close_on_exec);
542 return fd;
543 }
544 }
545 error = -EMFILE;
546 if (f->f_op && f->f_op->release)
547 f->f_op->release(inode,f);
548 cleanup_all:
549 if (f->f_mode & FMODE_WRITE)
550 put_write_access(inode);
551 cleanup_inode:
552 iput(inode);
553 cleanup_file:
554 f->f_count--;
555 return error;
556 }
557
558 asmlinkage int sys_open(const char * filename,int flags,int mode)
559 {
560 char * tmp;
561 int error;
562
563 error = getname(filename, &tmp);
564 if (error)
565 return error;
566 error = do_open(tmp,flags,mode);
567 putname(tmp);
568 return error;
569 }
570
571 #ifndef __alpha__
572
573
574
575
576
577 asmlinkage int sys_creat(const char * pathname, int mode)
578 {
579 return sys_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
580 }
581
582 #endif
583
584 int close_fp(struct file *filp)
585 {
586 struct inode *inode;
587
588 if (filp->f_count == 0) {
589 printk("VFS: Close: file count is 0\n");
590 return 0;
591 }
592 inode = filp->f_inode;
593 if (inode)
594 locks_remove_locks(current, filp);
595 if (filp->f_count > 1) {
596 filp->f_count--;
597 return 0;
598 }
599 if (filp->f_op && filp->f_op->release)
600 filp->f_op->release(inode,filp);
601 filp->f_count--;
602 filp->f_inode = NULL;
603 if (filp->f_mode & FMODE_WRITE)
604 put_write_access(inode);
605 iput(inode);
606 return 0;
607 }
608
609 asmlinkage int sys_close(unsigned int fd)
610 {
611 struct file * filp;
612
613 if (fd >= NR_OPEN)
614 return -EBADF;
615 FD_CLR(fd, ¤t->files->close_on_exec);
616 if (!(filp = current->files->fd[fd]))
617 return -EBADF;
618 current->files->fd[fd] = NULL;
619 return (close_fp (filp));
620 }
621
622
623
624
625
626 asmlinkage int sys_vhangup(void)
627 {
628 if (!suser())
629 return -EPERM;
630
631 if (current->tty)
632 tty_vhangup(current->tty);
633 return 0;
634 }